Suivi de température et humidité

Mon objectif était de pouvoir suivre et consulter la température des différentes pièces de l’appartement en temps quasi-réel à la fois sur une tablette fixée au mur et depuis un smartphone en dehors de l’appartement.

Ma solution repose sur plusieurs sondes disposées dans chaque pièce qui captent périodiquement la température et le taux d’humidité puis transmettent ces données à un serveur distant. Ce dernier conserve les données et héberge une application web permettant de les consulter via un smartphone ou un ordinateur. Au travers de webservices il met également ces données à disposition d’une tablette qui les affiche en continu.

Les températures et taux d'humidité sont affichées dans un encart en bas à droite
Les températures et taux d’humidité sont affichées dans un encart en bas à droite
Affichage des températures et taux d'humidité de chaque pièce
Affichage des températures et taux d’humidité
Suivi de l'évolution
Suivi de l’évolution

Les sondes de température et d’humidité

Matériel

Pour le choix du matériel des sondes 3 critères étaient importants :

  1. La capacité à définir la période de capture de la température et des taux d’humidité (toutes les 10 minutes) ;
  2. Pas d’émission radio (car elles sont actives toute la journée dans les chambres des enfants) ;
  3. Le coût.

Je me suis ainsi orienté vers le matériel suivant pour chacune des sondes :

  • Un Raspberry Pi Zero pour l’unité centrale (il dispose d’une connectique bien plus limitée que le Pi 3 mais il est également nettement moins cher (environ 5€ contre 35€) ;
  • Une sonde DHT22 qui permet de capter la température et le taux d’humidité. Cette sonde présente l’avantage d’être numérique et semblait la plus fiable dans cette gamme de prix (~3€) ;
  • Une résistance de 4,7KΩ (<1€) ;
  • Une carte réseau Ethernet en USB (car le Pi Zero ne dispose pas de connectique réseau) (~2,5€) ;
  • Un convertisseur micro-USB -> USB (~1€) ;
  • Le nécessaire pour le Pi Zero (carte SD, adaptateur secteur) ;
  • Un boitier pour le Pi Zero (non indispensable mais c’est plus propre) ;
  • Un adaptateur CPL car mes pièces ne disposent pas de prises ethernet et je ne souhaitais pas de Wi-Fi.

L’adaptateur CPL est de loin l’élément le plus coûteux, sans celui-ci l’ensemble tourne autour de 25€ par sonde.

Raspberry Pi Zero
Raspberry Pi Zero
sonde DHT22
sonde DHT22
carte réseau Ethernet en USB
carte réseau Ethernet en USB
convertisseur micro-USB - USB
convertisseur micro-USB – USB
Boitier du Pi Zero
Boitier du Pi Zero

Montage

Le montage est relativement simple, il consiste à souder la sonde sur le Raspberry.  Il faut prévoir une longueur de fil suffisante en fonction de l’emplacement de la sonde. Pour ma part, je pose le Raspberry au sol près de la prise électrique et je place la sonde à environ 1m du sol et non exposée aux courants d’air pour obtenir des valeurs de températures et de taux d’humidité les plus fiables possibles.

Voici le montage à réaliser :

Montage Raspberry Pi DHT22

Les branchements à effectuer sont :

  • La broche 1 de la sonde vers une broche de 3,3v du Pi Zero ;
  • La broche 2 de la sonde vers une broche d’entrée du Pi Zero (j’ai choisi la broche 4) ;
  • La broche 3 de la sonde n’est pas utilisée ;
  • La broche 4 de la sonde vers une broche terre du Pi Zero.
GPIO du Raspberry Pi Zero
GPIO du Raspberry Pi Zero

Logiciel

Il existe plusieurs distributions pour Raspberry, j’ai choisi l’officielle Raspbian basée sur Debian qui suffit largement à mes besoins.

Pour récupérer périodiquement la température et le taux d’humidité, j’ai choisi d’écrire une application en python reposant sur la bibliothèque d’Adafruit.

Première étape l’installation des pré-requis :

sudo apt-get update
sudo apt-get install build-essential python-dev python-openssl

Puis récupération de la bibliothèque :

git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT

Avant d’aller plus loin un hack est nécessaire :

A l’exécution la bibliothèque d’Adafruit détermine la version du Raspberry (Pi 1/Pi Zero ou Pi 2) sur la base de la version du processeur. Or il existe sur le marché plusieurs versions du Pi Zero (avec différentes versions du processeur). (Pour ma part j’ai deux versions différentes parmi mes 6 Pi Zero). Il est ainsi nécessaire de patcher la bibliothèque pour que le test fonctionne avec sa version du Pi Zero.

Il faut tout d’abord déterminer la version du processeur de son Pi Zero :

cat /proc/cpuinfo

Et chercher la ligne Hardware.

Sur l’un des miens, j’obtiens BCM2835.

pi@pi1:~ $ cat /proc/cpuinfo
processor       : 0
model name      : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 997.08
Features        : half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : BCM2835
Revision        : 900093
Serial          : 000000004fc34801

Il faut ensuite éditer le fichier Adafruit_DHT/platform_detect.py pour indiquer cette version à la ligne 97 (if match.group(1) == ‘BCM2835’:) :

def pi_version():
     """Detect the version of the Raspberry Pi.  Returns either 1, 2 or
     None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+),
     Raspberry Pi 2 (model B+), or not a Raspberry Pi.
     """
     # Check /proc/cpuinfo for the Hardware field value.
     # 2708 is pi 1
     # 2709 is pi 2
     # Anything else is not a pi.
     with open('/proc/cpuinfo', 'r') as infile:
         cpuinfo = infile.read()
     # Match a line like 'Hardware   : BCM2709'
     match = re.search('^Hardware\s+:\s+(\w+)

On peut maintenant compiler la bibliothèque :

sudo python setup.py install

Il reste ensuite a écrire un programme lancé périodiquement par un cron (pour ma part toutes les 10 minutes) qui interroge la sonde puis envoie les données au serveur. Afin de ne pas perdre de valeurs en cas de coupure réseau, si le programme ne parvient pas à envoyer les données au serveur, il les stocke temporairement dans un fichier pour les réémettre dès que la connexion fonctionne à nouveau.

#!/usr/bin/python
import sys
import os
from time import localtime, strftime
import Adafruit_DHT
import requests

# Reference de la sonde (DHT22), a ne pas modifier
SENSOR = 22

# Numero de la broche sur laquelle la sonde est soudee
PIN = 4

# Identifiant de la piece dont les donnees sont capturees
ROOM = ''

# Racine de l'url du webservice du serveur destinataires des donnees capturees
BASE_URL = 'http://XXXXXXXX/'

# Fichier utilise pour stocker les donnees n'ayant pu etre transmise au serveur
DATAS_NOT_SENT_FILE = '/home/pi/error_sonde'

# Nombre de tentative maximum de capture
NUMBER_OF_TRIES = 4

current_date = strftime("%Y-%m-%d %H:%M:%S", localtime())
formatted_humidity = ''
formatted_temperature = ''

# Interroge la sonde pour obtenir la temperature et le taux d'humidite courante
# Si necessaire, reessaye 15 fois en attendant 2 secondes entre chaque tentatives
humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN)

# La capture des donnees peut ne pas fonctionner (cas rare), au besoin tente 'nbTries' fois
i = 1
while (humidity is None or temperature is None) and i < NUMBER_OF_TRIES:
    humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN)
    i = i + 1

