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¶m=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¶m=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.