ESP32 Timer Wake Up from Deep Sleep

In this tutorial, we will learn to use Timer as a wake-up resource from a deep sleep. First, we will put ESP32 into deep sleep mode and then see how to wake it up using a predefined time using a timer.

ESESP32 Timer Wake Up from Deep Sleep

How to Set Timer Wake Up on ESP32

The real-time clock controller (RTC) of ESP32 has a built-in timer which we can use to wake up ESP32 from a deep sleep after a predefine time is expired. We have to set a predefined amount of time, after it is over, the built-in timer wakes up the chip from deep sleep mode. This is achieved through a function. We will put the board in deep sleep mode for a specified amount of milliseconds.

We can use esp_sleep_enable_timer_wakeup(sleep_time_in_us) function which is available in the Arduino IDE. This function takes a single argument that denotes the sleeping time in microseconds. For example:

esp_sleep_enable_timer_wakeup(sleep_time_in_us)

How to Write Deep Sleep Code for ESP32?

To program ESP32 deep sleep mode and set up a wake up resource, follow these steps:

  • Start by configuring the wake up resource. In other words, define what source will wake up ESP32 from a deep sleep. As you may know that ESP32 supports multiple sources such as timer, external interrupt, and touch pins. We can use any one of them or a combination of these. We will use a timer wake up source in this tutorial
  • Next, we need to decide which peripheral’s power should be cut off. By default, ESP32 shut down power for all peripherals that are not required by a selected wake up source.
  • In the end, use esp_deep_sleep_start() function to put ESP32 into deep sleep mode.

We will be using Arduino IDE to program ESP32. If you have not used ESP32 with Arduino IDE before, you need to install an ESP32 library in Arduino by following this guide:

ESP32 Timer Wake Up from Deep Sleep Example

Let’s have a look at a simple example demonstrating a timer wake up using the example from the library. We are going to show you a simple demonstration of how to use ESP32 deep sleep timer to wake up. The ESP32 will remain in active mode for 5 seconds and after that time is over, the ESP32 will be back in deep sleep mode. It will remain in deep sleep for 5 seconds. After that, it will again wake up and execute the same code.

Open your Arduino IDE and go to File > Examples > ESP32 > Deep Sleep > TimerWakeUp. The following sketch will open up.

/*
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 <cherukupallip@gmail.com>
*/

#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
}

How does the Code Work?

Defining Sleep Time

Firstly, the sleep time will be defined in the variable TIME_TO_SLEEP. It is set to 5 meaning the ESP32 board will remain in deep sleep for 5 seconds. Also, a microsecond to second conversion factor is also defined which will be used later on in the program code.

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

Saving Boot Count in RTC Memory

ESP32 has an 8kb SRAM for the RTC controller which is also known as RTC fast memory and this memory can be used to save data. The data stored on this memory will remain saved during deep sleep but it will be erased during boot-up. Hence, we can use this memory to save data before putting ESP32 into deep sleep mode.

Now we will save the number of times our ESP32 board woke up from deep sleep inside the variable ‘bootCount.’

This will be saved in the RTC Memory of the development board by using ‘RTC_DATA_ATTR’ before defining the bootCount variable.

RTC_DATA_ATTR int bootCount = 0;

ESP32 Wake Up Reason

The following section of code shows the function print_wakeup_reason(). Through this function, the reason of our ESP32 waking up from deep sleep mode will get displayed on the serial monitor. As you can see there are various options including external wakeup using RTC_IO/RTC_CNTL, timer, touchpad, ULP program. For whichever reason the wake up will occur, it will get displayed.

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;
  }
}

setup()

Inside the setup() function, we will open a serial connection at a baud rate of 115200 and add a delay of 1 second to open the serial monitor.

Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

Then we will increment the bootCount variable to 1 every time the ESP32 board wakes up from deep sleep. On the serial monitor, the number of times the ESP32 module booted will be displayed automatically.

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

Now, we will call the print_wakeup_reason() function which was defined earlier to display the reason of the wake up. The message will be displayed on the serial monitor.

//Print the wakeup reason for ESP32
  print_wakeup_reason();

Using the following function, the ESP32 board wakes up from deep sleep mode. This function takes in the time in microseconds as a parameter. Thus, we will pass TIME_TO_SLEEP (which is 5 seconds)* the conversion factor to insure that the argument inside the function is in micro seconds.

 esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Also, display the following message on the Serial Monitor.

Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");

Finally, the ESP32 board goes to deep sleep when esp_deep_sleep_start() function is called.

Serial.println("Going to sleep now");
Serial.flush(); 
esp_deep_sleep_start();

loop()

The loop() function is empty because it never reaches this part of the program code. The ESP32 goes into deep sleep.

Demonstration

Make sure you choose the correct board and COM port before uploading your code to the board. Therefore go to Tools > Board and select ESP32 Dev Module.

select esp32 board

Then, go to Tools > Port and select the appropriate port through which your board is connected.

Selecting COM PORT ESP32

Click on the upload button to upload the code to ESP32 development board.

After you have uploaded your code to the ESP32, press its ENABLE button.

ESP32 enable reset button

In your Arduino IDE, open up the serial monitor and you will see the messages showing the boot count and the board going to deep sleep and waking up after every 5 seconds.

ESP32 Deep sleep timer wake up serial monitor
Serial Monitor

Pressing the ENABLE button on the ESP32 board will erase the RTC fast memory and the boot count will go back to zero.

In summary:

In this tutorial, we have learned how to put ESP32 into deep sleep mode and wake it up from deep sleep by using a timer as a wake up source. Furthermore, we have also learned how to save data to RTC memories before putting ESP32 into a deep sleep.

We can use this feature in many applications. For example, in the following projects, we used deep sleep in data logger applications where ESP32 remains in deep sleep mode to save power and wake up after some predefined time to take sensor measurements and save data to an SD card or Google sheets.

Leave a Comment