# Si les donnees ont pu etre capturees
if humidity is not None and temperature is not None:
    # Formattage des donnees pour transmission au serveur
    formatted_humidity = '{0:0.0f}'.format(humidity)
    formatted_temperature = '{0:0.0f}'.format(temperature*100)
    url = BASE_URL + 'Releve/' + ROOM + '/' + formatted_temperature + '/' + formatted_humidity
    print(current_date + ';' + ROOM + ';' + formatted_temperature + ';' + formatted_humidity + ';' + str(temperature) + ';' + str(humidity) + ';' + url)

    try:
        # Envoi des donnees collectees au serveur
        requests.get(url)

        # Si l'envoi a fonctionne, on envoie egalement les donnees qui n'avaient pu etre transmises lors de precedentes captures
        if os.path.exists(DATAS_NOT_SENT_FILE):
            if os.path.getsize(DATAS_NOT_SENT_FILE) > 0 :
                datas = [('file', ('file', open(DATAS_NOT_SENT_FILE, 'rb'),'text'))]
                requests.post(BASE_URL + 'ReleveBulk', files=datas)

                # Vidage du contenu du fichier d'erreur
                f = open(DATAS_NOT_SENT_FILE, 'w')
                f.close()
    except:
        print("erreur lors de l'envoi des releves")

        # En cas d'erreur lors de l'envoi des donnees, celles-ci sont conservees dans le fichier des erreurs afin d'etre transmises des que la connexion est a nouveau fonctionnelle
        f = open(DATAS_NOT_SENT_FILE, 'a')
        f.write(current_date + ';' + ROOM + ';' + formatted_temperature + ';' + formatted_humidity + '\n')
        f.close()

