ESP32 risparmio energetico pratico: preservare i dati, sveglia a tempo e tramite tocco – 4

Spread the love

Con l’esp32, quando si utilizza un sonno leggero, un sonno profondo o uno stato di ibernazione, è necessario selezionare la sorgente di risveglio per far tornare attivo il dispositivo.

ESP32 practical power saving preserve data on deep sleep timer and touch wake-up
ESP32 practical power saving preserve data on deep sleep timer and touch wake-up

Ci sono molte soluzioni, alcune sono standard RTC o esterne, altre sono new entry come touch o ULP.

Se hai già letto il capitolo precedente, sai che ci sono alcune grandi differenze nel consumo di energia se selezioni una fonte di sveglia esterna o timer, quindi fai attenzione alla tua scelta.

Ma (e ora pensi che io sia noioso) devi prestare attenzione anche al tipo di modalità di sonno che usi, perché il sonno leggero ha più tipi di risveglio rispetto alle altre e può tornarti utile.

Conservare i dati durante la sospensione profonda e caricare del codice dopo la riattivazione

Per il seguente test utilizzo il Serial2 per il debug puoi trovare maggiori informazioni in questo articolo “ESP32: gestire più seriali e logging per il debug“.

Qui lo schema di connessione per utilizzare un FDTI esterno su Serial2.

esp32 DOIT DEV KIT v1 Serial2 UART2 ttl to usb schema
esp32 DOIT DEV KIT v1 Serial2 UART2 ttl to usb schema

Il pezzetto di codice wake deve essere residente nella memoria rapida RTC. Questo può essere fatto in due modi.

Function Block diagram Espressif esp32 Wi-Fi Bluetooth Microcontroller
Function Block diagram Espressif esp32 Wi-Fi Bluetooth Microcontroller

Il primo modo è utilizzare l’attributo  RTC_IRAM_ATTR per inserire una funzione nella memoria RTC:

void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
    esp_default_wake_deep_sleep();
    // Add additional functionality here
}

Il secondo modo è inserire la funzione in qualsiasi file sorgente il cui nome inizia con  rtc_wake_stub. I nomi dei file  rtc_wake_stub* hanno il loro contenuto automaticamente inserito nella memoria RTC dal linker.

Conservare i dati durante la sospensione profonda può essere fatto in due modi, ma il più semplice è usare  RTC_DATA_ATTR e  RTC_RODATA_ATTR per specificare tutti i dati (scrivibili o di sola lettura, rispettivamente) che devono essere caricati nella memoria RTC:

// preserve data
RTC_DATA_ATTR int wake_count;

void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
    esp_default_wake_deep_sleep();
    // increment data after wake
    wake_count++;
}

Qui uno sketch completo per verificarne il comportamento

/*
 *  ESP32
 *  Variable behaivor in DEEP Sleep
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org/it/esp32-risparmio-energetico-pratico-preservare-i-dati-sveglia-a-tempo-e-tramite-tocco-4/
 *
 */
#include "Arduino.h"

// Preserved value
RTC_DATA_ATTR int wake_count = 0;
RTC_DATA_ATTR int wake_count2 = 0;
// Not preserved
int wake_count3 = 0;

// Call function every wake
void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
    esp_default_wake_deep_sleep();
    // increment every wake
    wake_count2++;
}

void setup()
{
	  ++wake_count;
	  ++wake_count3;

	Serial2.begin(115200);

	while(!Serial2){delay(500);}

	Serial2.println("Wake count in setup: " + String(wake_count));
	Serial2.println("Wake count2 in setup: " + String(wake_count2));
	Serial2.println("Wake count3 in setup: " + String(wake_count3));

    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");
}

void loop()
{

}

Ecco il risultato della Serial2:

Wake count in setup: 1
Wake count2 in setup: 0
Wake count3 in setup: 1

DEEP SLEEP ENABLED FOR 5secs
Wake count in setup: 2
Wake count2 in setup: 1
Wake count3 in setup: 1

DEEP SLEEP ENABLED FOR 5secs
Wake count in setup: 3
Wake count2 in setup: 2
Wake count3 in setup: 1

DEEP SLEEP ENABLED FOR 5secs
Wake count in setup: 4
Wake count2 in setup: 3
Wake count3 in setup: 1

DEEP SLEEP ENABLED FOR 5secs

Tipi di sveglia

Puoi ottenere alcune informazioni quando lo Sketch si riavvia dal sonno profondo, il primo è la fonte di risveglio e puoi verificarlo con questi comandi

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
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 : Serial2.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial2.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial2.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial2.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial2.println("Wakeup caused by ULP program"); break;
    default : Serial2.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

e quando selezioni una particolare fonte di risveglio, you may have commands to retrieve other information, but we’ll see that soon.

