Aller au contenu

Station météo wifi – Partie 2

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

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
  "XXXXX",     // MQTT - Psw
  "XXXXX",     // MQTT - Identifiant
  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 Raspbian, contraction de Raspberry et Debian. 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 Raspbian !

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.

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 les premiers pas, c’est ici.

Pour accéder à node-RED, depuis votre navigateur, tapez l’adresse de votre PI :1880 (ex : 192.168.1.65: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 :

Etape 4 – InfluxDB

Les infos sont ici.

  • Grafana : Visualisation des données sous une forme sympathique (graphes, valeurs instantanée, etc…).

1 commentaire pour “Station météo wifi – Partie 2”

Laisser un commentaire

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