Après un premier essai de capteurs météo avec retransmission sans fil vers le web (Adafruit IO), voici un second projet dont l’objectif est de permettre le stockage en local des données. Trois avantages : vous êtes maître de vos données, pas de coût de stockage en ligne, et pas d’envoi en ligne en continu.
Passons à la description du projet…
Matériel utilisé
Carte NodeMCU ESP8266-12E

La carte utilisée (dénommée NodeMCU) s’appuie sur un module ESP-12E qui intègre un microcontrôleur ESP8266. L’ESP8266 est un circuit intégré à microcontrôleur avec connexion Wi-Fi développé par le fabricant chinois Espressif.
Cette carte regroupe donc :
- un microcontrôleur ESP8266 notamment programmable avec l’IDE ARDUINO,
- un module WIFI pour communiquer avec le vaste mnde,
- une liaison série,
- des entrées/sorties.
Capteur de température et d’hygrométrie DHT22

Ce capteur est utilisé pour capter température et hygrométrie à l’intérieur.
Capteur de température, humidité et pression atmosphérique bme280

Ce capteur est utilisé pour capter les données extérieures. Il est installé dans une petite capsule plastique. Il ne faut pas que la boîte soit étanche afin que le capteur puisse mesurer correctement la pression atmosphérique :

Le reste de l’électronique (carte ESP8266 + capteur DHT22) est positionné à l’intérieur :

Raspberry Pi 4

