ESP32 Deep Sleep y sus fuentes de estela

¿Estás buscando formas de maximizar la duración de la batería de tu dispositivo ESP32? En este artículo, exploraremos en detalle la función de Deep Sleep (sueño profundo) del ESP32 y sus distintas fuentes de consumo de energía. ¡Descubre cómo puedes prolongar la duración de la batería de tu dispositivo utilizando esta función clave!

Si su proyecto de IoT funciona con un adaptador de pared, no le importa el consumo de energía. Sin embargo, si ejecuta su proyecto con una batería, cada mA cuenta.

ESP32 puede ser un dispositivo que consume relativamente mucha energía dependiendo de su condición. En funcionamiento normal suele consumir unos 75 mA y unos 240 mA al transferir datos vía WiFi.

La solución es reducir el consumo de energía del ESP32 mediante el uso del modo de suspensión profunda.

Para obtener más información sobre los otros modos de suspensión del ESP32 y su consumo de energía, visite el tutorial a continuación.

ESP32 Deep Sleep y sus fuentes de estela
Información sobre los modos de suspensión ESP32 y su consumo de energía
El ESP32 es sin duda un digno competidor de muchos SoC WiFi/MCU, superándolos tanto en rendimiento como en precio. Sin embargo, depende de qué modo sea…

ESP32 sueño profundo

En el modo de suspensión profunda, las CPU, la mayor parte de la RAM y todos los periféricos digitales están apagados. Las únicas partes del chip que todavía están operativas son:

  • coprocesador ULP
  • controlador RTC
  • Periféricos RTC
  • Memoria RTC rápida y lenta

El chip consume aproximadamente 0,15 mA (cuando el coprocesador ULP está encendido) a 10 µA.

ESP32 Deep Sleep y sus fuentes de estela

En el modo de suspensión profunda, la CPU principal se apaga mientras el coprocesador UltraLowPower (ULP) puede recopilar lecturas del sensor y reactivar la CPU cuando sea necesario. Este patrón de sueño se conoce como Patrón monitoreado por sensor ULP. Esto es útil para desarrollar aplicaciones que requieren que la CPU se active mediante un evento externo, un temporizador o una combinación de ambos, manteniendo al mismo tiempo el consumo de energía al mínimo.

Además de la CPU, también se desactiva la memoria principal del chip. Esto eliminará todo lo almacenado en ese almacenamiento y lo hará inaccesible.


Debido a que la memoria RTC permanece encendida, su contenido se retiene incluso en estado de sueño profundo y se puede recuperar después de que se activa el chip. Por este motivo, el chip almacena los datos de conexión WiFi y Bluetooth en la memoria RTC antes de entrar en modo de sueño profundo.

Si desea utilizar los datos después del reinicio, guárdelos en la memoria RTC definiendo una variable global con RTC_DATA_ATTR Atributo. Por ejemplo, RTC_DATA_ATTR int myVar = 0;

Después de despertarse del sueño profundo, el chip se reinicia con un reinicio y comienza la ejecución del programa desde el principio.


ESP32 admite la ejecución de un Trozo de sueño-vigilia profundo cuando te despiertas de un sueño profundo. Esta función se ejecuta inmediatamente tan pronto como el chip se activa, antes de que se haya ejecutado cualquier inicialización normal, gestor de arranque o código ESP-IDF. Después de ejecutar el resguardo, el chip puede volver a dormir o continuar arrancando ESP-IDF normalmente.

A diferencia de otros modos de suspensión, el sistema no puede ingresar automáticamente al modo de suspensión profunda. El esp_deep_sleep_start() La función se utiliza para entrar en sueño profundo inmediatamente después de configurar las fuentes de activación.

Fuentes de activación del sueño profundo ESP32

El ESP32 se puede reactivar desde el modo de suspensión profunda a través de múltiples fuentes. Estas fuentes son:

  • Temporizador
  • Panel táctil
  • Activación externa (ext0 y ext1)

Se pueden combinar múltiples fuentes de alarma. En este caso, el chip se activa cuando se activa una de las fuentes.

Advertencia:

Es posible poner el ESP32 en modo de suspensión profunda sin configurar ninguna fuente de activación. En este caso, el chip permanecerá en modo de suspensión profunda indefinidamente hasta que se realice un reinicio externo.

Fuente de activación ESP32: temporizador

El controlador ESP32 RTC tiene un temporizador incorporado que le permite activar el ESP32 después de un período de tiempo predefinido.

