Language: EN

esp32-sleep-modes

What are sleep modes in ESP32

Sleep Modes are strategies used to minimize power consumption in electronic devices when they are not actively performing tasks.

These modes allow significant reduction in power consumption, which is crucial for battery-powered applications or those that are permanently connected.

When we enter a Sleep mode, at some point we will need to return to “normal” mode. To do this, there are several ways to “wake up” the ESP32. We call these events Wake-Up Sources.

There is a lot of outdated information about this in internet tutorials. If in doubt, consult the official manufacturer’s documentation

Sleep Modes on ESP32

The ESP32 has two Sleep modes. Added to the “normal” (active) mode, there are three possible operating modes.

⚡ Active Mode

This is the “normal” mode in which everything is connected. The CPU, RAM, and all peripherals are active.

The ESP32 is doing its thing, processing data, and with WiFi and BT enabled.

🔋 Light Sleep Mode

Light Sleep mode is similar to a computer’s “standby” mode. The ESP32 stops and reduces its consumption.

The CPU, RAM, and digital peripherals are disconnected from the clock and their voltage is reduced to save energy.

When returning to normal mode, the ESP32 continues its execution at the same point of the program it was at, preserving memory.

💤 Deep Sleep Mode

Deep Sleep mode is even more aggressive. It is almost like turning off and on the ESP32.

The CPUs, RAM, and digital peripherals are turned off. Only the RTC remains active.

When returning to normal mode, the ESP32 returns to the beginning of the program. Everything that was saved in memory is lost.

WakeUp Sources

The WakeUp Sources are also the most important part to enter Sleep mode. They are the available ways to wake up from Sleep mode.

By default, the ESP32 will deactivate all peripherals, except those that we specify as WakeUp Source. That is, the final state and consumption of the ESP32 will depend on the WakeUp Source that we define.

The WakeUp Source available in both Deep Sleep and Light Sleep modes are the following:

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

And these that only work in Light Sleep

  • GPIO Wakeup
  • UART Wakeup
  • WIFI Wakeup

To configure them, we will use these functions:

// Light Sleep and Deep Sleep
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);
esp_err_t esp_sleep_enable_touchpad_wakeup(void);
esp_err_t esp_sleep_enable_ulp_wakeup(void);
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode);

// Only in Light Sleep
esp_err_t esp_sleep_enable_gpio_wakeup(void);
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num);
esp_err_t esp_sleep_enable_wifi_wakeup(void);
void esp_sleep_enable_gpio_switch(bool enable);

Alternatively, we could use the esp_sleep_pd_config function (internally the previous ones do this):

esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
                                   esp_sleep_pd_option_t option);

Where esp_sleep_pd_domain_t can take these values:

/**
 * @brief Power domains which can be powered down in sleep mode
 */
typedef enum {
    ESP_PD_DOMAIN_RTC_PERIPH,      //!< RTC IO, sensors and ULP co-processor
    ESP_PD_DOMAIN_RTC_SLOW_MEM,    //!< RTC slow memory
    ESP_PD_DOMAIN_RTC_FAST_MEM,    //!< RTC fast memory
    ESP_PD_DOMAIN_XTAL,            //!< XTAL oscillator
#if SOC_PM_SUPPORT_CPU_PD
    ESP_PD_DOMAIN_CPU,             //!< CPU core
#endif
    ESP_PD_DOMAIN_RTC8M,           //!< Internal 8M oscillator
    ESP_PD_DOMAIN_VDDSDIO,         //!< VDD_SDIO
    ESP_PD_DOMAIN_MAX              //!< Number of domains
} esp_sleep_pd_domain_t;

And esp_sleep_pd_option_t can be:

/**
 * @brief Power down options
 */
typedef enum {
    ESP_PD_OPTION_OFF,      //!< Power down the power domain in sleep mode
    ESP_PD_OPTION_ON,       //!< Keep power domain enabled during sleep mode
    ESP_PD_OPTION_AUTO      //!< Keep power domain enabled in sleep mode, if it is needed by one of the wakeup options. Otherwise power it down.
} esp_sleep_pd_option_t;

Disable Sleep Wakeup Source

If necessary, we can deactivate one of the WakeUp Sources that we have defined previously.

/**
 * @brief Disable wakeup source
 *
 * This function is used to deactivate wake up trigger for source
 * defined as parameter of the function.
 * @param source - number of source to disable of type esp_sleep_source_t
 */
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source);

Get WakeUp Cause

The esp_sleep_get_wakeup_cause() function can be used to check which activation source caused the exit from the sleep mode.

/**
 * @brief Sleep wakeup cause
 */
typedef enum {
    ESP_SLEEP_WAKEUP_UNDEFINED,    //!< In case of deep sleep, reset was not caused by exit from deep sleep
    ESP_SLEEP_WAKEUP_ALL,          //!< Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source
    ESP_SLEEP_WAKEUP_EXT0,         //!< Wakeup caused by external signal using RTC_IO
    ESP_SLEEP_WAKEUP_EXT1,         //!< Wakeup caused by external signal using RTC_CNTL
    ESP_SLEEP_WAKEUP_TIMER,        //!< Wakeup caused by timer
    ESP_SLEEP_WAKEUP_TOUCHPAD,     //!< Wakeup caused by touchpad
    ESP_SLEEP_WAKEUP_ULP,          //!< Wakeup caused by ULP program
    ESP_SLEEP_WAKEUP_GPIO,         //!< Wakeup caused by GPIO (light sleep only)
    ESP_SLEEP_WAKEUP_UART,         //!< Wakeup caused by UART (light sleep only)
    ESP_SLEEP_WAKEUP_WIFI,              //!< Wakeup caused by WIFI (light sleep only)
    ESP_SLEEP_WAKEUP_COCPU,             //!< Wakeup caused by COCPU int
    ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG,   //!< Wakeup caused by COCPU crash
    ESP_SLEEP_WAKEUP_BT,           //!< Wakeup caused by BT (light sleep only)
} esp_sleep_source_t;

For the touch panel, it is possible to identify which touch pin caused the activation using the esp_sleep_get_touchpad_wakeup_status() functions.

void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();
  Serial.printf("Touch detected in d\n",touchPin);
}
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();
  Serial.printf("Touch detected in d\n",wakeup_reason);
}

For ext1 activation sources, it is possible to identify which touch pin caused the activation using the esp_sleep_get_ext1_wakeup_status() functions.

void print_wakeup_ext1(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_ext1 = esp_sleep_get_wakeup_cause();
  Serial.printf("Ext1 in d\n", wakeup_ext1);
}

Deactivate radio

When entering Sleep mode, the radio (WiFi and BT) are turned off in a “not so elegant” way. Therefore, if we are using any of these communication methods, we must explicitly deactivate them by doing.

esp_bluedroid_disable()
esp_bt_controller_disable()
esp_wifi_stop()

Which, in the case of using the Arduino environment, is done like this.

btStop();
WiFi.mode(WIFI_OFF);