Ce mini-ordinateur (la framboise en français) va permettre de gérer le serveur de données (stockage, visualisation). Il est installé dans un boîtier imprimé en 3D avec écran dédié.
Programmation du ESP8266 sous ARDUINO
Le programme ci-dessous permet de :
- récupérer les données des différents capteurs :
- DHT22 (température, humidité) en direct sur une entrée de la carte NodeMCU
- BME280 (pression, température, humidité) via un bus I2C géré par la carte NodeMCU
- transmettre les données en wifi vers le serveur hébergé sur le Raspberry.
Les données sont transmises en utilisant le protocole MQTT (Message Queuing Telemetry Transport).
// ZapGillouMTO
// v2.0 - 05/2020
//
// DHT22 : capteur température et humidité
// BME280 : capteur température, humidité, et pression atmosphérique
// Bibliothèques
#include <Adafruit_Sensor.h>
#include <DHT.h> // gestion DHT22
#include <DHT_U.h> // gestion DHT22
#include <Adafruit_BME280.h> // gestion BME280
#include <Wire.h> // gestion bus I2C
#include "EspMQTTClient.h" // gestion MQTT - Transfert de données
// MQTT/WIFI Config
EspMQTTClient client(
"XXXXX", // WIFI - Nom du réseau WIFI
"XXXXX", // WIFI - Mot de passe du réseau WIFI
"XXXXX", // MQTT - Serveur IP - Adresse Raspberry (192.168.1.XX)
"XXXXX", // MQTT - Login sur MOSQUITO installé sur le Raspberry
"XXXXX", // MQTT - Psw sur MOSQUITO installé sur le Raspberry
"XXXXX", // MQTT - Identifiant de l'ESP
1883 // MQTT - port
);
#define DHTPIN 14 // Correspond à D5 sur la carte NodeMCU
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT_Unified dht(DHTPIN, DHTTYPE); // Variable capteur DHT22
Adafruit_BME280 bme; // Variable capteur bmpe280
// Déclaration des variables globales utilisées pour l'aquisition des données
float ValeurTempin;
float ValeurTempout;
float ValeurHygroin;
float ValeurHygroout;
float ValeurPressout;
void setup()
{
// A des fins de test, transmission des infos sur la liaison série
// Toute cette transmission peut être supprimée si non utilisée
// Ouverture liaison série
Serial.begin(115200);
Serial.println("");
Serial.println("_Station Meteo ZapGillou");
// Initialisation liaison I2C
Wire.begin(0, 2); // Correspond aux broches D3/D4 sur la carte
if (!bme.begin(0x76)) {
Serial.println("_Capteur BME280 : NOK");
while (1);
}
else
{
Serial.println("_Capteur BME280 : OK");
}
dht.begin();
sensor_t sensor;
dht.temperature().getSensor(&sensor);
Serial.println("_Capteur DHT22");
Serial.println("_ 1.DHT22 : Capteur temperature");
Serial.print ("_ 1.Type : "); Serial.println(sensor.name);
Serial.print ("_ 1.Version : "); Serial.println(sensor.version);
Serial.print ("_ 1.ID : "); Serial.println(sensor.sensor_id);
Serial.print ("_ 1.Valeur min : "); Serial.print(sensor.min_value); Serial.println(F("°C"));
Serial.print ("_ 1.Valeur max : "); Serial.print(sensor.max_value); Serial.println(F("°C"));
Serial.print ("_ 1.Precision : "); Serial.print(sensor.resolution); Serial.println(F("°C"));
// Print humidity sensor details.
dht.humidity().getSensor(&sensor);
Serial.println("_ 2.DHT22 : Capteur humidite");
Serial.print ("_ 2.Type : "); Serial.println(sensor.name);
Serial.print ("_ 2.Version : "); Serial.println(sensor.version);
Serial.print ("_ 2.ID : "); Serial.println(sensor.sensor_id);
Serial.print ("_ 2.Valeur min : "); Serial.print(sensor.min_value); Serial.println(F("%"));
Serial.print ("_ 2.Valeur max : "); Serial.print(sensor.max_value); Serial.println(F("%"));
Serial.print ("_ 2.Precision : "); Serial.print(sensor.resolution); Serial.println(F("%"));
}
void onConnectionEstablished()
{
// Envoi MQTT des données sur les différents flux (pressout, tempout, hygroout, tempin, hygroin)
client.publish("pressout", String(ValeurPressout));
client.publish("tempout", String(ValeurTempout));
client.publish("hygroout", String(ValeurHygroout));
client.publish("tempin", String(ValeurTempin));
client.publish("hygroin", String(ValeurHygroin));
}
void loop()
{
ValeurPressout = bme.readPressure() / 100.0F;
Serial.print("_BME280 - Pression (hPA) = "); Serial.println(ValeurPressout);
ValeurTempout = bme.readTemperature();
Serial.print("_BME280 - Temperature (°C) = "); Serial.println(ValeurTempout);
ValeurHygroout = bme.readHumidity();
Serial.print("_BME280 - Humidite (%) = "); Serial.println(ValeurHygroout);
sensors_event_t event;
dht.temperature().getEvent(&event);
ValeurTempin = event.temperature;
Serial.print("_DHT22 - Temperature (°C) = "); Serial.println(ValeurTempin);
dht.humidity().getEvent(&event);
ValeurHygroin = event.relative_humidity;
Serial.print("_DHT22 - Humidite (%) = "); Serial.println(ValeurHygroin);
client.loop(); // Publication MQTT
// Tempo
Serial.println("_Tempo");
delay(60000); // 1 acquisition par minute
}
Et côté Raspberry
Ça a été le plus délicat car je découvrais tout de ce côté là…
Etape 1 – Distribution Raspbian
Avant toute chose, il faut installer une distribution linux sur la carte SD de votre Raspberry. J’ai choisi la plus populaire dénommée Raspberry Pi OS. Vous pouvez la trouver ici. Raspberry Pi Imager vous permet ensuite de générer une carte SD avec la distribution.
Insérez ensuite la carte SD dans le raspberry et patientez le temps du premier démarrage. Après quelques questions de configuration initiale, vous voilà sous Raspberry Pi OS !
Etape 2 – Mosquitto
Il convient maintenant de récupérer le flux de données venant de la station météo. Sous Raspberry, Mosquitto permet de recevoir les flux de données MQTT.
J’ai pu apprendre le fonctionnement de mosquitto sur ce site web.
Prévoyez la mise en service auto en cas de redémarrage du Raspberry, et définissez un accès user/psw :
sudo systemctl enable mosquitto.service
sudo mosquitto_passwd -c /etc/mosquitto/passwd user (user à remplacer)
Pour forcer l’accès non anonyme à Mosquitto, dans /etc/mosquitto/mosquitto.conf, rajouter les lignes
allow_anonymous false
password_file /etc/mosquitto/passwd
Et redémarrez Mosquitto :
systemctl restart mosquitto
Si votre Raspberry est derrière un routeur, pensez à rerouter le port 1883.
Etape 2bis – Testez Mosquitto !
Depuis votre PC, vous pouvez utiliser MQTT Explorer pour tester mosquitto.
Victoire !
pressout = 1024.64
tempout = 8.90
hygroout = 65.06
tempin = 19.30
hygroin = 49.20
Etape 3 – Node-RED
Node-RED est une solution graphique qui va permettre de récupérer les données reçues par Mosquitto et les rerouter vers une base de données par exemple.
Pour l’installation, c’est ici.
Pour accéder à node-RED, depuis votre navigateur, tapez l’adresse de votre PI :1880 (ex : 127.0.0.1:1880)

Node-RED permet ici de récupérer chaque flux MQTT (ex: tempin) et de le renvoyer vers la base de données ZGMTO gérée par InfluxDB, dans la table nommée DATAMTO. Cette table contient l’ensemble des valeurs des capteurs, la fonction intermédiaire permet d’affecter l’étiquette ad hoc à chaque flux (ici tempin) :

Le bloc vert « msg.payload » permet simplement de visualiser les données dans l’onglet DEBUG de Node-RED :

Quelques explications ici pour le démarrage auto de Node-RED en cas de reboot du raspberry.
Si votre Raspberry est derrière un routeur, pensez à rerouter le port 1880.
Etape 4 – Grafana
Grafana permet la visualisation des données sous une forme sympathique (graphes, valeurs instantanée, etc…).
Etape 5 – InfluxDB
Les infos sont ici. InfluxDB gèrera la base de données dans laquelle Node-RED déversera les données.
Installez le client associé également:
sudo apt install influxdb-client
Si votre Raspberry est derrière un routeur, pensez à rerouter le port 1883.
Etape 6 – Configurez Grafana

Si votre Raspberry est derrière un routeur, pensez à rerouter le port 3000.
Schéma global (issu de https://bentek.fr/influxdb-grafana-raspberry-pi/)

Super, ça donne envie de s’y mettre maintenant que j’ai un spécialiste Arduino à coté.