Esta característica es particularmente útil para proyectos que requieren marcas de tiempo o tareas diarias y al mismo tiempo garantizan un bajo consumo de energía.

El esp_sleep_enable_timer_wakeup(time_in_us) La función se utiliza para configurar el temporizador como fuente de despertador. Esta función acepta un período de tiempo en microsegundos (μs).

Código de ejemplo

Veamos cómo funciona con un ejemplo de la biblioteca. Abra su IDE de Arduino, navegue hasta Archivo> Ejemplos> ESP32> Deep Sleep y abra el Croquis TimerWakeUp.

Este boceto muestra el ejemplo de sueño profundo más simple con un temporizador como fuente de activación y cómo se almacenan los datos en la memoria RTC para su uso después de un reinicio.

#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
#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 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

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

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.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 * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");

  /*
  Next we decide what all peripherals to shut down/keep on
  By default, ESP32 will automatically power down the peripherals
  not needed by the wakeup source, but if you want to be a poweruser
  this is for you. Read in detail at the API docs
  http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
  Left the line commented as an example of how to configure peripherals.
  The line below turns off all RTC peripherals in deep sleep.
  */
  //esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  //Serial.println("Configured all RTC Peripherals to be powered down in sleep");

  /*
  Now that we have setup a wake cause and if needed setup the
  peripherals state in deep sleep, we can now start going to
  deep sleep.
  In the case that no wake up sources were provided but deep
  sleep was started, it will sleep forever unless hardware
  reset occurs.
  */
  Serial.println("Going to sleep now");
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

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

Una vez cargado el boceto, abra su monitor serie y establezca la velocidad en baudios en 115200 bps.

El ESP32 se despierta cada 5 segundos, muestra el motivo de la activación y el recuento de arranque en el monitor serie y vuelve al modo de suspensión profunda.

ESP32 Deep Sleep y sus fuentes de estela

Ahora intente restablecer el ESP32 presionando el botón EN. BootCount debería restablecerse a 1, lo que indica que la memoria RTC se ha borrado por completo.

Explicación del código:

Estas dos primeras líneas de código definen el tiempo durante el cual ESP32 duerme.

Este ejemplo utiliza el factor de conversión de microsegundos a segundos, lo que le permite establecer el tiempo de descanso en segundos. TIME_TO_SLEEP Variable. El ESP32 se pone en modo de suspensión profunda durante 5 segundos.

#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* Time ESP32 will go to sleep (in seconds) */

Como se mencionó anteriormente, puede almacenar datos en la memoria RTC del ESP32 (8KB SRAM) que no se eliminarán durante el sueño profundo. Sin embargo, se eliminará cuando se reinicie el ESP32.

Para guardar datos en el almacenamiento RTC, solo necesita agregar RTC_DATA_ATTR Atributo antes de definir una variable. En este ejemplo el bootCount La variable se almacena en la memoria RTC. Se cuenta el número de veces que ESP32 se despertó del sueño profundo.


RTC_DATA_ATTR int bootCount = 0;