Timer

Il controller RTC ha un timer integrato che può essere utilizzato per riattivare il chip dopo un periodo di tempo predefinito. Il tempo è specificato con una precisione al microsecondo, ma la risoluzione effettiva dipende dalla sorgente di clock selezionata per RTC SLOW_CLK.

Questa modalità di attivazione non richiede l’ accensione delle periferiche RTC o delle memorie RTC durante il sonno (controlla l’articolo precedente per capire quali sono i vantaggi) .

esp_err_tesp_sleep_enable_timer_wakeup(uint64_t time_in_us)

Abilita la sveglia tramite timer.

Return

  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if value is out of range

Parameters

  • time_in_us: time before wakeup, in microseconds (time_in_us * 1000 = milliseconds * 1000 = seconds)

Qui lo sketch completo:

/*
 *  ESP32
 *  DEEP Sleep and timer wake up
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org/it/esp32-risparmio-energetico-pratico-preservare-i-dati-sveglia-a-tempo-e-tramite-tocco-4/
 *
 */

#define TIME_TO_SLEEP  5        	/* Time ESP32 will go to sleep (in seconds) */

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
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 : Serial2.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial2.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial2.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial2.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial2.println("Wakeup caused by ULP program"); break;
    default : Serial2.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup(){
  Serial2.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial2.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 1000 * 1000);
  Serial2.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");

  Serial2.println("Going to sleep now");
  Serial2.flush();
  esp_deep_sleep_start();
  Serial2.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

Il risultato è:

Boot number: 1
Wakeup was not caused by deep sleep: 0
Setup ESP32 to sleep for every 5 Seconds 
Going to sleep now
Boot number: 2
Wakeup caused by timer
Setup ESP32 to sleep for every 5 Seconds
Going to sleep now
Boot number: 3

Touch

Il modulo RTC IO contiene la logica per attivare la sveglia quando si verifica un interrupt del sensore tattile. È necessario configurare l’interruzione del touch pad prima che il chip inizi la sospensione profonda.

esp32 DOIT DEV KIT v1 Serial2 FTDI and touch on breadboard
esp32 DOIT DEV KIT v1 Serial2 FTDI and touch on breadboard

Le revisioni 0 e 1 dell’ESP32 supportano questa modalità di attivazione solo quando le periferiche RTC non sono forzate ad essere accese.

esp_err_t esp_deep_sleep_enable_touchpad_wakeup()

Abilita la sveglia tramite sensore tattile.

Nota : nelle revisioni 0 e 1 dell’ESP32, la sorgente di riattivazione tattile non può essere utilizzata quando il dominio di alimentazione RTC_PERIPH è forzato per essere acceso (ESP_PD_OPTION_ON) o quando viene utilizzata la sorgente di riattivazione ext0.

Return

  • ESP_OK on success
  • ESP_ERR_INVALID_STATE if wakeup triggers conflict

E c’è una funzione per impostare il corretto touch pin di sveglia

void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold);

Seleziona il pin touch corretto e definisce la callback e la soglia.

Per ulteriori informazioni sul dispositivo fare riferimento a “DOIT ESP32 DEV KIT v1 immagine di piedinatura ad alta risoluzione e specifiche“.

Qui il codice dei pin touch

  • T0: GPIO 4
  • T1: GPIO 0
  • T2: GPIO 2
  • T3: GPIO 15
  • T4: GPIO 13
  • T5: GPIO 12
  • T6: GPIO 14
  • T7: GPIO 27
  • T8: GPIO 33
  • T9: GPIO 32

C’è un comando per controllare quali pin sono stati toccati

/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();

  switch(touchPin)
  {
    case 0  : Serial2.println("Touch detected on GPIO 4"); break;
    case 1  : Serial2.println("Touch detected on GPIO 0"); break;
    case 2  : Serial2.println("Touch detected on GPIO 2"); break;
    case 3  : Serial2.println("Touch detected on GPIO 15"); break;
    case 4  : Serial2.println("Touch detected on GPIO 13"); break;
    case 5  : Serial2.println("Touch detected on GPIO 12"); break;
    case 6  : Serial2.println("Touch detected on GPIO 14"); break;
    case 7  : Serial2.println("Touch detected on GPIO 27"); break;
    case 8  : Serial2.println("Touch detected on GPIO 33"); break;
    case 9  : Serial2.println("Touch detected on GPIO 32"); break;
    default : Serial2.println("Wakeup not by touchpad"); break;
  }
}

Molto semplice ma molto importante, e lo sketch completo:

/*
 *  ESP32
 *  DEEP Sleep and touch wake up
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org/it/esp32-risparmio-energetico-pratico-preservare-i-dati-sveglia-a-tempo-e-tramite-tocco-4/
 *
 */

