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
Figura 1

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!

Lascia una risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ti sei iscritto alla newsletter

There was an error while trying to send your request. Please try again.

Quattrodispositivi utilizzerà le informazioni fornite in questo modulo per restare in contatto con te e fornire aggiornamenti del sito