Siguiente esto print_wakeup_reason() Se define una función que devuelve el motivo por el cual ESP32 se despertó del sueño profundo.

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("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

En la configuración primero inicializamos la comunicación serie con la PC.

Serial.begin(115200);

El bootCount Luego, la variable se incrementa en uno y se envía al monitor en serie para mostrar cuántas veces el ESP32 se despertó del sueño profundo.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Entonces eso es todo print_wakeup_reason() Se llama a la función, pero puede llamar a cualquier función para realizar la tarea que desee, como leer el valor de un sensor.

print_wakeup_reason();

A continuación, configuramos la fuente del despertador del temporizador usando esp_sleep_enable_timer_wakeup(time_in_us) Función. Aquí el ESP32 está configurado para activarse cada 5 segundos.

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Finalmente, llamar al ESP32 lo pondrá en suspensión. esp_deep_sleep_start() Función.


esp_deep_sleep_start();

En este boceto, el ESP32 entra en modo de suspensión profunda en la función setup(), por lo que nunca alcanza la función loop(). De ahí esto loop() La función permanece vacía.

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

Fuente de activación ESP32: panel táctil

Puede despertar ESP32 del sueño profundo usando los siguientes pines táctiles.

ESP32 Deep Sleep y sus fuentes de estela

Es fácil activar el ESP32 mediante el pin táctil para despertarlo. En el IDE de Arduino solo necesitas usar esp_sleep_enable_touchpad_wakeup() Función.

alambrado

Conectemos un cable al GPIO#15 (Touch#3) que servirá como fuente de activación táctil. Puede conectar cualquier objeto conductor, como alambre, papel de aluminio, tela conductora, pintura conductora, etc., al lápiz táctil y convertirlo en un panel táctil.

ESP32 Deep Sleep y sus fuentes de estela

Código de ejemplo

Veamos cómo funciona con un ejemplo de la biblioteca. Abra su IDE de Arduino, navegue hasta Archivo> Ejemplos> ESP32> Deep Sleep y abra el Boceto TouchWakeUp.

Este boceto muestra el ejemplo de sueño profundo más simple utilizando el tacto como fuente de activación y cómo se almacenan los datos en la memoria RTC para su uso después de un reinicio.

#define Threshold 40 /* 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 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",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  : Serial.println("Touch detected on GPIO 4"); break;
    case 1  : Serial.println("Touch detected on GPIO 0"); break;
    case 2  : Serial.println("Touch detected on GPIO 2"); break;
    case 3  : Serial.println("Touch detected on GPIO 15"); break;
    case 4  : Serial.println("Touch detected on GPIO 13"); break;
    case 5  : Serial.println("Touch detected on GPIO 12"); break;
    case 6  : Serial.println("Touch detected on GPIO 14"); break;
    case 7  : Serial.println("Touch detected on GPIO 27"); break;
    case 8  : Serial.println("Touch detected on GPIO 33"); break;
    case 9  : Serial.println("Touch detected on GPIO 32"); break;
    default : Serial.println("Wakeup not by touchpad"); break;
  }
}

void callback(){
  //placeholder callback function
}

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

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.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 3 (GPIO15)
  touchAttachInterrupt(T3, callback, Threshold);

  //Configure Touchpad as wakeup source
  esp_sleep_enable_touchpad_wakeup();

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

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

Una vez cargado el boceto, abra su monitor serie y establezca la velocidad en baudios en 115200 bps.

Ahora, cuando se toca el pin, el ESP32 muestra el recuento de inicio, el motivo del despertar y el GPIO tocado en el monitor serie.

ESP32 Deep Sleep y sus fuentes de estela

Explicación del código:

La primera línea de código establece el umbral del pin táctil en 40. Cuanto mayor sea el umbral, mayor será la sensibilidad. Puede cambiar este valor según su proyecto.

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

Como se mencionó anteriormente, puede almacenar datos en la memoria RTC del ESP32 (8KB SRAM) que no se eliminarán durante el sueño profundo. Sin embargo, se eliminará cuando se reinicie el ESP32.

Para guardar datos en el almacenamiento RTC, solo necesita agregar RTC_DATA_ATTR Atributo antes de definir una variable. En este ejemplo el bootCount La variable se almacena en la memoria RTC. Se cuenta el número de veces que ESP32 se despertó del sueño profundo.

RTC_DATA_ATTR int bootCount = 0;

Luego una variable llamada touchPin de tipo touch_pad_t (tipo enum), que luego nos servirá para imprimir el GPIO a través del cual ESP32 despertará del modo de suspensión.

touch_pad_t touchPin;

