Chez moi, j'ai un potager. Souvent, qui dit potager, dit serre pour faire pousser les plants. Comme je suis un peu bidouilleur/geek, j'avais pour projet de connaître la température intérieure de la serre, et celle extérieure tant qu'à faire. Grâce à ce projet, j'ai pu mettre en place des sondes DS18B20 sur un Raspberry Pi et créer un frontal Web pour la consultation des données. Voyons comment j'ai procédé.

Le projet

Comme je le disais en intro, j'ai un potager dans lequel je cultive tous les ans "quelques" légumes (tomates, courgettes, pommes de terre, poivrons, oignons, et j'en passe...). Je fais mes plants moi-même. C'est-à-dire que je sème les graines, ça pousse, je plante et je récolte (je résume très grossièrement ^^).

Il y a 3 ans, je me suis construit une serre basique, avec quelques bouts de bois et du polycarbonate (le truc qu'on voit au fond sur la première photo, à gauche de la cuve d'eau). Cependant, mon but est de connaître la température intérieure de la serre pour savoir quand l'ouvrir, afin que les plants n'étouffent pas.
Une page Web représentant des graphiques des températures des sondes (température intérieure de la serre et extérieure) va être créée de toute pièce également ! Comme ça, je prends mon smartphone, je vais sur le site dédié, et je consulte les températures relevées et les graphiques.

Vous allez me dire que ce genre d'interface Web existe déjà. Je le sais bien, mais j'aime bien tout créer de A à Z !

Le matériel

J'avais un Raspberry Pi 2 en rab, qui me servait à faire des tests avant l'achat de la version 3, maintenant dédiée à RecalBox ;)

Si vous ne connaissez pas le principe du Raspberry Pi, pour faire simple, c'est un mini ordinateur de la taille d'un portefeuille, qui permet d'interagir avec des périphériques externes, reliés par des fils électriques ou des ondes.

Pour pouvoir récupérer les températures souhaitées, il me fallait des sondes étanches. Mon choix s'est vite porté sur les sondes Dallas DS18B20, trouvables à environ 10 euros les 5. Elles sont pleinement compatibles avec le Raspberry Pi, les résultats sont fiables et la mise en oeuvre assez simple. Leur plage de mesure s'étend de -55°C à +125°C, de précision ±0,5 °C entre -10°C et +85°C. Largement suffisant pour ce que je veux en faire !

Pour pouvoir relier les sondes au Raspberry Pi, il faut des câbles électriques et une plaque de prototypage (breadboard en anglais) si on veut faire ça correctement, du moins proprement. Egalement, une résistance de valeur 4.7 kΩ sera nécessaire (jaune, violet, rouge).

Le tout (Raspberry, câbles, plaque de prototypage) sera placé dans une boîte de dérivation étanche (17x14 cm), accrochée à un muret abrité, sous un hangar. La serre étant de l'autre côté du mur du hangar.

N'ayant pas tiré de câble réseau entre ma maison et le hangar situé à plus de 50m, le Pi sera connecté en Wifi à mon réseau local. J'ai en stock un dongle USB/Wifi qui fonctionne avec le Raspberry. Cependant, tout ce monde sera placé très loin de ma Box (plus de 50m, sous un hangar)... Après quelques tests, la portée du Wifi s'arrêtant à 7-8m de la boîte dans laquelle se trouve le Pi, ce dernier n'arrive donc pas à capter le signal...
Deux solutions s'offrent à moi : déplacer la boîte ou placer une antenne Wifi déportée, reliée au Pi. C'est cette dernière méthode que j'ai choisie. J'ai acheté une antenne Wifi, reliée à un câble avec fiche SMA qui est lui-même relié à un dongle USB. J'ai acheté un câble de 5m pour rallonger celui livré avec l'antenne. Du coup, le Pi arrive à dialoguer avec le réseau local :)

Voici une commande Bash permettant d'avoir la qualité du signal Wifi :

watch -n 1 "awk 'NR==3 {print \"Signal strength = \" \$3 \"00 %\"}''' /proc/net/wireless"

Montage de la sonde

Je pars du principe que vous avez installé une distribution Linux sur votre Raspberry Pi (Raspbian Lite pour ma part).

Voici le schéma de branchement d'une sonde DS18B20 pour un Raspberry Pi 2 :

Il faut relier :

  • fil rouge de la sonde sur le pin #1 (3.3v)
  • fil noir de la sonde sur le pin #6 (Ground / masse)
  • fil jaune de la sonde sur le pin #7 (appelé GPIO4)

La résistance de 4.7 kΩ (jaune, violet, rouge) doit être placée sur les fils rouge et jaune.

La sonde ne fonctionnera pas tout de suite sur le système. Pour cela, il faut faire quelques manipulations pour activer des modules dans Linux qui permettent de faire communiquer la sonde.

Ajoutez ces deux lignes à la fin du fichier /etc/modules :

w1-gpio
w1-therm