Pour la maintenance logicielle des Raspberry, j’utilise ansible qui permet d’effectuer des opérations groupées via SSH sur l’ensemble des 6 Raspberry. Je l’utilise essentiellement pour la mise à jour du système et le déploiement d’une nouvelle version du programme python.

Le serveur

Le serveur doit réceptionner les données brutes transmises par les sondes (température, humidité) pour :

  • Stocker ces données ;
  • Notifier la tablette que de nouvelles valeurs sont disponibles ;
  • Mettre à disposition de la tablette la dernière valeur de température et de taux d’humidité pour chacune des pièces ;
  • Héberger l’application web pour smartphone.

Les flux ressemblent à cela :

Ces webservices reposent sur la bibliothèque python flask pour réceptionner les valeurs brutes transmises par les sondes et pour répondre aux requêtes de la tablette 10′′. La couche de stockage repose sur une base de données relationnelle MySQL. Un webservice est dédié au superviseur nagios me permettant d’être notifié si une sonde ne transmet plus ses données. Cela m’évite de superviser directement les sondes (qui générerait du trafic réseau pour chaque sonde), seule la disponibilité de l’information depuis le serveur m’intéresse.

Les interfaces utilisateurs

Tablette 10′′

Je souhaitais disposer d’un écran fixé au mur affichant en permanence les températures dans les différentes pièces. J’ai choisi un Raspberry PI 3 avec un écran 10′’ tactile. Un affichage plus petit de type LCD aurait pu convenir mais je souhaitais profiter de cet écran pour afficher d’autres informations. Aujourd’hui il me permet également d’apporter d’autres services :

  • Afficher un tableau blanc (éditable depuis une appli iPhone) ;
  • Afficher les listes de courses et permettre d’ajouter des articles parmi les plus ajoutés ;
  • Ajouter un minuteur de cuisson qui notifie par SMS ;
  • Afficher la météo du jour et de la semaine ;
  • Afficher les temps de cuisson du cuit-vapeur ;
  • Permettre de réactiver le wifi quand il est coupé par la programmation horaire ;
  • Afficher le matin en semaine les prochains passages du bus pour la crèche ;
  • etc.
Les températures et taux d'humidité sont affichées dans un encart en bas à droite
Les températures et taux d’humidité sont affichées dans un encart en bas à droite

Tout comme les sondes, le Raspberry Pi 3 derrière cette tablette tourne sur Raspbian. Ce dernier est configuré pour lancer au démarrage un programme (toujours en python) apportant les différents services listés ci-dessus. Pour l’IHM je n’ai pas trouvé de bibliothèque python suffisamment souple pour le rendu que j’avais en tête. J’ai donc utilisé la bibliothèque « bas niveau » Tkinter sur laquelle repose ma version « maison » de widget et de widget manager.

Je me suis posé la question de la consommation électrique induite par cette tablette qui reste allumée. La consommation du Raspberry est très limitée et reste raisonnable. N’ayant pas l’information concernant l’écran, j’ai configuré le X window manager pour que l’écran se mette en veille au bout de 10 minutes d’inactivité et se rallume au toucher. Via une tâche cron cette veille est désactivée (l’écran reste allumé) le matin du réveil au départ et le soir du retour au coucher.

Application mobile

Je souhaitais pouvoir également consulter les températures en dehors de l’appartement.  Plutôt que de développer une application native j’ai choisi de le faire au travers d’une application web ce qui me permet d’y accéder simplement depuis n’importe quel navigateur et même au travers d’une application iPhone en l’installant sous forme de web app.

Un minimum d’HTML et de CSS permet d’afficher les températures et taux d’humidité courants de chaque pièce.

Je souhaitais pouvoir également suivre l’évolution des données, j’ai utilisé pour cela la bibliothèque Highstock suffisamment paramétrable pour obtenir le rendu que je souhaitais.

Application smartphone de suivi de température

Références des Sources utilisées