Siguiente esto print_wakeup_reason() Se define una función que devuelve el motivo por el cual ESP32 se despertó del sueño profundo.

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("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

El print_wakeup_touchpad() También hay una función definida que devuelve el número GPIO utilizado para despertar a ESP32 del sueño profundo.

void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();

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

siguiente un callback() La función está definida. Esto no es más que una Rutina de Servicio de Interrupción (ISR) que se llama cada vez que se activa una interrupción táctil. Desafortunadamente, esta función no se ejecuta cuando ESP32 está en suspensión profunda. Por lo tanto esta función permanece vacía.

void callback(){
  //placeholder callback function
}

En la configuración primero inicializamos la comunicación serie con la PC.

Serial.begin(115200);

El bootCount Luego, la variable se incrementa en uno y se envía al monitor en serie para mostrar cuántas veces el ESP32 se despertó del sueño profundo.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Entonces eso es todo print_wakeup_reason() Y print_wakeup_touchpad() Se llaman funciones, pero puede llamar a cualquier función para realizar la tarea que desee, como leer el valor de un sensor.


print_wakeup_reason();
print_wakeup_touchpad();

Ahora la interrupción debe conectarse a uno de los pines táctiles con el umbral de sensibilidad deseado. Aquí la interrupción está conectada al panel táctil 3 (GPIO15).

touchAttachInterrupt(T3, callback, Threshold);

A continuación, configuramos la fuente de activación táctil usando esp_sleep_enable_touchpad_wakeup() Función.

esp_sleep_enable_touchpad_wakeup();

Finalmente, llamar al ESP32 lo pondrá en suspensión. esp_deep_sleep_start() Función.

esp_deep_sleep_start();

En este boceto, el ESP32 entra en sueño profundo. setup() funciona por sí solo, por lo que nunca lo alcanza loop() Función. De ahí esto loop() La función permanece vacía.

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

Fuente de activación ESP32: activación externa

Hay dos tipos de activadores externos para despertar al ESP32 del sueño profundo.

  • ext0: use esto si solo desea habilitar el chip a través de un pin GPIO específico.
  • ext1: use esto si desea habilitar el chip con múltiples pines GPIO.

Si desea utilizar un pin de interrupción para despertar a ESP32 del sueño profundo, debe utilizar el llamado pin de interrupción Pines RTC_GPIO. Estos GPIO se reenvían al subsistema de baja potencia RTC para que puedan usarse cuando el ESP32 está en suspensión profunda.

Los pines RTC_GPIO son:

ESP32 Deep Sleep y sus fuentes de estela

ext0 Fuente de activación externa

El ESP32 se puede configurar para despertarse del sueño profundo cuando uno de los pines RTC_GPIO cambia su nivel lógico.

El esp_sleep_enable_ext0_wakeup(GPIO_PIN, LOGIC_LEVEL) La función se utiliza para activar esta fuente de alarma. Esta función requiere dos parámetros. El primero es el número de pin GPIO y el segundo es el nivel lógico (BAJO o ALTO) a través del cual queremos activar el despertar.

Dado que ext0 usa RTC IO para activar ESP32, los periféricos RTC permanecen activos en el sueño profundo.

Y dado que el módulo RTC-IO está habilitado, puede usar las resistencias pullup o pulldown internas. Deben configurarse con rtc_gpio_pullup_en() Y rtc_gpio_pulldown_en() funciones esp_deep_sleep_start() se llama.

alambrado

Conectemos un pulsador con una resistencia desplegable de 10K al GPIO#33.

ESP32 Deep Sleep y sus fuentes de estela

Código de ejemplo

Veamos cómo funciona con un ejemplo de la biblioteca. Abra su IDE de Arduino, navegue hasta Archivo> Ejemplos> ESP32> Deep Sleep y abra el Bosquejo de WakeUp externo.

Este boceto muestra el ejemplo de sueño profundo más simple con un ext0 como fuente de activación.

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

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 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

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

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.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 for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so doesnt need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  //esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

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

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

Una vez cargado el boceto, abra su monitor serie y establezca la velocidad en baudios en 115200 bps.

Ahora, cuando presione el botón, el ESP32 mostrará el número de inicio y el motivo de activación en el monitor serie. Pruébelo varias veces y observe cómo aumenta el recuento inicial con cada pulsación de tecla. También tenga en cuenta que ext0 usa RTC IO para activar el ESP32.

ESP32 Deep Sleep y sus fuentes de estela

Explicación del código:

La primera línea de código establece la máscara de bits. No es necesario para la activación externa de ext0, por lo que puedes ignorarlo por ahora. Aprenderemos sobre esto como parte de la explicación del código de activación externo para ext1.

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

Como se mencionó anteriormente, puede almacenar datos en la memoria RTC del ESP32 (8KB SRAM) que no se eliminarán durante el sueño profundo. Sin embargo, se eliminará cuando se reinicie el ESP32.

Para guardar datos en el almacenamiento RTC, solo necesita agregar RTC_DATA_ATTR Atributo antes de definir una variable. En este ejemplo el bootCount La variable se almacena en la memoria RTC. Se cuenta el número de veces que ESP32 se despertó del sueño profundo.

RTC_DATA_ATTR int bootCount = 0;

Siguiente esto print_wakeup_reason() Se define una función que devuelve el motivo por el cual ESP32 se despertó del sueño profundo.

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("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

En la configuración primero inicializamos la comunicación serie con la PC.

Serial.begin(115200);

El bootCount Luego, la variable se incrementa en uno y se envía al monitor en serie para mostrar cuántas veces el ESP32 se despertó del sueño profundo.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Entonces eso es todo print_wakeup_reason() Se llama a la función, pero puede llamar a cualquier función para realizar la tarea que desee, como leer el valor de un sensor.

print_wakeup_reason();

Ahora la fuente de activación externa está configurada usando ext0 esp_sleep_enable_ext0_wakeup(GPIO_PIN, LOGIC_LEVEL) Función. Esta función requiere dos parámetros. El primero es el número de pin GPIO y el segundo es el nivel lógico (BAJO o ALTO) a través del cual queremos activar el despertar. En este ejemplo, el ESP32 está configurado para activarse cuando el nivel lógico de GPIO#33 pasa a ALTO.

esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);

Finalmente, llamar al ESP32 lo pondrá en suspensión. esp_deep_sleep_start() Función.

esp_deep_sleep_start();

En este boceto, el ESP32 entra en sueño profundo. setup() funciona por sí solo, por lo que nunca lo alcanza loop() Función. De ahí esto loop() La función permanece vacía.

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

ext1 Fuente de activación externa

El ESP32 se puede configurar para despertarse del sueño profundo usando múltiples pines. Recuerda que estos pines deben pertenecer a los pines RTC GPIO.

Dado que la fuente de activación ext1 utiliza un controlador RTC, no es necesario que los periféricos RTC ni la memoria RTC estén encendidos. En este caso, las resistencias pullup y pulldown internas no están disponibles.

Para usar las resistencias pullup o pulldown internas, debemos solicitar que los periféricos RTC permanezcan encendidos durante el modo de suspensión y configurar las resistencias pullup/pulldown usando rtc_gpio_pullup_en() Y rtc_gpio_pulldown_en() Funciones antes de quedarse dormido.

El esp_sleep_enable_ext1_wakeup(BUTTON_PIN_MASK, LOGIC_LEVEL) La función se utiliza para activar esta fuente de alarma. Esta función requiere dos parámetros. El primero es una máscara de bits que le dice al ESP32 qué pines queremos usar y el segundo parámetro puede ser uno de los dos niveles lógicos mencionados a continuación para activar el despertar:

  • Despiértate cuando uno de los pines seleccionados esté ALTO (ESP_EXT1_WAKEUP_ANY_HIGH)
  • Despierta cuando todos los pines seleccionados estén BAJOS (ESP_EXT1_WAKEUP_ALL_LOW)

máscara de bits

La forma más sencilla de comprender la máscara de bits es escribirla en formato binario. Puede ver que la numeración de bits se basa en la numeración GPIO normal. El bit menos significativo (LSB) representa GPIO#0 y el bit más significativo (MSB) representa GPIO#39.

ESP32 Deep Sleep y sus fuentes de estela

  • 0 representa alfileres enmascarados
  • 1 representa pines que se activan como fuente de activación

Entonces, si desea habilitar la reactivación de un GPIO, debe escribir un 1 en la ubicación correspondiente y un 0 en cada uno de los pines restantes. Y finalmente necesitas convertirlo a HEX.

Por ejemplo, si desea utilizar GPIO#32 y GPIO#33 como fuentes de activación externas, la máscara de bits se vería así:

ESP32 Deep Sleep y sus fuentes de estela

alambrado

Conectemos los dos botones a GPIO#33 y GPIO#32 usando resistencias desplegables de 10K.

ESP32 Deep Sleep y sus fuentes de estela

Código de ejemplo

Veamos cómo funciona usando el mismo ejemplo de ExternalWakeUp de la biblioteca. Abra su IDE de Arduino nuevamente, navegue hasta Archivo> Ejemplos> ESP32> Deep Sleep y abra el Boceto de activación externa.

Hagamos tres cambios en el boceto para que nos funcione:

  1. Cambiar la constante BUTTON_PIN_BITMASK
  2. Comenta el código para ext0.
  3. Comentar el código para ext1

Los cambios en el boceto se resaltan enVerde.

#define BUTTON_PIN_BITMASK 0x300000000

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 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %dn",wakeup_reason); break;
  }
}

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

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.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 for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so doesnt need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  //esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

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

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

