esp32-deep-sleep

Cómo usar el modo Deep Sleep en un ESP32

El Deep Sleep es un modo de bajo consumo que apaga casi por completo el ESP32, lo que resulta en un consumo de energía extremadamente bajo.

En este modo, el ESP32 consume solo unos pocos microamperios de corriente, lo que lo hace ideal para aplicaciones con baterías o alimentación limitada.

Cuando el ESP32 se encuentra en Deep Sleep, deja de ejecutar el programa y entra en un estado de suspensión. El ESP32 apaga la mayoría de los circuitos internos del microcontrolador, con excepción de algunos componentes esenciales como el Real-Time Clock (RTC).

Para salir del modo Deep Sleep, los WakeUp Source disponibles son:

  • Timer
  • Touchpad
  • ULP Coprocessor Wakeup
  • External Wakeup (Ext0 y Ext1)

Al salir Deep Sleep, el programa vuelve a iniciarse desde el principio. Las variables que hayamos guardado en la memoria “normal” se borran. Es casi como reiniciar el ESP32.

RTC

El RTC cumple un papel muy importante en el modo Deep Sleep. Si necesitas más información sobre este componente mira Detalles del hardware del ESP32.

Guardar Datos en Memorias RTC

Para guardar datos en la memoria RTC, simplemente debes agregar el atributo RTC_DATA_ATTR antes de la definición de una variable.

RTC_DATA_ATTR int bootCount = 0;

Stub wake

También tenemos la posibilidad de ejecutar una función cuando volvemos del modo deep sleep.

Esta función se juntará únicamente cuando volvemos de un modo Deep Sleep, pero no en el primer arranque de un procesador

esta función se guarda igualmente en la memoria fast memory, y para ello usamos el atributo RTC_IRAM_ATTR

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

Evidentemente esta función tiene que ser lo más corta posible normalmente únicamente cambiar el contenido de una variable

Uso del modo Deep Sleep en el IDE de Arduino

Las funciones necesarias para usar el modo Deep Sleep están definidos en el fichero “esp_sleep.h”. Esta biblioteca contiene las funciones y macros necesarios para configurar y controlar el modo Deep Sleep del ESP32.

#include <esp_sleep.h>

Antes de entrar en el modo Deep Sleep debemos configurar una WakeUp Source. Por ejemplo, si queremos usar el Timer para que el ESP32 se despierte trascurrido un cierto tiempo, podemos hacerlo con la función esp_sleep_enable_timer_wakeup().

Esta función toma como argumento el tiempo en microsegundos que el ESP32 debe permanecer en Deep Sleep antes de despertar.

Finalmente, entraríamos en el modo Deep Sleep utilizando la función esp_deep_sleep_start(). Esta función pondrá al ESP32 en modo Deep Sleep y lo mantendrá en ese estado hasta que ocurra un WakeUp Source.

Por ejemplo, para hacer que el ESP32 se despierte después de 5 segundos:

esp_sleep_enable_timer_wakeup(5 * 1000000);
esp_deep_sleep_start();

Usar el Timer como WakeUp source es tan habitual que incluso se dispone de una función alternativa más escueta, que nos permite usarlo en una única función.

/**
 * @brief Enter deep-sleep mode
 *
 * The device will automatically wake up after the deep-sleep time
 * Upon waking up, the device calls deep sleep wake stub, and then proceeds to load application.
 */
void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));

Ejemplos de código

Uso del modo Deep Sleep

Veamos un ejemplo completo de cómo utilizar el modo Deep Sleep para hacer que el ESP32 entre en sueño profundo durante 10 segundos y luego se despierte:

void setup()
{
  Serial.begin(115200);
  Serial.println("Iniciando...");
   
  esp_deep_sleep(2 * 1000000);  // entrar en deep sleep por 10 segundos
  
  // Esta función nunca se ejecutará debido al modo Deep Sleep
}

void loop()
{
  // Esta función nunca se ejecutará debido al modo Deep Sleep
}

En este ejemplo, el ESP32 entra en modo Deep Sleep después de imprimir el mensaje “Iniciando…“.

Permanecerá en este estado de bajo consumo durante 10 segundos y luego se despertará para volver a ejecutar el programa.

Uso de la memoria del RTC

Veamos un ejemplo de cómo usar la memoria del RTC para guardar datos entre reinicios en Deep Sleep

RTC_DATA_ATTR int bootCount = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("Iniciando...");
   
  bootCount++;
  Serial.println(bootCount);
  esp_deep_sleep(2 * 1000000);  // entrar en deep sleep por 10 segundos
  
  // Esta función nunca se ejecutará debido al modo Deep Sleep
}

void loop()
{
  // Esta función nunca se ejecutará debido al modo Deep Sleep
}

En este caso simplemente estamos contando el número de veces que se ha salido del Deep Sleep.

Uso de la función wake stub

Ahora un ejemplo de uso de la función Wake Stub, que se ejecuta inmediatamente al salir de un Deep Sleep

RTC_DATA_ATTR int bootCount = 0;

void RTC_IRAM_ATTR esp_wake_deep_sleep() {
    esp_default_wake_deep_sleep();
    bootCount++;
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Iniciando...");
     
  Serial.println(bootCount);
  esp_deep_sleep(2 * 1000000);  // entrar en deep sleep por 10 segundos  
}

void loop()
{
  // Esta función nunca se ejecutará debido al modo Deep Sleep
}