ESP8266 with DHT22 sending MQTT
Um einen Aussensensor eine gewisse Zeit mit einer Batterie betreiben zu können ist die Möglichkeit den Prozessor schlafen zu legen extrem wichtig. Und wenn man mit einem relativ großen Messinterval zufrieden ist, lässt sich noch mehr aus einem Akku herausholen. Der ESP8266 kann das sogar recht gut. Im Netz kann man durchaus Quellen finden, die biss zu 60 Minuten lange deep sleeps erwähnen. Mit ESP.deepSleep(sleep_uSec) lässt sich der ESP schlafen legen. Zusätzlich muss der Reset Pin mit GPIO16 verbunden werden.
Im deepsleep läuft nur noch die RTC vom Prozessor, der nach Ablauf der festgelegten Periode per GPIO16 den Reset Pin auf low zieht. Und so den geladenen Sketch (ja ich programmiere den ESP mit Arduino) neu ausführt. Code nach dem Aufruf des deep sleep wird nicht ausgeführt. Allerdings wird berichtet, dass ein delay(100); nötig ist um sicher in den deep sleep zu kommen.
Mit ESP.getResetReason() kann man als Klartext den Grund für den letzten Reset abfragen. Die Antwort lautet dann „Deep-Sleep Wake“, auch wenn der Reset Pin per Taster vor Ablauf der Schlafperiode getriggert wird.
Wichtig ist entweder die Brücke vor einem neu Programmieren auszulöten oder anders schaltbar zu machen. Damit man genug Zeit hat den neuen Sketch auf den ESP hoch zu laden. Alternativ kann man vor dem sleep ein delay von 30 Sekunden einbauen.
Ich benutze shiftr.io als MQTT Broker um die Messages schön zu visualisieren. Das ganze ist aber ziemlich langweilig wenn alle Nodes nur alle 15 Minuten was senden.
Material & Links
Code
- dht_deepsleep.ino
/* License TBD Christian Moll */ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include "DHT.h" #include <MQTTClient.h> #define DHTTYPE DHT22 #define DHTPIN 4 #define FORCE_DEEPSLEEP const char* host = "esp8266_room1"; // will also be used on shiftr.io const char* ssid = "ssid"; const char* password = "password"; WiFiClient net; MQTTClient mqtt; DHT dht(DHTPIN, DHTTYPE); unsigned int batt; double battV; void connect(); void setup(void){ dht.begin(); Serial.begin(115200); Serial.println(); Serial.println("Booting Sketch..."); WiFi.mode(WIFI_AP_STA); WiFi.begin(ssid, password); mqtt.begin("broker.shiftr.io", net); connect(); Serial.printf("ready!"); } void loop(void){ if(!mqtt.connected()) { connect(); } mqtt.loop(); delay(30000); // time to make reprogramming possible batt = analogRead(A0); battV = mapDouble(batt, 0, 1023, 0.0, 6.6); float h = dht.readHumidity(); float t = dht.readTemperature(); // Check if any reads failed and exit early (to try again). if (!isnan(h) || !isnan(t)) { mqtt.publish("/room1/temp", String(t)); mqtt.publish("/room1/humidity", String(h)); } mqtt.publish("/room1/batt", String(battV)); mqtt.publish("/room1/battRaw", String(batt)); mqtt.publish("/room1/resetReason", ESP.getResetReason()); #ifdef FORCE_DEEPSLEEP Serial.println("Force deepsleep 15min!"); ESP.deepSleep(15 * 60 * 1000000); delay(100); #endif //handle deep sleep depending on battV if (battV < 3.3) { ESP.deepSleep(30 * 1000000); //send IFTTT low_bat warning delay(100); } else if (battV < 4.0) { ESP.deepSleep(2 * 1000000); delay(100); } } void connect() { while(WiFi.waitForConnectResult() != WL_CONNECTED){ WiFi.begin(ssid, password); Serial.println("WiFi failed, retrying."); } Serial.print("IP address: "); Serial.println(WiFi.localIP()); while (!mqtt.connect(host, "shiftr-thing", "shiftr-pass")) { Serial.print("."); } Serial.println("\nconnected!"); } void messageReceived(String topic, String payload, char * bytes, unsigned int length) { Serial.print("incoming: "); Serial.print(topic); Serial.print(" - "); Serial.print(payload); Serial.println(); } double mapDouble(double x, double in_min, double in_max, double out_min, double out_max) { double temp = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; temp = (int) (4*temp + .5); return (double) temp/4; }