Una vez cargado el boceto, abra su monitor serie y establezca la velocidad en baudios en 115200 bps.

Ahora, cuando presione el botón, obtendrá algo similar en el monitor serie. También tenga en cuenta que ext1 usa el controlador RTC para activar el ESP32.

ESP32 Deep Sleep y sus fuentes de estela

Explicación del código:

Este código es idéntico al código de ext0 excepto por dos cambios.

La máscara de bits se define al principio del código. Dado que en el ejemplo utilizamos los pines GPIO#32 y GPIO#33, la máscara tiene unos en sus respectivas posiciones, con 32 ceros en el lado derecho y 6 ceros en el lado izquierdo.

00000011 00000000 00000000 00000000 00000000 ENVASE = 0x300000000 MALEFICIO

#define BUTTON_PIN_BITMASK 0x300000000

Y finalmente ext1 se activa como fuente de activación.

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);


Error 403 The request cannot be completed because you have exceeded your quota. : quotaExceeded

ESP32 Deep Sleep y sus fuentes de estela

En un proyecto de IoT alimentado por un adaptador de pared, no suele importar mucho el consumo de energía. Pero si vas a alimentar tu proyecto con una batería, cada mA cuenta.

El ESP32 puede ser un dispositivo relativamente hambriento de energía dependiendo del estado en el que se encuentre. Normalmente consume alrededor de 75 mA para operaciones normales y alrededor de 240 mA cuando transmite datos a través de WiFi.