#define Threshold 60 /* Greater the value, more the sensitivity */

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
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 : Serial2.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial2.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial2.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial2.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial2.println("Wakeup caused by ULP program"); break;
    default : Serial2.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();

  switch(touchPin)
  {
    case 0  : Serial2.println("Touch detected on GPIO 4"); break;
    case 1  : Serial2.println("Touch detected on GPIO 0"); break;
    case 2  : Serial2.println("Touch detected on GPIO 2"); break;
    case 3  : Serial2.println("Touch detected on GPIO 15"); break;
    case 4  : Serial2.println("Touch detected on GPIO 13"); break;
    case 5  : Serial2.println("Touch detected on GPIO 12"); break;
    case 6  : Serial2.println("Touch detected on GPIO 14"); break;
    case 7  : Serial2.println("Touch detected on GPIO 27"); break;
    case 8  : Serial2.println("Touch detected on GPIO 33"); break;
    case 9  : Serial2.println("Touch detected on GPIO 32"); break;
    default : Serial2.println("Wakeup not by touchpad"); break;
  }
}

void callback(){
  //placeholder callback function
}

void setup(){
  Serial2.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial2.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32 and touchpad too
  print_wakeup_reason();
  print_wakeup_touchpad();

  //Setup interrupt on Touch Pad 6 (GPIO14)
  touchAttachInterrupt(T6, callback, Threshold);

  //Setup interrupt on Touch Pad 7 (GPIO27)
  touchAttachInterrupt(T7, callback, Threshold);


  //Configure Touchpad as wakeup source
  esp_sleep_enable_touchpad_wakeup();

  //Go to sleep now
  Serial2.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial2.println("This will never be printed");
}

void loop(){
  //This will never be reached
}

e qui un pezzo dell’output della Serial2:

Boot number: 3
Wakeup caused by touchpad
Touch detected on GPIO 14
Going to sleep now
Boot number: 4
Wakeup caused by touchpad
Touch detected on GPIO 27
Going to sleep now
Boot number: 5

Grazie

  1. ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
  2. ESP32: fileSystem integrato SPIFFS
  3. ESP32: gestire più seriali e logging per il debug
  4. ESP32 risparmio energetico pratico
    1. ESP32 risparmio energetico pratico: gestire WiFi e CPU
    2. ESP32 risparmio energetico pratico: modem e light sleep
    3. ESP32 risparmio energetico pratico: deep sleep e ibernazione
    4. ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
    5. ESP32 risparmio energetico pratico: sveglia esterna e da ULP
    6. ESP32 risparmio energetico pratico: sveglia da UART e GPIO
  5. ESP32: filesystem integrato LittleFS
  6. ESP32: filesystem integrato FFat (Fat/exFAT)
  7. ESP32-wroom-32
    1. ESP32-wroom-32: flash, piedinatura, specifiche e configurazione dell’Arduino IDE
  8. ESP32-CAM
    1. ESP32-CAM: piedinatura, specifiche e configurazione dell’Arduino IDE
    2. ESP32-CAM: upgrade CamerWebServer con gestione della luce flash
  9. ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
  10. ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
  11. Come usare la scheda SD con l’esp32
  12. esp32 e esp8266: file system FAT su memoria SPI flash esterna
  13. Gestione aggiornamenti firmware e OTA
    1. Gestione del firmware
      1. ESP32: flash del firmware binario compilato (.bin)
      2. ESP32: flash del firmware e filesystem (.bin) con strumenti grafici
    2. Aggiornamento OTA con Arduino IDE
      1. Aggiornamenti OTA su ESP32 con Arduino IDE: filesystem, firmware e password
    3. Aggiornamento OTA con browser web
      1. Aggiornamenti OTA su ESP32 tramite browser web: firmware, filesystem e autenticazione
      2. Aggiornamenti OTA su ESP32 tramite browser web: caricamento in HTTPS (SSL/TLS) con certificato autofirmato
      3. Aggiornamenti OTA su ESP32 tramite browser web: interfaccia web personalizzata
    4. Aggiornamenti automatici OTA da un server HTTP
      1. Aggiornamento automatico Firmware OTA dell’ESP32 dal server
      2. Aggiornamento automatico Firmware OTA dell’ESP32 dal server con controllo della versione
      3. Aggiornamento automatico Firmware OTA dell’ESP32 in HTTPS (SSL/TLS) con certificato autofirmato affidabile
    5. Aggiornamento del firmware non standard
      1. Aggiornamento firmware e filesystem ESP32 dalla scheda SD
      2. Aggiornamento firmware e filesystem ESP32 con client FTP
  14. Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
  15. i2c esp32: gestione rete a 5v, 3.3v e interfaccia aggiuntiva
  16. […]

Spread the love

Lascia un commento

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