Implementare il risparmio energetico del microcontrollore ESP32: guida pratica
In questo articolo, vogliamo approfondire e mettere in pratica le modalità di risparmio energetico del microcontrollore ESP32.
Se avete già letto il mio articolo precedente link , saprete già le modalità di funzionamento per il risparmio energetico del microcontrollore ESP32.
Nel seguito dell’articolo vedremo come implementare il codice delle diverse modalità per ottenere risparmio energetico.
Le principali modalità per uscire dal risparmio energetico su ESP32
Per poter uscire dalle modalità di risparmio energetico, la CPU, in alcuni casi, non è alimentata, alcune parti hardware, per garantire il ripristino del sistema , devono essere sempre attive.
Le periferiche sono le seguenti:
- RTC controller
- ULP coprocessor
- RTC fast memory
- RTC slow memory
Touchpad
Il modulo RTC IO contiene la logica per la riattivazione delle periferiche quando si verifica una commutazione del sensore Touchpad.
Per risvegliare l’ESP da un’interruzione tramite il sensore Touchpad, bisogna prima configurarla tramite la funzione “esp_sleep_enable_touchpad_wakeup()” che abilita questa modalità di “risveglio”
Timer
Il modulo RTC ha un timer integrato che può essere utilizzato per riattivare il chip dopo un periodo di tempo predefinito.
La risoluzione effettiva dipende dalla sorgente di clock selezionata per RTC SLOW_CLK.
La funzione “esp_sleep_enable_timer_wakeup()” abilita il “risveglio” delle periferiche.
Il controller RTC può riattivare le funzioni del microcontrollore ESP32 , tramite la gestione di uno dei pin RTC GPIO impostato ad un livello predefinito.
Ci sono due possibili selezioni per riattivare il sistema:
- Riattivazione se uno dei pin selezionati è alto (ESP_EXT1_WAKEUP_ANY_HIGH)
- Riattivazione se tutti i pin selezionati sono bassi (ESP_EXT1_WAKEUP_ALL_LOW).
Per utilizzare i resistori pullup/pulldown interni, è necessario mantenere attivo il dominio di alimentazione delle periferiche RTC durante la sospensione e configurare i resistori pullup/pulldown utilizzando le funzioni:
- rtc_gpio_pullup_en()
- rtc_gpio_pulldown_en()
le funzioni sopra elencate devono essere chiamate prima della funzione “esp_deep_sleep_start()”.
GPIO (solo per Light-sleep)
In modalità Light-sleep oltre ai metodi di riattivazione EXT0 e EXT1, esiste un’altra opzione di risveglio da eventi esterni.
Ogni pin può essere impostato individualmente per la riattivazione del sistema tramite la funzione “gpio_wakeup_enable()“.
Questo metodo di riattivazione è diverso da EXT0 e EXT1, in quanto può essere utilizzata con qualsiasi I/O (sia RTC che digitale) anziché solo con I/O RTC.
Modalità di risparmio energetico
- Active
- Modem-Sleep
- Light-Sleep
- Deep-Sleep
- Hibernation
La modalità Active non ci offre risparmio energetico, ma ci permette di avere tutte le periferiche sempre attive e al massimo delle loro prestazioni.
Quindi, se non abbiamo limitazioni sul consumo di energia e abbiamo bisogno di avere tutto sempre a disposizione, con una risposta rapida, allora la modalità Active è quella che fa per noi.
Insomma, è una soluzione perfetta per chi cerca le massime prestazioni.
Modem-Sleep
Con questa modalità la CPU è sempre attiva, e la commutazione di tutte le periferiche wireless avviene in modo automatico e anche la velocità della CPU viene regolata automaticamente in base al carico di lavoro e all’utilizzo delle periferiche.
Questo processo avviene senza alcuna interazione da parte vostra.
L’ESP32 entra automaticamente nella modalità di sospensione delle periferiche wireless, quindi non esiste alcun metodo per accedere a questa modalità.
Questo significa che il sistema in piena autonomia gestirà questa modalità di funzionamento.
Codice Light-Sleep
#define uS_TO_S_FACTOR 1000000ULL /*convertiamo i us in secondi */ #define TIME_TO_SLEEP 5 /* il tempo in secondi in cui l'ESP32 va in sleep*/ int i; void print_wakeup_reason(){ esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); switch(wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Il risveglio è stato causato da: RTC_IO"); break; case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Il risveglio è stato causato da: RTC_CNTL"); break; case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Il risveglio è stato causato da: timer"); break; case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Il risveglio è stato causato da: touchpad"); break; case ESP_SLEEP_WAKEUP_ULP : Serial.println("Il risveglio è stato causato da: ULP"); break; default : Serial.printf("Il risveglio è stato causato da: deep sleep: %d\n",wakeup_reason); break; } } void setup(){ Serial.begin(9600); while (!Serial) { } } void loop(){ print_wakeup_reason(); //stampiamo sul terminale il motivo del risveglio i = 0; // istruzioni d'esempio while (i<=10){ Serial.println("istruzioni dimostrative"); Serial.println(i); i++; delay(500); } //fine istruzioni d'esempio esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // il timer è sttao impostato a 5 secondi Serial.println("L'ESP32 è andato in light-sleep"); Serial.flush(); esp_light_sleep_start(); }
#define uS_TO_S_FACTOR 1000000ULL
Questa definizione di macro in C indica che la costante “uS_TO_S_FACTOR” è impostata su 1000000ULL (che rappresenta 1000000 come numero intero senza segno a 64 bit).
Questa costante viene utilizzata per convertire microsecondi in secondi.
Ad esempio, moltiplicando un valore di tempo in microsecondi per questa costante otterrai il corrispondente valore in secondi.
#define TIME_TO_SLEEP 5
Definiamo il numero di secondi in cui il microcontrollore ESP32 deve rimare in “sleep”
esp_sleep_wakeup_cause_t wakeup_reason;
il tipo enumerativo “esp_sleep_wakeup_cause_t” definisce le diverse ragioni per cui un dispositivo può essere “risvegliato” da una modalità di risparmio energetico.
Ad esempio, potrebbe essere “risvegliato” a causa di un segnale dall’interfaccia RTC o da un segnale GPIO.
Questa variabile viene utilizzata per determinare il motivo per cui il microcontrollore è stato “risvegliato” e può essere utilizzata per prendere decisioni sul comportamento successivo del dispositivo.
wakeup_reason = esp_sleep_get_wakeup_cause();
Questa linea di codice chiama la funzione “esp_sleep_get_wakeup_cause()” per recuperare la ragione del risveglio del microcontrollore ESP.
La funzione restituisce un valore di tipo “esp_sleep_wakeup_cause_t” che viene assegnato alla variabile “wakeup_reason“
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println(“Il risveglio è stato causato da: RTC_IO”); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println(“Il risveglio è stato causato da: RTC_CNTL”); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println(“Il risveglio è stato causato da: timer”); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println(“Il risveglio è stato causato da: touchpad”); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println(“Il risveglio è stato causato da: ULP”); break;
default : Serial.printf(“Il risveglio è stato causato da: deep sleep: %d\n”,wakeup_reason); break;
}
Stampiamo sul terminale della seriale la causa del “risveglio”
// istruzioni d’esempio
while (i<=10){
Serial.println(“istruzioni dimostrative”);
Serial.println(i);
i++;
delay(500);
}
//fine istruzioni d’esempio
In questa parte di codice, potete inserire il volstro applicativo che verrà eseguito tra uno “sleep” e un “risveglio”
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Questa linea di codice chiama la funzione “esp_sleep_enable_timer_wakeup()” per abilitare il risveglio del microcontrollore ESP tramite un timer. La funzione accetta come argomento il tempo di sleep espresso in microsecondi, che è calcolato moltiplicando il valore di “TIME_TO_SLEEP” per la costante “uS_TO_S_FACTOR“. La funzione configura il timer interno del microcontrollore in modo che scatti dopo il tempo specificato e risvegli il dispositivo dalla modalità di risparmio energetico. Questo è utile per programmare il risveglio del dispositivo a intervalli regolari o per garantire che il dispositivo si risvegli dopo un certo periodo di tempo.
esp_light_sleep_start();
Questa linea di codice chiama la funzione attiva la modalità Light-sleep sul microcontrollore ESP.
L’utilizzo di questa modalità di funzionamento per l’ESP32 permette una significativa riduzione dell’assorbimento di corrente, che va dall’80% all’87%.
Se la tua applicazione può sfruttare questa modalità di funzionamento ed è alimentata da una batteria, potrai ottenere aumento dell’autonomia considerevole.
Deep-Sleep
Nella modalità Light-Sleep, il funzionamento del Core dell’’ESP32 Core è temporaneamente sospeso, ma esso è in grado di riprendere rapidamente il suo funzionamento non appena viene riattivato.
Tuttavia, in questa modalità, il Core l’ESP32 Core non è del tutto inattivo, ma possiamo definirla in stand by pronto a riattivarsi in tempi molto rapidi.
Al contrario, durante la modalità Deep-Sleep, il Core delll’ESP32 è completamente inattivo e soltanto il co-processore ULP e l’RTC sono ancora operativi.
Con questa modalità il consumo energetico minimo, poiché il Core dell’ESP32 è completamente spento e non assorbe corrente.
Questa modalità è molto utile in applicazioni che richiedono un funzionamento a lunga durata con batterie, poiché permette di estendere notevolmente la durata delle batterie.
Il codice per il Deep-Sleep è simile alla modalità precedente, ma bisogna sostituire esp_light_sleep_start(); con esp_deep_sleep_start();
Hibernation
La modalità Hibernation ha un’efficienza energetica ancora maggiore rispetto alle modalità precedenti.
In questa modalità, l’ESP32 assorbe solo 5 µA.
L’oscillatore interno a 8 MHz e il coprocessore ULP sono disattivati, così come la memoria di ripristino dell’RTC.
Solamente un timer RTC con il low clock e alcuni GPIO RTC sono attivi.
Il timer RTC o i GPIO RTC possono riattivare il microcontrollore.
Per attivare la modalità Hibernation , utilizziamo lo stesso codice scritto per le modalità descritte in precedenza, ma deselezioniamo tutte le periferiche RTC per renderle inattive.
Aggiungiamo solo questa riga di codice, prima dell’attivazione “esp_deep_sleep_start();“:
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
Conclusione
Non ho inserito le altre possibili disattivazione del ESP32 “sleep”, poichè basta cambiare solo l’istruzione di configurazione dell’interrupt.
Spero che le informazioni fornite siano fonti di ispirazione per nuovi progetti.
Se hai domande o osservazioni, sarò felice di aiutarti, lascia un commento di seguito.
Inoltre, ti invito a condividere i tuoi progetti e risultati con la comunità, in modo che possano essere di ispirazione per gli altri.
Buona fortuna con i tuoi progetti futuri!