ESP32 Timer Wake Up from Deep Sleep

This tutorial shows how to put the ESP32 in deep sleep mode and wake it up with a timer after a predetermined amount of time. The ESP32 will be programmed with Arduino IDE.

ESP32 Timer Wake Up from Deep Sleep

Updated 8 October 2024.

To learn more about deep sleep and other wake-up sources, you can follow the next tutorials:

Writing a Deep Sleep Sketch

To write a sketch to put your ESP32 into deep sleep mode, and then wake it up, you need to:

  1. First, configure the wake-up sources. This means configuring what will wake up the ESP32. You can use one or combine more than one wake-up source. This article shows you how to use the timer wake-up. Use the esp_sleep_enable_timer_wakeup() function and pass as argument time sleep time in microseconds.
  2. You can decide what peripherals to shut down or keep on during deep sleep. However, by default, the ESP32 automatically powers down the peripherals that are not needed with the wake up source you define.
  3. Finally, you use the esp_deep_sleep_start() function to put your ESP32 into deep sleep mode.

Timer Wake Up

The ESP32 can go into deep sleep mode, and then wake up at predefined periods of time. This feature is handy if you are running projects that require time stamping or daily tasks while maintaining low power consumption.

Timer Wake Up

The ESP32 RTC controller has a built-in timer you can use to wake up the ESP32 after a predefined amount of time.

Enable Timer Wake Up

Enabling the ESP32 to wake up after a predefined time is very straightforward. In the Arduino IDE, you just need to specify the sleep time in microseconds in the following function:

esp_sleep_enable_timer_wakeup(time_in_us)

Code

To program the ESP32 we’ll use Arduino IDE. So, you need to make sure you have the ESP32 core installed. Follow the next tutorial if you haven’t already:

Let’s see how deep sleep with timer wake-up works using an example from the ESP32 Arduino core. Open your Arduino IDE, and go to File > Examples > ESP32 > Deep Sleep, and open the TimerWakeUp sketch.

/*
Simple Deep Sleep with Timer Wake Up
=====================================
ESP32 offers a deep sleep mode for effective power
saving as power is an important factor for IoT
applications. In this mode CPUs, most of the RAM,
and all the digital peripherals which are clocked
from APB_CLK are powered off. The only parts of
the chip which can still be powered on are:
RTC controller, RTC peripherals ,and RTC memories

This code displays the most basic deep sleep with
a timer to wake it up and how to store data in
RTC memory to use it over reboots

This code is under Public Domain License.

Author:
Pranav Cherukupalli <[email protected]>
*/

#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: %d\n", 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
}

View raw code

Let’s take a look at this code. The first comment describes what is powered off during deep sleep with timer wake up.

In this mode CPUs, most of the RAM,
and all the digital peripherals which are clocked
from APB_CLK are powered off. The only parts of
the chip which can still be powered on are:
RTC controller, RTC peripherals ,and RTC memories

When you use timer wake-up, the parts that will be powered on are RTC controller, RTC peripherals, and RTC memories.

Define the Sleep Time

These first two lines of code define the period of time the ESP32 will be sleeping.

#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) */

This example uses a conversion factor from microseconds to seconds, so that you can set the sleep time in the TIME_TO_SLEEP variable in seconds. In this case, the example will put the ESP32 into deep sleep mode for 5 seconds.

Save Data on RTC Memories

With the ESP32, you can save data on the RTC memories. The ESP32 has 8kB SRAM on the RTC part, called RTC fast memory. The data saved here is not erased during deep sleep. However, it is erased when you press the reset button (the button labeled EN on the ESP32 board).

To save data on the RTC memory, you just have to add RTC_DATA_ATTR before a variable definition. The example saves the bootCount variable on the RTC memory. This variable will count how many times the ESP32 has woken up from deep sleep.

RTC_DATA_ATTR int bootCount = 0;

Wake Up Reason

Then, the code defines the print_wakeup_reason() function, that prints the source that caused the wake-up from deep 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: %d\n", wakeup_reason); break;
  }
}

The setup()

In the setup() is where you should put your code. You need to write all the instructions before calling the esp_deep_sleep_start() function.

This example starts by initializing the serial communication at a baud rate of 115200.

Serial.begin(115200);

Then, the bootCount variable is increased by one in every reboot, and that number is printed in the serial monitor.

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

Then, the code calls the print_wakeup_reason() function, but you can call any function you want to perform a desired task. For example, you may want to wake up your ESP32 once a day to read a value from a sensor.

Next, the code defines the wake-up source by using the following function:

esp_sleep_enable_timer_wakeup(time_in_us)

This function accepts as argument the time to sleep in microseconds as we’ve seen previously. In our case, we have the following:

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Then, after all the tasks are performed, the ESP32 goes to sleep by calling the following function:

esp_deep_sleep_start()

As soon as you call the esp_deep_sleep_start() function, the ESP32 will go to sleep and will not run any code written after this function. When it wakes up from deep sleep, it will run the code from the beginning.

loop()

