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 :

Les composants

Le capteur

Il pourrait être intéressant de creuser la construction d’un HAT spécifique avec les composants suivants :

Le serveur

Installation du système

  1. 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/

  2. 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
    
  3. 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é ssh dans la partition boot :
      $ touch /run/media/brice/boot/ssh
      
    • Pour le wifi, il faut créer le fichier suivant (toujours dans la partition boot) :
      $ vim /run/media/brice/boot/wpa_supplicant.conf
      
      Et y ajouter les lignes suivantes, en adaptant YOURSSID & YOURPASSWORD
      country=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 partition boot) :
      username:myencryptedpassword
      
  4. Placer la carte SD dans le RPi0 et le brancher. Patienter quelques secondes pour qu’il s’allume.

  5. Se connecter en SSH

  6. Vérifier la présence de mises à jour et les installer :

    $ sudo apt update && sudo apt upgrade
    
  7. Installer vim :

    $ sudo apt install vim
    
  8. 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 :

Schéma de câblage

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.

  1. Installation de pip & setuptools :

    $ sudo apt-get install python3-pip
    $ sudo pip3 install --upgrade setuptools
    
  2. 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.

  3. 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

  1. Aller dans “Devices”, ajouter un nouveau device en cliquant sur le signe + (en haut à droite).

  2. Donner un nom (1) et cliquer sur Credentials en bas à droite de la pop-up : Ajout device

  3. 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) : Ajout device

  4. 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 :

Télémétrie

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.

  1. Activer les instances utilisateurs systemd au démarrage (et non à l’ouverture de session) :

    $ sudo loginctl enable-linger brice
    
  2. Ajouter les lignes suivantes pour affecter les variables XDG_RUNTIME_DIR et DBUS_SESSION_BUS_ADDRESS manuellement dans le .bashrc de 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"
    
  3. Créer le répertoire pour les services systemd utilisateur :

    $ mkdir -p ~/.config/systemd/user/
    
  4. 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
    
  5. Recharger la liste des services :

    $ systemctl --user daemon-reload
    
  6. Activer le service au démarrage :

    $ systemctl --user enable sensor.service 
    
  7. 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