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 power consumption.

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

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

The available WakeUp Sources to exit Deep Sleep are:

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

Upon exiting Deep Sleep, the program restarts from the beginning. The variables we have saved in “normal” memory are cleared. It’s almost like restarting the ESP32.

RTC

The RTC plays a very important role in Deep Sleep mode. If you need more information about this component, check 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 return from deep sleep mode.

This function runs only when we return from Deep Sleep mode, but not on the first boot of a processor.

This function is also saved in fast memory, and for this, 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 has to be as short as possible, usually only changing the content of a variable

Using Deep Sleep mode in the Arduino IDE

The necessary functions 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 for the ESP32 to wake up after a certain time has elapsed, 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 puts the ESP32 into Deep Sleep mode and keeps 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 more concise 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 see a complete example of how to use Deep Sleep mode to make the ESP32 go into 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 be executed due to Deep Sleep mode
}

void loop()
{
  // This function will never be executed 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 run the program again.

Using RTC memory

Let’s see an example of using RTC memory to save data between restarts 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 be executed due to Deep Sleep mode
}

void loop()
{
  // This function will never be executed 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 runs 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 be executed due to Deep Sleep mode
}