ESP32 risparmio energetico pratico: sonno profondo ed ibernazione – 3
La modalità di risparmio energetico più comune per ESP32 è il sonno profondo, qui vedremo cosa significa sonno profondo e la differenza con la variante di ibernazione.
L’ibernazione come il modem sleep è una definizione logica che devi gestire, non esiste un comando specifico, viene “attivata” applicando una determinata logica e poiché questa modalità offre grandi vantaggi può spingerti a cambiare la logica del tuo codice.
In modalità deep sleep, le CPU, la maggior parte della RAM e tutte le periferiche digitali con clock Advanced Peripheral Bus (APB_CLK) sono spente. Le uniche parti del chip che possono ancora essere accese sono: controller dell’orologio in tempo reale (RTC), periferiche RTC, il coprocessore Ultra Low Power (ULP) e memorie RTC (lente e veloci).
In questa tabella dal datasheet dell’esp32 ci sono informazioni su come raggruppare le modalità sleep.
Modalità di alimentazione | Descrizione | Consumo di energia | ||
Attivo (RF funzionante) |
Pacchetto Tx Wi-Fi |
78 mA ~ 90 mA senza comunicazione Per TX RX maggiori informazioni nella tabella successiva |
||
Pacchetto Wi-Fi / BT Tx | ||||
Wi-Fi / BT Rx e ascolto | ||||
Modem-sleep |
La CPU è accesa. |
240 MHz * | Dual-core chip(s) | 30 mA ~ 68 mA |
Single-core chip(s) | N/A | |||
160 MHz * | Dual-core chip(s) | 27 mA ~ 44 mA | ||
Single-core chip(s) | 27 mA ~ 34 mA | |||
Velocità normale: 80 MHz | Dual-core chip(s) | 20 mA ~ 31 mA | ||
Single-core chip(s) | 20 mA ~ 25 mA | |||
Light-sleep | – | 0.8 mA | ||
Deep-sleep |
Il coprocessore ULP è acceso. | 150 µA 100 µA @1% duty 10 µA | ||
Pattern monitorato dal sensore ULP | ||||
Timer RTC + memoria RTC | ||||
Hibernation | Solo timer RTC | 5 µA | ||
Power off | CHIP_PU è impostato su un livello basso, il chip è spento. | 1 µA |
Sonno profondo (Deep sleep)
Il sonno profondo è il modo più efficiente per mettere il tuo dispositivo in stato di stop, ma c’è una grande differenza dal sonno leggero (light sleep) che lo rende meno utilizzabile, lo stato viene cancellato, quindi se hai impostato una variabile al riavvio del dispositivo, la variabile viene ripristinata, e il programma si riavvia dal setup iniziale.
But you have to pay attention, in my block diagram I do not disable the peripheral group but only the single ones to emphasize that the only real difference from hibernation are the functional units that remain active, this is what Espressif writes:
Il modulo RTC IO contiene la logica di riattivazione quando uno dei GPIO RTC è impostato su un livello logico predefinito. RTC IO fa parte del dominio di alimentazione delle periferiche RTC, quindi le periferiche RTC verranno mantenute accese durante la sospensione profonda se viene richiesta questa sorgente di attivazione.
Dalla documentazione Espressif
Perciò, se usiamo una fonte esterna di risveglio, sarà considerato un sonno profondo, se non usiamo niente o solo RTC avremo un hibernation.
Quindi ecco un semplice schizzo per testare il sonno profondo (deep sleep).
/*
* ESP32
* DEEP Sleep and wake up
* by Mischianti Renzo <https://mischianti.org>
*
* https://mischianti.org/it/esp32-risparmio-energetico-pratico-sonno-profondo-ed-ibernazione-3/
*
*/
#include <WiFi.h>
#include <BluetoothSerial.h>
#include "driver/adc.h"
#include <esp_bt.h>
#include <esp_wifi.h>
#include <esp_sleep.h>
#define STA_SSID "<YOUR-SSID>"
#define STA_PASS "<YOUR-PASSWD>"
BluetoothSerial SerialBT;
int variable = 0;
void setup() {
Serial2.begin(115200);
while(!Serial2){delay(500);}
SerialBT.begin("ESP32test"); //Bluetooth device name
SerialBT.println("START BT");
Serial2.println("START WIFI");
WiFi.begin(STA_SSID, STA_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial2.print(".");
}
Serial2.println("");
Serial2.println("WiFi connected");
Serial2.println("IP address: ");
Serial2.println(WiFi.localIP());
delay(1000);
Serial2.print("Initial Variable value = ");
Serial2.println(variable);
variable += 10;
Serial2.print("Variable updated = ");
Serial2.println(variable);
Serial2.println();
Serial2.println("DEEP SLEEP ENABLED FOR 5secs");
delay(100);
esp_sleep_enable_timer_wakeup(5 * 1000 * 1000);
// Pay attention to this command, with this wake up source
// your device can't go to hibernate mode
// but only deep sleep
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
esp_deep_sleep_start();
Serial2.println();
Serial2.println("DEEP SLEEP WAKE UP");
Serial2.print("Variable = ");
Serial2.println(variable);
}
void loop() {
}
void disableWiFi(){
adc_power_off();
WiFi.disconnect(true); // Disconnect from the network
WiFi.mode(WIFI_OFF); // Switch WiFi off
Serial2.println("");
Serial2.println("WiFi disconnected!");
}
void enableWiFi(){
adc_power_on();
WiFi.disconnect(false); // Reconnect the network
WiFi.mode(WIFI_STA); // Switch WiFi off
Serial2.println("START WIFI");
WiFi.begin(STA_SSID, STA_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial2.print(".");
}
Serial2.println("");
Serial2.println("WiFi connected");
Serial2.println("IP address: ");
Serial2.println(WiFi.localIP());
}
void disableBluetooth(){
btStop();
esp_bt_controller_disable();
delay(1000);
Serial2.println("BT STOP");
}
Quando si avvia lo sketch, denotiamo la prima differenza dal sonno leggero, lo stato della variabile non viene conservato in modalità di sospensione profonda e il flusso del programma viene riavviato dal setup()
.
Come puoi vedere il valore della variabile è 0, viene ripristinato ogni volta. E ogni volta che l’esp32 esce dalla sospensione profonda riparte dal setup()
iniziale.
Ora testeremo questo sketch con i nostri 3 dispositivi.
DOIT DEV KIT v1
Per maggiori informazioni sul dispositivo fare riferimento a “DOIT ESP32 DEV KIT v1 immagine di piedinatura ad alta risoluzione e specifiche“.
Qui lo schema di connessione che abbiamo usato.
Usando l’alimentatore esterno, alimentare l’esp32 con il pin 5v e il pin GND e scollegare l’USB. Per accedere usiamo la porta Serial2, ma se vuoi usare la porta Serial devi solo spostare il convertitore FTDI sul pin TX invece che sul pin TX2, non puoi usare l’USB perché alimenta il dispositivo e il multimetro ottiene un amperaggio errato.
Anche in questo caso il risultato non è buono, questo dispositivo in ibernazione consuma 12.19mA, molto molto molto lontano dai 150µA dichiarati da Espressif.
Come accaduto per il light sleep all’inizio ero depresso, ma proprio dall’esperienza del light sleep capisco che il dispositivo che utilizzo non è progettato per la produzione, in una scheda di sviluppo ci sono molti altri componenti che possono cambiare il risultato, come i LED , regolatori di tensione, ecc.
Provo a fare lo stesso test con due famosi produttori di schede, che hanno dispositivi con gestione della batteria e altre funzionalità, non solo per sviluppo.
TTGO T8
Per prima cosa voglio provare un TTGO, che è uno dei più famosi produttori di questo genere di dispositivi, con molte varianti, utilizzo uno dei suoi migliori prodotti il TTGO T8.
Il risultato con alimentazione a 5V dal pin specifico dà un cattivo risultato 9.63mA, ma la scheda quando alimentata solo con batteria esclude alcune unità funzionali come led, regolatore di tensione ecc., Quindi lo stesso test con alimentazione a batteria raggiunge 4.56mA risultato più ragionevole .
WeMos LOLIN32
Per maggiori informazioni sul dispositivo fare riferimento a “ESP32 WeMos LOLIN32 immagine di piedinatura ad alta risoluzione e specifiche“
Ecco lo schema di connessione.
Ed ecco lo schema di connessione con alimentazione a batteria.
Poi il WeMos LOLIN32, amo WeMos come produttore, credo di avere un buon set di dispositivi e questi sono molto versatili con dimensioni varie.
Il risultato con alimentazione a 5V dal pin specifico dà un risultato decisamente migliore di 2.92mA, e la scheda quando alimentata solo con la batteria raggiunge 1.81mA.
Device | Mode | Power |
---|---|---|
DOIT DEV KIT v1 | Power to VIN pin | 12.19mA |
TTGO T8 | Power to 5V pin | 9.63mA |
Power via Battery | 4.56mA | |
WeMos LOLIN32 | Power via 5V pin | 2.92mA |
Power via Battery | 1.81mA |
Ibernazione
L’ibernazione è simile al deep sleep, ma devi rinunciare ad alcune possibilità di risveglio come la fonte esterna.
Creo un semplice sketch per testare le prestazioni di ibernazione
/*
* ESP32
* DEEP Sleep and wake up
* by Mischianti Renzo <https://mischianti.org>
*
* https://mischianti.org/it/esp32-risparmio-energetico-pratico-sonno-profondo-ed-ibernazione-3/
*
*/
#include <WiFi.h>
#include <BluetoothSerial.h>
#include "driver/adc.h"
#include <esp_bt.h>
#include <esp_wifi.h>
#include <esp_sleep.h>
#define STA_SSID "<YOUR-SSID>"
#define STA_PASS "<YOUR-PASSWD>"
BluetoothSerial SerialBT;
int variable = 0;
void setup() {
Serial2.begin(115200);
while(!Serial2){delay(500);}
SerialBT.begin("ESP32test"); //Bluetooth device name
SerialBT.println("START BT");
Serial2.println("START WIFI");
WiFi.begin(STA_SSID, STA_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial2.print(".");
}
Serial2.println("");
Serial2.println("WiFi connected");
Serial2.println("IP address: ");
Serial2.println(WiFi.localIP());
delay(1000);
Serial2.print("Initial Variable value = ");
Serial2.println(variable);
variable += 10;
Serial2.print("Variable updated = ");
Serial2.println(variable);
Serial2.println();
Serial2.println("DEEP SLEEP ENABLED FOR 5secs");
delay(100);
esp_sleep_enable_timer_wakeup(5 * 1000 * 1000);
esp_deep_sleep_start();
Serial2.println();
Serial2.println("DEEP SLEEP WAKE UP");
Serial2.print("Variable = ");
Serial2.println(variable);
}
void loop() {
}
void disableWiFi(){
adc_power_off();
WiFi.disconnect(true); // Disconnect from the network
WiFi.mode(WIFI_OFF); // Switch WiFi off
Serial2.println("");
Serial2.println("WiFi disconnected!");
}
void enableWiFi(){
adc_power_on();
WiFi.disconnect(false); // Reconnect the network
WiFi.mode(WIFI_STA); // Switch WiFi off
Serial2.println("START WIFI");
WiFi.begin(STA_SSID, STA_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial2.print(".");
}
Serial2.println("");
Serial2.println("WiFi connected");
Serial2.println("IP address: ");
Serial2.println(WiFi.localIP());
}
void disableBluetooth(){
btStop();
esp_bt_controller_disable();
delay(1000);
Serial2.println("BT STOP");
}
Per mettere i dispositivi in ibernazione invece che in modalità deep sleep rimuovo semplicemente la fonte di risveglio esterna. Ricorda ext0 mettere in sonno profondo, ma ext1 previene l’uso del sonno profondo.
DOIT DEV KIT v1
L’ibernazione ha un risultato migliore rispetto al sonno profondo e DEV KIT v1 consuma 3.46mA, ma è molto molto molto lontano dai 5µA dichiarati da Espressif.
Provo a fare lo stesso test con due famosi produttori di schede, che hanno dispositivi con gestione della batteria e altre funzionalità, non solo per sviluppo.
TTGO T8
Il risultato con alimentazione a 5V dal pin specifico dà un cattivo risultato di 7,95mA, ma lo stesso test con alimentazione a batteria arriva è 3,33mA, decisamente migliore del primo risultato e del DOIT DEV KIT v1.
WeMos LOLIN32
Il risultato con alimentazione a 5V dal pin specifico dà un risultato decisamente migliore 1.26mA, ma la scheda quando alimentata solo con batteria raggiunge i 160µA, e questo è un risultato veramente buono.
Risultati
I dati sono molto chiari, il DOIT DEV KIT v1 è il perdente e il LOLIN32 è il vincitore, TTGO ha il prezzo più alto non può essere considerato all’altezza.
Device | Mode | Power |
---|---|---|
DOIT DEV KIT v1 | Power to VIN pin | 3.46mA |
TTGO T8 | Power to 5V pin | 7.95mA |
Power via Battery | 3.33mA | |
WeMos LOLIN32 | Power via 5V pin | 1.26mA |
Power via Battery | 160µA |
Grazie
- ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
- ESP32: fileSystem integrato SPIFFS
- ESP32: gestire più seriali e logging per il debug
- ESP32 risparmio energetico pratico
- ESP32 risparmio energetico pratico: gestire WiFi e CPU
- ESP32 risparmio energetico pratico: modem e light sleep
- ESP32 risparmio energetico pratico: deep sleep e ibernazione
- ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
- ESP32 risparmio energetico pratico: sveglia esterna e da ULP
- ESP32 risparmio energetico pratico: sveglia da UART e GPIO
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (Fat/exFAT)
- ESP32-wroom-32
- ESP32-CAM
- ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
- ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
- Come usare la scheda SD con l’esp32
- esp32 e esp8266: file system FAT su memoria SPI flash esterna
- Gestione aggiornamenti firmware e OTA
- Gestione del firmware
- Aggiornamento OTA con Arduino IDE
- Aggiornamento OTA con browser web
- Aggiornamenti automatici OTA da un server HTTP
- Aggiornamento del firmware non standard
- Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
- Collegare l’EByte E70 (CC1310) ai dispositivi ESP32 c3/s3 ed un semplice sketch di esempio
- ESP32-C3: piedinatura, specifiche e configurazione dell’IDE Arduino
- Integrazione del modulo W5500 su ESP32 con Core 3: supporto nativo ai protocolli Ethernet con SSL e altre funzionalità
- Integrazione del modulo LAN8720 su ESP32 con Core 3: supporto nativo del protocollo Ethernet con SSL e altre funzionalità.
Ciao.
Volevo il tuo parere su questo progetto.
Ho realizzato una connessione BLE client server tra due ESP32.
Il client è sotto Home Assistant e attraverso uno switch accende un LED sul server BLE (l’altra ESP32).
Volendo alimentare a batteria il server BLE, ovviamente, c’è un problema di consumi (che hai meticolosamente dettagliato nei tuoi articoli).
Ponendo in deep sleep il server (che verrà alimentato a batteria) credo che si perderà la connessione BLE con il client.
L’unico modo per avere la connessione quando serve è , a quanto ho capito, risvegliare a intervalli regolari il server e avere il client che contemporaneamente chiede la connessione .
E’ questo l’unico modo, per il quale a conti fatti comunque non avrei durata della batteria misurata in mesi/anni ma piuttosto in qualche settimana o esiste un metodo più efficiente.
Grazie anticipate per il tuo tempo.
Ciao cosimo,
credo che non ci sia un modo di “risvegliare” il dispositivo in BLE.
Per avere un’efficienza elevata ti consiglio di passare a dei moduli LoRa, che ti permettono di risvegliare il dispositivo tramite WOR, come descritto su quest’articolo.
Ebyte LoRa E32 per Arduino, esp32 o esp8266 : WOR (wake on radio) del microcontrollore e lo shield per esp32
Ciao Renzo
Cia Renzo.
Grazie per la risposta.
Hai fatto anche un calcolo del consumo del modulo LoRa ?
In modalità sleep il modulo LoRa E32 mi pare che si parli di pochi µA, praticamente minimo.
E consente, a differenza di altri dispositivi WiFi di mettere il dispositivo in deep sleep se non interessa il messaggio di wake.
Ciao Renzo
Ciao Renzo,
ho provato lo sketch riportato sotto la dicitura “Creo un semplice sketch per testare le prestazioni di ibernazione” di questa pagina con la mia scheda ESP32-D2WD ma ottengo come Amperaggio 11,6mA e non un 3,4 mA .
Cosa devo modificare nello sketch per ottenere i valori attesi dall’ibernazione?
Grazie
Ciao Nino,
probabilmente non puoi ottenere gli stessi valori, come scrivo nell’articolo ogni produttore usa schemi e resistenze diverse sulle schede, ed ognuna ha degli assorbimenti diversi.
Ciao Renzo