The loop() section is empty because the ESP32 will sleep before reaching this part of the code. So, you need to write all your tasks in the setup() before calling the esp_deep_sleep_start() function.

Testing the Timer Wake-Up

Upload the example sketch to your ESP32. Make sure you have the right board and COM port selected. Open the Serial Monitor at a baud rate of 115200.

Every 5 seconds, the ESP32 wakes up, prints a message on the serial monitor, and goes to deep sleep again.

Every time the ESP32 wakes up, the bootCount variable increases. It also prints the wake-up reason as shown in the figure below.

ESP32 Timer Wake-Up Demonstration

However, notice that if you press the EN button on the ESP32 board, it resets the bootCount to 1 again.

Wrapping Up

In summary, we’ve shown you how to use the timer wake-up source to wake-up the ESP32 in this unit.

  • To enable the timer wake-up, you use the esp_sleep_enable_timer_wakeup(time_in_us) function;
  • Use the esp_deep_sleep_start() function to start deep sleep.

You can modify the provided example, and instead of printing a message, you can make your ESP32 do any other task.

The timer wake-up is useful to perform periodic tasks with the ESP32 without draining much power, as we do in the following projects:

Finally, we also have a tutorial about deep sleep with the ESP8266 that you might be interested in: ESP8266 Deep Sleep with Arduino IDE.

This is an excerpt from our course: Learn ESP32 with Arduino IDE. If you like ESP32 and you want to learn more, we recommend enrolling in Learn ESP32 with Arduino IDE course.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

21 thoughts on “ESP32 Timer Wake Up from Deep Sleep”

  1. I get an error when compiling in the Arduino IDE.
    == Cut and Paste ==
    Sleep_Wakeup_Modes:25: error: ‘RTC_DATA_ATTR’ does not name a type
    RTC_DATA_ATTR int bootCount = 0;
    == Done =========
    I’m using a ESP32 -> DOIT ESP32 DevKit V1″ module.
    Is there a header file that I need to include in this.
    Shashi

    Reply
    • Hi.
      No, the code should work as it is – without the need to include anything else.
      Honestly, I have no idea why you are getting that error :/
      Sorry that I can’t help much.
      Regards,
      Sara

      Reply
    • Google Search that error message. May be other people that have had that same error come up during projects.

      Reply
    • Hi, any progress on this behaviour????

      I get the same error, I use the timer wake-up sketch on a WiFi Lora 32(V2) board. The timer sketch, directly taken from the sample runs OK. Also when I re-compile it.

      When I copy the first lines (up to and including the print_wakeup_reason() procedure into my own sketch, the compiler states: ‘RTC_DATA_ATTR’ does not name a type.

      I thought that it could have something to do with the board still cycling the timer wake-up sketch, but as the original sketch compiles OK, this cannot be the cause.

      Reply
      • Hi,

        Problem solved by moving my include lines to the top of the code.
        I did this after reading the comment of Sergi (add #include Arduino.h).

        Still, it puzzles me: why does the site example not need to include Arduino.h ? And why does my own code need it??

        Fred

        Reply
  2. Hi Kevin
    I’ve got the same problem as you.
    I’m using Atom, not Arduino IDE, and the same DOIT ESP32 DevKit V1 module
    I’ve solved the problem including

    #include

    Regards

    Sergi Fernández

    Reply
  3. My ESP32 only says “Wakeup caused by touchpad” when not touching it or anything (nothing connected at all).

    Any ideas?

    Reply
  4. I would like to put my esp32 into deep sleep with a timer. Currently esp 32 exposes an api which is called every 20 minutes. I would like to put him to sleep for 19 minutes, allow the api to respond and then put him back to sleep. I’ve seen your example but it doesn’t use the loop method. In my loop method there is the server.handleClient () statement; and with the sleep timer it is never called. how can i solve? Thanks to those who will answer

    Reply
  5. I would like to put my esp32 into deep sleep with a timer. Currently esp 32 exposes an api which is called every 20 minutes. I would like to put him to sleep for 19 minutes, allow the api to respond and then put him back to sleep. I’ve seen your example but it doesn’t use the loop method. In my loop method there is the server.handleClient () statement; and with the sleep timer it is never called. how can i solve? Thanks to those who will answer

    Reply
  6. as i get a reboot from time to time (for no known reason, it’s reported as SW_CPU_RESET for both cores), i tried to put all data that should survive a reboot in rtc ram by defining them as globals with RTC_DATA_ATTR in front.
    to check out if it works, i used ESP.restart() to force a reboot after data has been configured.
    unfortunately, my data reads back as 0 instead of the previously configured value.
    shouldn’t this work?

    Reply
  7. Hello, I would like to know whether it is possible to turn off the timer wake up once enabled (if the battery is too low, to not destroy it).

    Reply
  8. This will disable the wakeup time. Change the source for any other wake up trigger.

    esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);

    Reply
  9. The deep sleep code works fine on a Seeed XIAOESP32-C3. The problem is how do I regain control of the ESP32? The com port appears every time it wakes up but almost instantly vanishes, leaving no time to upload new code

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.