La solución aquí es reducir el consumo de energía del ESP32 aprovechando el Modo de Deep Sleep.

Para conocer más sobre otros modos de sueño del ESP32 y su consumo de energía, por favor visita el tutorial a continuación.

Visión general de los modos de sueño del ESP32 y su consumo de energía

El ESP32 es sin duda un competidor digno para muchos SoCs WiFi/MCU, superándolos tanto en rendimiento como en precio. Sin embargo, dependiendo del modo en el que se encuentre…

ESP32 Deep Sleep

En el modo de deep sleep, las CPUs, la mayor parte de la RAM y todos los periféricos digitales se apagan. Las únicas partes del chip que permanecen operativas son:

  1. Coprocesador ULP
  2. Controlador RTC
  3. Periféricos RTC
  4. Memoria RTC rápida y lenta

El chip consume alrededor de 0.15 mA (si el coprocesador ULP está activado) a 10 µA.

En el modo de deep sleep, la CPU principal se apaga, mientras que el coprocesador ULP puede tomar lecturas de sensores y despertar la CPU cuando sea necesario. Este patrón de sueño se conoce como patrón monitorizado por sensor ULP. Esto es útil para diseñar aplicaciones donde la CPU debe ser despertada por un evento externo, un temporizador o una combinación de ambos, manteniendo un consumo de energía mínimo.

Junto con la CPU, la memoria principal del chip también se deshabilita. Como resultado, todo lo almacenado en esa memoria se borra y no se puede acceder a ella.

Debido a que la memoria RTC se mantiene encendida, su contenido se conserva incluso durante el modo de deep sleep y se puede recuperar después de que el chip se despierte. Por eso, el chip almacena los datos de conexión Wi-Fi y Bluetooth en la memoria RTC antes de entrar en deep sleep.

Si quieres utilizar los datos después del reinicio, almacénalos en la memoria RTC definiendo una variable global con el atributo RTC_DATA_ATTR. Por ejemplo, RTC_DATA_ATTR int myVar = 0;

Después de salir del modo de deep sleep, el chip se reinicia con un reinicio y comienza la ejecución del programa desde el principio.

El ESP32 admite la ejecución de un deep sleep wake stub al salir del modo de deep sleep. Esta función se ejecuta inmediatamente después de que el chip se despierta, antes de que se ejecute cualquier inicialización normal, bootloader o código ESP-IDF. Después de que se ejecute el wake stub, el chip puede volver a dormir o continuar iniciando ESP-IDF normalmente.

A diferencia de otros modos de sueño, el sistema no puede entrar automáticamente en modo de deep sleep. La función esp_deep_sleep_start() se utiliza para entrar en deep sleep inmediatamente después de configurar las fuentes de despertador.

Fuentes de despertador de Deep Sleep de ESP32

El ESP32 puede despertarse del modo de deep sleep utilizando múltiples fuentes. Estas fuentes son:

  1. Temporizador
  2. Pad táctil
  3. Despertador externo (ext0 y ext1)

Se pueden combinar múltiples fuentes de despertador, en cuyo caso el chip se despertará cuando una de las fuentes se active.

Advertencia: Es posible poner el ESP32 en modo de deep sleep sin configurar fuentes de despertador, en cuyo caso el chip permanece en modo de deep sleep indefinidamente hasta que se aplique un reinicio externo.

1 comentario en «ESP32 Deep Sleep y sus fuentes de estela»

Deja un comentario