Exécutez ensuite ces deux commandes (une par une) pour activer ces deux modules :

modprobe w1-gpio
modprobe w1-therm

Dans le fichier /boot/config.txt, rajoutez cette ligne qui permet de corriger un problème lié aux mises à jour du Pi :

dtoverlay=w1-gpio

Redémarrez ensuite votre Pi.

Pour les tests, j'ai relié la sonde à la plaque via un connecteur WAGO (équivalent d'un domino).

Pour lire les valeurs de la sonde, il suffit de se rendre dans le dossier /sys/bus/w1/devices/ et de rentrer ensuite dans le dossier commençant par 28-. Enfin, lisez simplement le fichier w1_slave avec la commande cat :

Vérifiez que vous avez bien YES de présent. Si non, votre Raspberry Pi n'arrive pas à communiquer avec votre sonde.
La température est exprimée en degrés Celsius, multipliée par 1000. Ici, la température est de 20.312°C. Elle est représenté sous la forme t=20312, en fin de fichier.

Pour plus de confort, j'ai mis à disposition un petit script en Python (inspiré de celui d'Adafruit) permettant d'afficher les températures des sondes reliées à un Raspberry Pi. Très simple, il parcourt le dossier contenant les sondes et retourne leur température.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import glob, os, sys
from datetime import datetime

def get_temp(device_file):
    temp_c = 0

    if os.path.isfile(device_file):
        f = open(device_file, 'r')
        lines = f.readlines()
        f.close()

        if lines[0].strip()[-3:] == 'YES':
            equals_pos = lines[1].find('t=')

            if equals_pos != -1:
                temp_string = lines[1][equals_pos+2:]
                temp_c = float(temp_string) / 1000.0

    return temp_c

base_dir = '/sys/bus/w1/devices/'
devices_folder = glob.glob(base_dir + '28*')

for device_dir in devices_folder:
    device = os.path.basename(device_dir)

    temp = round(get_temp(device_dir+'/w1_slave'), 1)

print device+' : '+str(temp)

Maintenant que j'arrive à lire les données transmises par la sonde, je soude les fils de la sonde à des câbles semi-rigides, qui seront eux connectés à la plaque de prototypage :

Un p'tit coup de gaine thermoretractable :

Et encore une gaine :

Le Pi et sa plaque vont prendre place dans une boîte de dérivation électrique. J'ai mis une bande de velcro sur une petite plaquette de bois pour sortir le Pi facilement (sans avoir à retirer des vis) :

L'antenne Wifi (oui, ok, c'est un peu fixé à l'arrache :D) :

La sonde présente dans la serre ressort légèrement :

Tandis que celle pour la température extérieure est comme ceci :

Consultation des données

Je peux donc maintenant avoir les températures des sondes à l'instant T en me connectant au Raspberry en SSH. Cependant, je veux mieux, et surtout plus pratique. Je veux avoir un historique des données sous forme de graphique, le tout accessible depuis l'extérieur (Internet).

J'ai donc créé une application Web en PHP, hébergée sur un serveur externe (par souci de disponibilité et étant donné ma super connexion Internet, je n'ai pas fait le choix de l'auto-héberger). En parallèle, j'ai écrit un script en Python sur le Pi, afin qu'il puisse envoyer toutes les heures les valeurs des sondes via un appel d'une API de mon application Web. Ces données sont enregistrées dans une base sqlite et sont donc traitées sur l'appli Web pour affichage.

J'aurai très bien pu installer un Domoticz ou équivalent pour historiser les températures, mais j'aime bien créer des p'tites applis :)

Script Python : envoi des données

Le script du Pi est assez simple, il est très proche de celui présenté plus haut. Je recherche les devices connectés au Pi, en filtrant par ceux commençant par 28-, qui correspond aux sondes branchées.

Pour chaque sonde, je récupère la température via une lecture du fichier /w1_slave (fonction get_temp) et un petit parsage (valeur après le t=). Enfin, j'envoie à l'API de mon application Web le numéro de la sonde, la température relevée et la date.

Ce script est appelé toutes les heures via une simple tâche cron.

0 * * * * /chemin/vers/le/script/sensors.py

Voici le script utilisé :

#!/usr/bin/python
# -*- coding: utf-8 -*-

import glob, requests, os, sys
from datetime import datetime

session = requests.Session()

RASPI_SENSORS_URL = "https://nom.de.domaine.fr/"
API_KEY = "xxx"

def get_temp(device_file):
    temp_c = 0

    if os.path.isfile(device_file):
        f = open(device_file, 'r')
        lines = f.readlines()
        f.close()

        if lines[0].strip()[-3:] == 'YES':
            equals_pos = lines[1].find('t=')

            if equals_pos != -1:
                temp_string = lines[1][equals_pos+2:]
                temp_c = float(temp_string) / 1000.0

    return temp_c

base_dir = '/sys/bus/w1/devices/'
devices_folder = glob.glob(base_dir + '28*')

