In diesem Beitrag wird der DeepSleep-Modus durch den effektiveren Hibernate-Modus abgelöst. Zudem unternehme ich weitere Versuche das WLAN-Connect-Problem in den Griff zu kriegen.
Der ESP32 bietet diverse Stromspareinstellungen für die Zeit an, in der er nicht gebraucht wird. Der DeepSleep-Modus war für den Anfang schon ganz gut. Es geht aber noch effektiver und zwar mit dem Hibernate-Modus. Hier wird dann wirklich bis auf die langsame RTC-Clock alles abgeschaltet. Während sich DeepSleep noch maximal 150μA gönnt, sind es bei Hibernate nur noch 5μA. Man kann das beispielsweise hier nachlesen.
Hibernate zu erreichen ist indes nicht ganz so trivial. Bestimmte Register des ESP32 werden normalerweise im Automatik-Modus betrieben und kümmern sich nicht um den DeepSleep.
Hibernate zu erreichen ist indes nicht ganz so trivial. Bestimmte Register des ESP32 werden normalerweise im Automatik-Modus betrieben und kümmern sich nicht um den DeepSleep. Die entsprechenden kleinen Stromverbraucher im Chip bleiben deshalb eingeschaltet. Der Befehl zum Erreichen des Hibernates ist aber der gleiche wie bei DeepSleep:
esp_sleep_enable_timer_wakeup(sleeptime * 1000000); //Board soll schlafen und nach [sleeptime] Sekunden aufwachen
esp_deep_sleep_start(); //Aktivierung Schlafzyklus
Die einzelnen Register zur Verbrauchersteuerung im Chip erreicht man über den Befehl esp_sleep_pd_config(). Die Parameter für die Steuerung fand ich zuerst in Steph’s μLab:
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
Diese Anweisungen werden einfach den schon bekannten Befehlen zum Erreichen des DeepSleep vorangestellt, wodurch dann das Hibernate erreicht wird. Leider hat das aber nicht funktioniert. Sobald das Programm auf dem ESP32 lief, kam sofort eine Fehlermeldung, die diese Befehle als problematisch erkannte. Es wurde dann auch nicht einmal mehr ein normaler DeepSleep errecht.
Offensichtlich gibt es in der ESP–IDF (Development framework for Espressif SoCs) irgendeinen hartnäckigen und schon länger bekannten Fehler, der das Ausschalten der jeweiligen Register verhindert. Es gibt aber Abhilfe, wie ich an anderer Stelle ermitteln konnte. Vor dem Ausschalten der Register muss erst ein definiertes Einschalten erfolgen. Die ganze Funktion sieht dann so aus:
void hibernate() {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
// // esp_sleep_pd_config(ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_OFF); // enum is deprecated
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF);
esp_sleep_enable_timer_wakeup(sleeptime * 1000000); //Board soll schlafen und nach [sleeptime] Sekunden aufwachen
esp_deep_sleep_start(); //Aktivierung Schlafzyklus
}
Ich habe zwar noch nicht nachgemessen, ob der Stromverbrauch tatsächlich auf 5μA runter geht, aber es läuft wenigstens.
Ein anderes hartnäckiges Problem betrifft den Connect ins WLAN. Nach ein paar erfolgreichen Connects wird die Zeit bis zur Verbindung immer länger. Irgendwann klappt es dann doch. Alle Versuche dies zu ändern schlugen bisher fehl. Wenn ich mir aber überlege, dass ich den ESP32 quasi komplett abschalte, wodurch überigens jegliche Speicher gelöscht werden, vermute ich das Problem mittlerweile eher entweder bei meiner Fritzbox oder aber in einer unzureichenden Stromversorgung über den PC. Wenn jemand von Euch eine gute idee hat, schreibt es gerne hier in die Kommentare. Eine Idee bestand darin, den Brownout Detector abzuschalten, was aber letztendlich auch nicht sicher geholfen hat:
#include "soc/soc.h" // disable brownout detector (Fehler bei WiFi Anmeldung beheben)
#include "soc/rtc_cntl_reg.h" // disable brownout detector (Fehler bei WiFi Anmeldung beheben)
... und innerhalb der setup() ...
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector (Fehler bei WiFi Anmeldung beheben)
In dieser Beitragsreihe geht es damit weiter, dass ich den Sketch so umbaue, dass er die Daten an eine Datenbank liefert. Vermutlich werde ich aber erst in gut einem Monat dazu kommen. Ich bitte um Geduld.