Introduction
Voici un article qui rejoint un peu les deux grandes thématiques de ce blog : la cuisine et la tech.
Il s’agit de construire un capteur de température et d’humidité pour une cave de séchage pour les salaisons.
Les objectifs :
- être compact,
- être relativement peu cher,
- disposer d’une historisation des données,
- avoir un impact minime sur le capteur (en l’occurrence un Raspberry Pi),
- réutiliser des briques logicielles standards et maintenues (pas envie de redévelopper ou réutiliser un vieux script),
- mettre en place des alarmes en cas de dépassement de seuil.
Les composants
Le capteur
- Un Raspberry Pi Zero WH (Wireless + Headers) (https://www.raspberrypi.com/products/raspberry-pi-zero-w/),
- Un capteur de température et d’humidité SHT-30 disposant d’un câble de 1M (https://www.adafruit.com/product/4099),
- Une alimentation USB,
- Une extension pour les headers afin de connecter plus simplement les câbles du connecteur (https://thepihut.com/products/mini-terminal-breakout-board-for-raspberry-pi),
Il pourrait être intéressant de creuser la construction d’un HAT spécifique avec les composants suivants :
- Headers femelle
- Morceau de board
- Fils
Le serveur
- Un serveur Debian avec Docker,
- Un container avec le service Thingsboard installé (voir l’article #6 − Services avec Docker & Compose).
Installation du système
-
Télécharger la dernière image de Raspberry Pi OS Lite depuis le site de Raspberry Pi : https://www.raspberrypi.com/software/operating-systems/
-
Copier l’image disque sur une carte mémoire :
$ sudo dd bs=4M if=Téléchargements/2021-05-07-raspios-buster-armhf-lite.img of=/dev/mmcblk0 conv=fsync -
Avant de remettre la carte SD dans le RPi0, nous allons activer le wifi et le service SSH :
- Pour le service SSH, il suffit de créer un fichier vide nommé
sshdans la partitionboot:$ touch /run/media/brice/boot/ssh - Pour le wifi, il faut créer le fichier suivant (toujours dans la partition
boot) :Et y ajouter les lignes suivantes, en adaptant$ vim /run/media/brice/boot/wpa_supplicant.confYOURSSID&YOURPASSWORDcountry=FR ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="YOURSSID" scan_ssid=1 psk="YOURPASSWORD" key_mgmt=WPA-PSK } - Générer un mot de passe pour la création du premier utilisateur :
echo 'mypassword' | openssl passwd -6 -stdin - Créer le fichier
userconf.txt(toujours dans la partitionboot) :username:myencryptedpassword
- Pour le service SSH, il suffit de créer un fichier vide nommé
-
Placer la carte SD dans le RPi0 et le brancher. Patienter quelques secondes pour qu’il s’allume.
-
Se connecter en SSH
-
Vérifier la présence de mises à jour et les installer :
$ sudo apt update && sudo apt upgrade -
Installer
vim:$ sudo apt install vim -
Changer du nom du serveur :
$ sudo vim /etc/hosts $ sudo vim /etc/hostname $ sudo hostname viper
Câblage
Le schéma de câblage est le suivant :

Ce schéma utilise le capteur SHT31 (dont le SHT-30 est une variante avec câble et protections).
On retrouve les connectiques suivantes :
| Couleur | Fonction |
|---|---|
| Rouge/Marron | VCC/VIN (3-5VDC) |
| Noir | Ground |
| Jaune | Clock/SCL |
| Vert/Bleu | Data/SDA |
D’après la documentation, les câbles data et clock peuvent parfois être inversés, donc ne pas hésiter à tester les 2 si vous ne recevez aucune information.
TODO : mettre une photo du câblage réel.
Capture des données
Installation
Pour interagir avec le capteur SHT-30 nous allons utiliser les bibliothèques CircuitPython & Blinka.
-
Installation de
pip&setuptools:$ sudo apt-get install python3-pip $ sudo pip3 install --upgrade setuptools -
Installation de CircuitPython & Blinka :
sudo pip3 install --upgrade adafruit-python-shell wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py sudo python3 raspi-blinka.py(En fonction de votre version de Python par défaut, le script vous demandera de confirmer le changement de la version : 2.x vers 3.x)
This script configures your Raspberry Pi and installs Blinka RASPBERRY_PI_ZERO_W detected. Updating System Packages [...] DONE. Settings take effect on next boot. REBOOT NOW? [Y/n] Y Reboot started...À la fin de l’installation (qui prend quelques minutes), il propose de redémarrer le Raspberry Pi Zero, ce qu’il faut accepter.
-
Après le redémarrage, installer la bibliothèque SHT31D (https://github.com/adafruit/Adafruit_CircuitPython_SHT31D) :
$ sudo pip3 install adafruit-circuitpython-sht31d
Tests de capture
Afin de tester la bonne installation des bibliothèques précédentes, il est possible d’exécuter les commandes suivantes dans un shell Python :
import board
import busio
import adafruit_sht31d
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_sht31d.SHT31D(i2c)
print('Humidity: {0}%'.format(sensor.relative_humidity))
print('Temperature: {0}C'.format(sensor.temperature))
Les premières lignes importent les modules nécessaires et initialisent la connexion I2C avec le capteur.
Les 2 dernières lignes lisent les valeurs et les affiches.
Voici le résultat :
Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import board
>>> import busio
>>> import adafruit_sht31d
>>> i2c = busio.I2C(board.SCL, board.SDA)
>>> sensor = adafruit_sht31d.SHT31D(i2c)
>>> print('Humidity: {0}%'.format(sensor.relative_humidity))
Humidity: 63.834592202639804%
>>> print('Temperature: {0}C'.format(sensor.temperature))
Temperature: 18.294804303044174C
Un script d’exemple (pour lire et afficher les valeurs toutes les 2 sec.) est également disponible sur le repository GitHub du driver SHT31D.
$ wget https://github.com/adafruit/Adafruit_CircuitPython_SHT31D/blob/main/examples/sht31d_simpletest.py
$ python sht31d_simpletest.py
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Sensor Heater status = True
Sensor Heater status = False
Temperature: 18.7 C
Humidity: 67.6 %
Temperature: 18.1 C
Humidity: 67.1 %
...
Intégration avec Thingsboard
L’objectif de tout cela n’étant pas d’afficher les valeurs en continu dans un terminal, nous allons intégrer le capteur dans Thingsboard pour qu’il historise les données (et plein d’autres choses que nous verrons plus tard).
Dans Thingsboard
-
Aller dans “Devices”, ajouter un nouveau device en cliquant sur le signe + (en haut à droite).
-
Donner un nom (1) et cliquer sur
Credentialsen bas à droite de la pop-up :
-
Ajouter un crédentiel (1), renseigner le jeton d’accès (2) (à générer soi-même, et à noter, car il sera utile plus tard), et cliquer sur
Add(toujours en bas à droite) :
-
Votre device est désormais ajouté à Thingsboard.
Sur le Raspberry Pi Zero
La plupart des prérequis ont déjà été installés précédemment, mais il reste à installer la bibliothèque paho-mqtt pour permettre à notre script de discuter avec le service MQTT de Thingsboard :
$ sudo pip3 install paho-mqtt
Créer le repertoire scripts dans le home de l’utilisateur :
$ mkdir ~/scripts
Et enfin, créer le script sht30_thingsboard.py :
import os
import time
import sys
import board
import adafruit_sht31d
import paho.mqtt.client as mqtt
import json
THINGSBOARD_HOST = '<serveur mqtt>'
ACCESS_TOKEN = '<token thingsboard du device>'
# Data capture and upload interval in seconds.
INTERVAL=15
# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C()
sensor = adafruit_sht31d.SHT31D(i2c)
sensor_data = {'temperature': 0, 'humidity': 0}
next_reading = time.time()
client = mqtt.Client()
# Set access token
client.username_pw_set(ACCESS_TOKEN)
# Connect to ThingsBoard using default MQTT port and 60 seconds keepalive interval
client.connect(THINGSBOARD_HOST, 1883, 60)
client.loop_start()
try:
while True:
humidity = round(sensor.relative_humidity,2)
temperature = round(sensor.temperature,2)
print(u"Temperature: {:g}\u00b0C, Humidity: {:g}%".format(temperature, humidity))
sensor_data['temperature'] = temperature
sensor_data['humidity'] = humidity
# Sending humidity and temperature data to ThingsBoard
client.publish('v1/devices/me/telemetry', json.dumps(sensor_data), 1)
next_reading += INTERVAL
sleep_time = next_reading-time.time()
if sleep_time > 0:
time.sleep(sleep_time)
except KeyboardInterrupt:
pass
client.loop_stop()
client.disconnect()
Il faudra bien évidemment penser à modifier les lignes suivantes (au début du script) pour y ajouter vos valeurs :
THINGSBOARD_HOST = '<serveur mqtt>' ACCESS_TOKEN = '<token thingsboard du device>'Et éventuellement la fréquence de lecture (en secondes) :
INTERVAL=15
Vous pouvez désormais lancer le script manuellement pour vérifier son bon fonctionnement :
$ python sht30_thingsboard.py
Temperature: 17.97°C, Humidity: 68.13%
Temperature: 17.94°C, Humidity: 68.08%
...
Vous devriez retrouver les valeurs remontées dans la télémétrie (1) du device créé précédement dans Thingsboard :

Automatisation
Afin de lire en continu les données sans avoir un shell ouvert, nous allons mettre en place un service systemd (dans l’environnement utilisateur) pour le script précédent.
-
Activer les instances utilisateurs
systemdau démarrage (et non à l’ouverture de session) :$ sudo loginctl enable-linger brice -
Ajouter les lignes suivantes pour affecter les variables
XDG_RUNTIME_DIRetDBUS_SESSION_BUS_ADDRESSmanuellement dans le.bashrcde votre utilisateur (normalement elles le sont automatiquement à l’ouverture de session) :export XDG_RUNTIME_DIR="/run/user/$UID" export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" -
Créer le répertoire pour les services
systemdutilisateur :$ mkdir -p ~/.config/systemd/user/ -
Créer le service
~/.config/systemd/user/sensor.service:[Unit] Description=Sensor service After=multi-user.target [Service] Type=simple Restart=always ExecStart=python3 /home/brice/scripts/sht30_thingsboard.py [Install] WantedBy=multi-user.target -
Recharger la liste des services :
$ systemctl --user daemon-reload -
Activer le service au démarrage :
$ systemctl --user enable sensor.service -
Et enfin le démarrer :
$ systemctl --user start sensor.service
Bonus
Envoi manuel de données
A des fins de tests, si vous avez besoin d’envoyer des données manuellement (unitairement) vers Thingsboard, il vous faudra un client MQTT (par exemple Mosquitto).
Lancer la commande suivante :
$ mosquitto_pub -d -q 1 -h "<serveur mqtt>" -p "1883" -t "v1/devices/me/telemetry" -u "<token thingsboard du device>" -m {"temperature":35}
Sources
- https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi
- https://learn.adafruit.com/adafruit-sht31-d-temperature-and-humidity-sensor-breakout/python-circuitpython
- https://thingsboard.io/docs/samples/raspberry/temperature/
- https://learn.adafruit.com/adafruit-sht31-d-temperature-and-humidity-sensor-breakout/overview
- https://learn.adafruit.com/circuitpython-on-raspberrypi-linux