Language: EN

esp32-deep-sleep

How to use Deep Sleep mode on an ESP32

Deep Sleep is a low-power mode that almost completely shuts down the ESP32, resulting in extremely low energy consumption.

In this mode, the ESP32 consumes only a few microamperes of current, making it ideal for battery-powered or limited power applications.

When the ESP32 is in Deep Sleep, it stops executing the program and enters a suspended state. The ESP32 turns off most of the internal circuits of the microcontroller, except for some essential components like the Real-Time Clock (RTC).

To exit Deep Sleep mode, the available WakeUp Sources are:

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

Upon exiting Deep Sleep, the program restarts from the beginning. Any variables we had stored in “normal” memory are erased. It is almost like rebooting the ESP32.

RTC

The RTC plays a very important role in Deep Sleep mode. If you need more information about this component, see ESP32 Hardware Details.

Saving Data in RTC Memory

To save data in RTC memory, you simply need to add the RTC_DATA_ATTR attribute before the definition of a variable.

RTC_DATA_ATTR int bootCount = 0;

Stub wake

We also have the option to execute a function when we wake up from deep sleep.

This function will only be called when waking up from Deep Sleep mode, but not on the first boot of a processor.

This function is also stored in fast memory, and for that, we use the RTC_IRAM_ATTR attribute.

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

Obviously, this function should be as short as possible, usually just changing the content of a variable.

Using Deep Sleep Mode in the Arduino IDE

The functions necessary to use Deep Sleep mode are defined in the “esp_sleep.h” file. This library contains the functions and macros needed to configure and control the Deep Sleep mode of the ESP32.

#include <esp_sleep.h>

Before entering Deep Sleep mode, we must configure a WakeUp Source. For example, if we want to use the Timer to wake the ESP32 after a certain time, we can do so with the esp_sleep_enable_timer_wakeup() function.

This function takes as an argument the time in microseconds that the ESP32 should remain in Deep Sleep before waking up.

Finally, we would enter Deep Sleep mode using the esp_deep_sleep_start() function. This function will put the ESP32 into Deep Sleep mode and keep it in that state until a WakeUp Source occurs.

For example, to make the ESP32 wake up after 5 seconds:

esp_sleep_enable_timer_wakeup(5 * 1000000);
esp_deep_sleep_start();

Using the Timer as a WakeUp source is so common that there is even a shorter alternative function available, which allows us to use it in a single function.

/**
 * @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));

Code Examples

Using Deep Sleep Mode

Let’s look at a complete example of how to use Deep Sleep mode to make the ESP32 enter deep sleep for 10 seconds and then wake up:

void setup()
{
  Serial.begin(115200);
  Serial.println("Starting...");
   
  esp_deep_sleep(2 * 1000000);  // enter deep sleep for 10 seconds
  
  // This function will never execute due to Deep Sleep mode
}

void loop()
{
  // This function will never execute due to Deep Sleep mode
}

In this example, the ESP32 enters Deep Sleep mode after printing the message “Starting…“.

It will remain in this low-power state for 10 seconds and then wake up to re-execute the program.

Using RTC Memory

Let’s look at an example of how to use RTC memory to save data between reboots in Deep Sleep:

RTC_DATA_ATTR int bootCount = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("Starting...");
   
  bootCount++;
  Serial.println(bootCount);
  esp_deep_sleep(2 * 1000000);  // enter deep sleep for 10 seconds
  
  // This function will never execute due to Deep Sleep mode
}

void loop()
{
  // This function will never execute due to Deep Sleep mode
}

In this case, we are simply counting the number of times we have exited Deep Sleep.

Using the wake stub function

Now an example of using the Wake Stub function, which executes immediately upon exiting 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("Starting...");
     
  Serial.println(bootCount);
  esp_deep_sleep(2 * 1000000);  // enter deep sleep for 10 seconds  
}

void loop()
{
  // This function will never execute due to Deep Sleep mode
}