for device_dir in devices_folder:
    device = os.path.basename(device_dir)

    temp = round(get_temp(device_dir+'/w1_slave'), 1)

    #print device+' : '+str(temp)

    # POST send
    date = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')

    post_data = {'key': API_KEY, 'sensor': device, 'value': temp, 'date': date}

    post_request = session.post(url=RASPI_SENSORS_URL+'api.php', data=post_data)

Application Web : consultation des températures relevées

L'application Web est du fait maison. Elle est en PHP et utilise le mini framework PureCSS pour la partie design. Les graphiques sont gérés par amCharts et jQuery.

Toutes les heures, le script Python envoie donc les relevés des températures des sondes à une API simpliste développée sur l'appli, qui fait tout un tas de contrôles pour enfin enregistrer les températures dans sa base SQLite (qui a un nom aléatoire, au passage, pour la sécurité).

L'outil dispose d'une partie administration donnant la possibilité de créer des sondes (nom, n° de la sonde reliée au Raspberry, couleur, ...), elles-mêmes rangées dans des groupes. J'ai donc un groupe nommé "Potager", dans lequel j'ai mes 2 sondes (extérieure et celle dans la serre). Je pourrai très bien avoir un autre Raspberry Pi (ou autre) dans la maison avec d'autres sondes de températures dont les valeurs seraient transmises à l'application Web pour historisation. Ces sondes seraient alors rangées dans un groupe Maison par exemple.

Egalement, tout un tas de paramètres sont modifiables tels que : la clé d'API pour le dialogue entre le Pi et le serveur Web (qui est d'ailleurs générée aléatoirement à l'installation), la durée du cache des graphiques, le nombre d'entrées à afficher pour la timeline, ...

Avec le temps, les données de la base deviennent importantes et les temps de génération des graphiques s'allongent. J'ai mis en place du cache et également la possibilité de paramétrer une période à afficher.

L'application Web est disponible dans son entièreté sur le dépôt Github.

Voici plusieurs captures d'écran de l'application Web.

Formulaire d'installation :

L'accueil, version publique, avec les dernières températures relevées et le graphique :

L'accueil mais une fois connecté, avec les menus d'administration qui s'activent :

Le formulaire de connexion :

La liste des différentes sondes enregistrées :

Le formulaire de modification d'une sonde :

La liste des groupes de sondes :

Les différents paramètres modifiables :

Problématiques rencontrées

Lors de la mise en place du projet, j'ai rencontré principalement deux soucis. Le premier était la portée du signal WiFi du dongle branché sur le Raspberry Pi. Comme dit au début de l'article, le Pi étant à plus de 50m de distance de ma Freebox, ça fait un peu long... J'ai résolu ce problème avec une antenne WiFi déportée et un câble de 5m.

Egalement, la longueur du câble de la sonde pour la température de la serre était trop court. Après quelques recherches, j'ai décidé de rallonger le câble avec quelques mètres d'un câble réseau qui ne me servait plus. Deux soudures et quelques centimètres de gaines thermorétractables après, mon câble de sonde était rallongé et fonctionnait parfaitement !

Evolutions à envisager

L'installation du Raspberry Pi et des sondes a été fait au printemps 2016. Après plus de deux années de fonctionnement, les résultats sont plus que satisfaisants mais plusieurs évolutions pourraient être réalisées pour gagner en confort.

En effet, la serre se trouve tout au bout de mon jardin. Lors de la période des semis en serre et des débuts des chaleurs l'après-midi et des fraîcheurs la nuit, je dois donc ouvrir la serre le matin avant de partir au boulot, tout en sachant que la température n'est pas idéale pour les futurs plants mais la chaleur de l'après-midi me rend obligatoire cette tâche. Si je n'ouvre pas la serre le matin, la température à l'intérieur peut vite dépasser les 50°C ! J'ai d'ailleurs écrit un petit script Python qui m'envoie une alerte Pushbullet si la température de la serre est supérieure à 45°C ;)

L'idéal serait donc de mettre en place un système de bras motorisés par des servos-moteurs, contrôlés par le Raspberry ou un Arduino. Dès qu'il fait plus de x degrés dans la serre et en extérieur, on ouvre la serre. Idem pour la fermeture.

De plus, un capteur d'humidité et de luminosité pourraient être installés pour gagner en points de contrôle pour le déclenchement de l'ouverture / fermeture de la serre.

Enfin, un système d'arrosage goutte à goutte déclenché par une pompe reliée à ma cuve d'eau de pluie pourrait combler ma fainéantise utile de bidouilleur :)

Conclusion

Voilà, après quelques bricolages et développements, j'ai la température extérieure et celle de la serre directement sur mon smartphone, quand je veux :) Pour vraiment quelques euros et un peu de bricolage pas bien sorcier, c'est vraiment efficace !

Le Raspberry Pi est vraiment un objet fantastique qui a vraiment révolutionné le monde de la domotique, robotique et automatisme en général !