https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/software-install-updated

https://www.highcharts.com/products/highstock/

http://flask.pocoo.org

https://www.ansible.com/

Je suis preneur de vos retours, suggestions ou questions via le formulaire de commentaire. Et n’hésitez pas à partager si vous avez également réalisé un système de suivi de température.

10 réactions sur “ Suivi de température et humidité ”

  1. Symon Réponse

    Hello,

    Super projet, je suis fan et esthétique en plus.
    quels retours ou améliorations faites depuis 2 ans ?

    Perso je vais me lancer pour monitorer l’hygrométrie de mes pièces avant changement de fenêtres.

    • Clément Caillaud Auteur ArticleRéponse

      Merci pour le retour, j’ai effectué des améliorations (principalement cosmétiques). J’ai mis à jour les captures de l’article.
      N’hésitez pas à faire un retour à votre tour quand vous aurez démarré le monitorage de l’hygrométrie de vos pièces.

  2. Pierre-Jean Réponse

    Bonjour,

    Merci pour ce tutoriel. Je trouve votre application mobile très jolie. Est-elle téléchargeable quelque part ?

    Cordialement,
    Pierre-Jean V.

    • Clément Caillaud Auteur ArticleRéponse

      Bonjour Pierre-Jean,

      Merci pour ce retour. L’application mobile n’est pas téléchargeable publiquement car je n’ai pas industrialisé le système pour qu’il puisse être déployé dans un autre contexte.

  3. Christophe D Réponse

    Salut,
    Super projet. Je me lance (bien que novice) pour répliquer tout ça.
    J’ai cherché des RPI0 mais c’est impossible d’en trouver. Je me suis donc rabattu sur des Zero-W mais on est à 20€ la bête..
    Petite question : est-il possible de plugger plusieurs DHTT22 sur un RPI0 ? (en mettant évidemment un câblage plus long pour qu’ils soit dans une autre pièce 🙂 ).
    Merci en tous cas d’avoir partagé ce pj inspirant !
    Christophe

    • Clément Caillaud Auteur ArticleRéponse

      Merci Christophe pour le commentaire !
      J’ai pris les PI0 sur Pimoroni, on ne peut en prendre qu’un à la fois (avec ainsi les frais de port à chaque fois) mais rien n’empêche de commander plusieurs fois.
      Concernant le branchement de plusieurs DHT22 je m’étais posé la question. Je ne l’ai pas réalisé mais je pense qu’on peut en brancher plusieurs en utilisant d’autres broches que la n°4 du GPIO. Attention à la longueur des fils reliant la sonde au PI0, j’ai lu que d’après des tests empiriques celle-ci est limitée. A tester donc avant sur breadboard…

  4. elvenhax Réponse

    Voila je suis en sonde DHT22 sur un raspberry depuis plusieurs mois deja. Par contre je constate que je ne recupere pas tout le temps les valeurs de la sonde.

  5. Houda Réponse

    d’abord merci beaucoup pour vos soutiens, ça m’aide vraiment au niveau de mon projet de fin d’étude
    SVP pouvez-vous de m’envoyer les tableaux de la base de données ??
    Merci d’avance

  6. JeanLouis Réponse

    Bonjour,

    En premier lieu merci pour cet article qui résume bien ce que je veux réaliser.
    Je dispose de 3 caves à vin sur 3 sites différents Je recherchais de sondes thermomètre fonctionnant en WiFi genre Xiaomi mais du coup il me faudrait un Hub pour chaque capteur 🙁 et le coût s’envole…

    Du coup si je peux disposer sur chaque site d’un RPI0 avec 2 sondes (une à l’intérieur et l’autre a l’extérieur du frigo cave) en reprenant votre design j’obtiendrais l’historique des valeurs… et éventuellement en cas de dysfonctionnement (montée de la Temp ou Hydro en dehors de valeurs prédéterminées) envoi d’un mail pour me prévenir.

    Par contre je suis une quiche en développement RPI… alors j’ai besoin d’aide sur la partie serveur et App mobile. Je me doute du travail que représente ce projet, alors je suis preneur de tout renseignement ou tout partage.

    Merci d’avance

    • Clément Caillaud Auteur ArticleRéponse

      Bonjour Jean-Louis,

      Le fonctionnement que vous décrivez semble tout à fait réalisable. J’ai indiqué ici un exemple de ce qui peut être fait en python.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *