Faire du NodeMCU un vrai objet IOT

Ca y est, après 2 tutos, nous avons réussi à récupérer des informations sur notre nodeMCU pour les différentes sondes. Maintenant, nous allons voir comment économiser l’énergie et en faire un vrai objet communiquant avec le reste de notre domotique.

Concept

Le but final est de faire une sonde de température/humidité/pression qui consomme le moins d’énergie, pour pouvoir fonctionner sur piles. Il faudra donc que le montage soit en sommeil et, une fois de temps en temps, se reveille pour envoyer ses valeurs dans un système domotique.

On utilisera Domoticz dans un premier temps, puis on fera du MQTT dans un deuxième (je présenterais MQTT et ses avantages dans un tuto dédié).

Deep Sleep

Pour mettre en sommeil notre Arduino pour un temps donné, nous allons devoir jouer avec l’instruction deep sleep. En réalité, il y a 4 modes sur NodeMCU qui permettent différentes choses.

On voit que pour consommer le moins de courant possible en veille, il faut utiliser le deep sleep : moins de 20 micro ampère annoncé !

Pour que le deep sleep fonctionne, il faut relier les bornes RST avec D0. Car quand RST reçoit un niveau bas (LOW), il relance le nodemcu et relance donc le programme. C’est ce qu’il fait à la fin du deep sleep. Voici donc le cablage.

Voici le code testé

#include <ESP8266WiFi.h>
#include <Wire.h>                                                       // required by BME280 library
#include <BME280_t.h>
 
const char* ssid = "mon_ssid";
const char* password = "xxxxx";

const int MYALTITUDE = 350;
BME280<> BMESensor;

WiFiServer server(80);

//fonction qui corrige la pression en fonction de l'altitude
double getP(double Pact, double temp, double altitude) {
  return Pact * pow((1 - ((0.0065 * altitude) / (temp + 0.0065 * altitude + 273.15))), -5.257);
}


void setup() {
  Serial.begin(115200);
  delay(10);
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Start the server
  server.begin();
  Serial.println("Server started");
 
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  //initialisation bme280
  Wire.begin(0,2); 
  BMESensor.begin();
  BMESensor.refresh();
  Serial.print("Temp : ");
  Serial.println(BMESensor.temperature);
  Serial.print("Hum : ");
  Serial.println(BMESensor.humidity);
  Serial.print("Pressure : ");
  Serial.println(getP((BMESensor.pressure / 100.0F), BMESensor.temperature, MYALTITUDE));
  Serial.println("Going into deep sleep for 20 seconds");
  ESP.deepSleep(20e6); // 20e6 is 20 seconds
 
}

void loop() { 
}

Et voici le résultat dans la console

Note : vous pouvez avoir des problèmes de transmission avec le logiciel Arduino et vous avez les messages suivants :

  • warning: espcomm_sync failed
  • error: espcomm_open failed

Pour régler ce problème, débranchez la pin D0 le temps du transfert et rebrancher la après. Ca a réglé le problème chez moi.

Envoyer les données dans Domoticz

Ca y est, on a notre objet connecté qui fonctionne. Il faut désormais l’exploiter et la première chose à tester, c’est de l’envoyer dans Domoticz.

Première étape, il faut créer un dummy device dans Domoticz correspondant au capteur exploité. On fera l’exemple sur le BME280.

Une fois créé, il faut repérer son id dans les Devices. Ici c’est le 74.

On va donc pouvoir commencer à ajouter du code dans notre NodeMCU pour envoyer les données dans Domoticz. Pour cela, il faut ouvrir une URL avec des paramètres qui nous renverra un json. Tout cela est très bien décrit dans la documentation Domoticz.

Pour notre exemple, il faut donc que nous ouvrons une URL du type /json.htm?type=command&param=udevice&idx=IDX&nvalue=0&svalue=TEMP;HUM;HUM_STAT;BAR;BAR_FOR

où :

  • IDX = id du dummy device (74 ici)
  • TEMP = température
  • HUM = Humidité
  • HUM_STAT = état de l’humidité
  • BAR = pression atmosphérique
  • BAR_FOR = prévision barométrique

Pour la prévision barométrique, je ne m’en suis pas servi car il faudrait historiser la donnée et faire une tendance sur 3/6/9/12h …

Pour HUM_STAT, voici les valeurs possibles. On définira dans le code les seuils suivants :

  • 0=Normal (entre 30 et 45%)
  • 1=Confortable (entre 45 et 70%)
  • 2=Sec (inférieur à 30%)
  • 3=Humide (supérieur à 70%)

Pour le reste, rien de sorcier. Je vous met le code ci dessous, vous retrouverez assez vite les différents éléments. Les paramètres globaux de connexion à Domoticz sont en haut du fichier.

PS : il faut paramétrer sur le port qui est en http (8080 par défaut). Pour le https, il faut une configuration plus complexe pour ignorer les certificats.

#include <ESP8266WiFi.h>
#include <Wire.h>                                                       
#include <BME280_t.h>
 
const char* ssid = "mon_ssid";
const char* password = "xxxxxxx";
const char* host = "192.168.1.6"; //IP domoticz serveur
const int httpPort = 8080;        //domoticz port
const int idx = 74;               //domoticz id

const int MYALTITUDE = 350;
BME280<> BMESensor;

WiFiServer server(80);

//fonction qui corrige la pression en fonction de l'altitude
double getP(double Pact, double temp, double altitude) {
  return Pact * pow((1 - ((0.0065 * altitude) / (temp + 0.0065 * altitude + 273.15))), -5.257);
}


void setup() {
  Serial.begin(115200);
  delay(10);
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Start the server
  server.begin();
  Serial.println("Server started");
 
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  //initialisation bme280
  Wire.begin(0,2); 
  BMESensor.begin();
  BMESensor.refresh();
  
  WiFiClient client;

  // We now create a URI for the request
  float temp = BMESensor.temperature;
  float hum = BMESensor.humidity;
  float pres = getP((BMESensor.pressure / 100.0F), BMESensor.temperature, MYALTITUDE);
  int humstat = 0;
  if(hum < 30) humstat = 2;
  if (hum >=30 && hum < 45) humstat = 0;
  if (hum >=45 && hum < 70) humstat = 1;
  if(hum >= 70) humstat = 3;

  
  String url1 = "/json.htm?type=command&param=udevice&idx=";
  String url1_1 = "&nvalue=0&svalue=";
  String url2 = ";";
  String url3 = ";0";
  String url = String(url1 + idx + url1_1 + temp + url2 + hum + url2 + humstat + url2 + pres + url3);

  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
   
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(10);

  // Read all the lines of the reply from server and print them to Serial
  Serial.println("Respond:");
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  Serial.println("Going into deep sleep for 120 seconds");
  ESP.deepSleep(120e6); // 120e6 is 120 seconds
    
}

void loop() { 
}
 

Et voici le résultat dans Domoticz

Conclusion

On approche d’une solution complète avec des capteurs de températures autonomes qui envoient des données dans notre serveur central. La prochaine étape va être d’utiliser MQTT et de gérer des files de messages.

2 Comments

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.