ESP32 External Wake Up from Deep Sleep

This article shows how to put the ESP32 in deep sleep mode and wake it up with an external wake-up. An external wake-up source can be the press of a pushbutton, the detection of movement, or other scenarios that involve changing the value of a signal: from HIGH to LOW or LOW to HIGH.
You have two possibilities of external wake-up: ext0, and ext1.

ESP32 External Wake Up from Deep Sleep

Updated 8 October 2024.

Throughout this article we’ll cover the following subjects:

  • how to put the ESP32 in deep sleep mode;
  • wake up the ESP32 by changing the value of one GPIO (with a pushbutton) using the ext0 method;
  • wake up the ESP32 using several GPIOs using the ext1 method;
  • identify which GPIO caused the wake-up.

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 keep in mind that:

  1. First, you need to 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. In this article, we’ll show you how to use the external wake-up sources.
  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.

External Wake Up

External wake up is one of the ways to wake up the ESP32 from deep sleep. This means that you can wake up the ESP32 by toggling the value of a signal on a pin, like the press of a button. You have two possibilities of external wake-up: ext0, and ext1.

External Wake Up

External Wake Up (ext0)

This wake-up source allows you to use a pin to wake up the ESP32. The ext0 wake‑up source option uses RTC GPIOs to wake up. So, RTC peripherals are kept on during deep sleep if this wake-up source is requested.

To use this wake-up source, you use the following function:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

This function accepts as the first argument the pin you want to use, in this format GPIO_NUM_X, in which X represents the GPIO number of that pin.

The second argument, level, can be either 1 or 0. This represents the state of the GPIO that will trigger wake-up.

Note: you can only use pins that are RTC GPIOs with this wake-up source. Here’s a list of the RTC GPIOs for different ESP32 chip models:

  • ESP32-S3: 0-21;
  • ESP32: 0, 2, 4, 12-15, 25-27, 32-39;
  • ESP32-S2: 0-21;

External Wake Up (ext1)

This wake-up source allows you to use multiple RTC GPIOs. This wake-up source is implemented by the RTC controller. So, RTC peripherals and RTC memories can be powered off in this mode.

To use this wake-up source, you use the following function:

esp_sleep_enable_ext1_wakeup_io(bitmask, mode);

This function accepts two arguments:

  • A bitmask of the GPIO numbers that will cause the wake up;
  • Mode: the logic to wake up the ESP32. It can be:
    • ESP_EXT1_WAKEUP_ALL_LOW: wake up when all GPIOs go low;
    • ESP_EXT1_WAKEUP_ANY_HIGH: wake up if any of the GPIOs go high.

If you’re using an ESP32-S2, ESP32-S3, ESP32-C6 or ESP32-H2, these are the available modes:

  • ESP_EXT1_WAKEUP_ANY_LOW: wake up when any of the selected GPIOs is low
  • ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high

Note: you can only use pins that are RTC GPIOs.

For all the details about the ext1 deep sleep wake-up source, take a look at the Espressif deep sleep documentation.

Parts Required

To follow this tutorial, you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Code – External Wake Up Example

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

The following example demonstrates how to use the external wake-up source. You can find it at File > Examples > ESP32 Deep Sleep > ExternalWakeUp, or you can copy it from below.

/*
  Deep Sleep with External Wake Up
  =====================================
  This code displays how to use deep sleep with
  an external trigger as a wake up source and how
  to store data in RTC memory to use it over reboots

  This code is under Public Domain License.

  Hardware Connections
  ======================
  Push Button to GPIO 33 pulled down with a 10K Ohm
  resistor

  NOTE:
  ======
  Only RTC IO can be used as a source for external wake
  source. They are pins: 0,2,4,12-15,25-27,32-39.

  Author:
  Pranav Cherukupalli <[email protected]>
*/
#include "driver/rtc_io.h"

#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)  // 2 ^ GPIO_NUMBER in hex
#define USE_EXT0_WAKEUP          1               // 1 = EXT0 wakeup, 0 = EXT1 wakeup
#define WAKEUP_GPIO              GPIO_NUM_33     // Only RTC IO are allowed - ESP32 Pin example
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 for an external trigger.
    There are two types for ESP32, ext0 and ext1 .
    ext0 uses RTC_IO to wakeup thus requires RTC peripherals
    to be on while ext1 uses RTC Controller so does not need
    peripherals to be powered on.
    Note that using internal pullups/pulldowns also requires
    RTC peripherals to be turned on.
  */
#if USE_EXT0_WAKEUP
  esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);  //1 = High, 0 = Low
  // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep.
  // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs.
  // No need to keep that power domain explicitly, unlike EXT1.
  rtc_gpio_pullup_dis(WAKEUP_GPIO);
  rtc_gpio_pulldown_en(WAKEUP_GPIO);

#else  // EXT1 WAKEUP
  //If you were to use ext1, you would use it like
  esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
  /*
    If there are no external pull-up/downs, tie wakeup pins to inactive level with internal pull-up/downs via RTC IO
         during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will
         increase some power comsumption. However, if we turn off the RTC_PERIPH domain or if certain chips lack the RTC_PERIPH
         domain, we will use the HOLD feature to maintain the pull-up and pull-down on the pins during sleep.
  */
  rtc_gpio_pulldown_en(WAKEUP_GPIO);  // GPIO33 is tie to GND in order to wake up in HIGH
  rtc_gpio_pullup_dis(WAKEUP_GPIO);   // Disable PULL_UP in order to allow it to wakeup on HIGH
#endif
  //Go to sleep now
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {
  //This is not going to be called
}

View raw code

This example awakes the ESP32 when you trigger GPIO 33 to high. The code example shows how to use both methods: ext0 and ext1. If you upload the code as it is, you’ll use ext0. The function to use ext1 is commented. We’ll show you how both methods work and how to use them.

Let’s take a quick look at the code.

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 reason by which the ESP32 has been awakened 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;
  }
}

setup()

In the setup(), you start by initializing the serial communication:

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

Then, you increment one to the bootCount variable, and print that variable in the Serial Monitor.

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

Next, you print the wake-up reason using the print_wakeup_reason() function defined earlier.

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

After this, you need to enable the wake-up sources. We’ll test each of the wake-up sources, ext0 and ext1, separately.

ext0

In this example, the ESP32 wakes up when the GPIO 33 is triggered to high:

esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);  // 1 = High, 0 = Low

Instead of GPIO 33, you can use any other RTC GPIO pin. Just define it on the WAKEUP_GPIO variable at the beginning of the code.

#define WAKEUP_GPIO GPIO_NUM_33     // Only RTC IO are allowed

Internal Pull-Up and Pull-Down Resistors

We also call the following two lines:

rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);

The rtc_gpio_pullup_dis() function disables any internal pull-up resistors on the wake-up GPIO—it ensures that the pin is not unintentionally held high. This is important because a pull-up resistor would keep the pin high, potentially causing unintended wakeups.

The rtc_gpio_pulldown_en() function enables the internal pull-down resistor on the wake-up GPIO—it ensures the pin is held low until a valid wakeup signal (HIGH) is received. By configuring the pin with a pull-down resistor, we guarantee that it remains in a stable low state during deep sleep. This stability ensures that the ESP32 wakes up only when the specified GPIO pin receives an external high signal, matching the wakeup condition set by the esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1).

Wiring the Circuit

To test this example, wire a pushbutton to your ESP32 by following the next schematic diagram. The button is connected to GPIO 33 using a pull-down 10k Ohm resistor.

ESP32 connected to GPIO 33

Note that only RTC GPIOs can be used as a wake-up source—you can check the pinout of your board to identify the RTC GPIOs. Instead of GPIO 33, you can use any RTC GPIO pins to connect your button.

Testing the Example

Let’s test this example. Upload the example code to your ESP32. Make sure you have the right board and COM port selected. Open the Serial Monitor at a baud rate of 115200.

Press the pushbutton to wake up the ESP32.

ESP32 Deep Sleep External Wake Up with Pushbutton

Try this several times, and see the boot count increasing with each button press.

ESP32 testing exterbak wake-up

Using this method is useful to wake up your ESP32 using a pushbutton, for example, to execute a particular task. However, with this method, you can only use one GPIO as a wake-up source.

What if you want to have different buttons, all of them wake up the ESP, but do different tasks? For that you need to use the ext1 method.

ext1

The ext1 wake-up source allows you to wake up the ESP32 using different GPIOs and perform different tasks depending on the GPIO that caused the wake-up.

Instead of using the esp_sleep_enable_ext0_wakeup() function, you use the esp_sleep_enable_ext1_wakeup_io() function.

esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);

In this particular example, to run that part of the code, make sure you set the USE_EXT0_WAKEUP variable to 0 at the beginning of the code like so:

#define USE_EXT0_WAKEUP  0  // 1 = EXT0 wakeup, 0 = EXT1 wakeup

The esp_sleep_enable_ext1_wakeup_io() function

The first argument of the esp_sleep_enable_ext1_wakeup_io() function is a bitmask of the GPIOs you’ll use as a wake-up source, and the second argument defines the logic to wake up the ESP32.

GPIOs Bitmask

To define the GPIOs bitmask, we can use the BUTTON_PIN_BITMASK() macro defined at the beginning of the code.

#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)  // 2 ^ GPIO_NUMBER in hex

BUTTON_PIN_BITMASK(GPIO) is a macro that creates a bitmask for a specific GPIO. It is not a function but behaves somewhat similarly by accepting an argument and returning a value.

So, if you want to return the bitmask for a specific GPIO, you just need to call it like so:

BUTTON_PIN_BITMASK(WAKEUP_GPIO)

So, the esp_sleep_enable_ext1_wakeup_io() will look like this:

esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);

Bitmask for Multiple GPIOs

To create a bitmask for multiple GPIOs using the BUTTON_PIN_BITMASK(GPIO) macro, you can use bitwise OR (|) to combine the individual bitmasks for each GPIO pin. Here’s how you can do it:

Suppose you want to create a bitmask for GPIO pins 2 and 15. You can do this by combining the individual bitmasks for each pin like this:

uint64_t bitmask = BUTTON_PIN_BITMASK(GPIO_NUM_2) | BUTTON_PIN_BITMASK(GPIO_NUM_15);

We’ll see an example using multiple GPIOs as a wake-up source next.

Wake-Up Mode

The second argument of the esp_sleep_enable_ext1_wakeup_io() function is the wake-up mode. As we’ve seen previously, these are your options:

  • ESP_EXT1_WAKEUP_ALL_LOW: wake up when all GPIOs go low;
  • ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the GPIOs go high.

If you’re using an ESP32-S2, ESP32-S3, ESP32-C6 or ESP32-H2, these are the available modes:

  • ESP_EXT1_WAKEUP_ANY_LOW: wake up when any of the selected GPIOs is low
  • ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high

In our particular example, we’re using ESP_EXT1_WAKEUP_ANY_HIGH. So, the ESP32 will wake-up when any of the GPIOs from the bitmask are high.

Like with the ext0, we disable pull-up internal resistors and enable pull-down resistors to ensure stability of the reading of the wake-up GPIO.

External Wake Up – Multiple GPIOs

Now, you should be able to wake up the ESP32 using different buttons, and identify which button caused the wake up. In this example we’ll use GPIO 2 and GPIO 15 as a wake-up source.

Schematic

Wire two buttons to your ESP32. In this example, we’re using GPIO 2 and GPIO 15, but you can connect your buttons to any RTC GPIOs.

ESP32 two pushbuttons to wake-up from deep sleep

Code Multiple GPIOs – External Wake-Up

You need to make some modifications to the example code we’ve used before:

  • create a bitmask to use GPIO 15 and GPIO 2. We’ve shown you how to do this before;
  • enable ext1 as a wake-up source;
  • create a function that identifies the GPIO that caused the wake-up.

The next sketch has all those changes implemented.

/*  
  Rui Santos & Sara Santos - Random Nerd Tutorials
  https://RandomNerdTutorials.com/learn-esp32-with-arduino-ide/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include "driver/rtc_io.h"

#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)  // 2 ^ GPIO_NUMBER in hex
#define WAKEUP_GPIO_2              GPIO_NUM_2     // Only RTC IO are allowed - ESP32 Pin example
#define WAKEUP_GPIO_15              GPIO_NUM_15     // Only RTC IO are allowed - ESP32 Pin example

// Define bitmask for multiple GPIOs
uint64_t bitmask = BUTTON_PIN_BITMASK(WAKEUP_GPIO_2) | BUTTON_PIN_BITMASK(WAKEUP_GPIO_15);

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the GPIO that triggered the wakeup
*/
void print_GPIO_wake_up(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(2), 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");
      print_GPIO_wake_up();
      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();

  //Use ext1 as a wake-up source
  esp_sleep_enable_ext1_wakeup_io(bitmask, ESP_EXT1_WAKEUP_ANY_HIGH);
  // enable pull-down resistors and disable pull-up resistors
  rtc_gpio_pulldown_en(WAKEUP_GPIO_2);
  rtc_gpio_pullup_dis(WAKEUP_GPIO_2);
  rtc_gpio_pulldown_en(WAKEUP_GPIO_15);
  rtc_gpio_pullup_dis(WAKEUP_GPIO_15);

  //Go to sleep now
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {
  //This is not going to be called
}

View raw code

How Does the Code Work?

Let’s take a quick look at how the code works.

GPIOs Bitmask

You define the GPIOs bitmask at the beginning of the code:

#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)  // 2 ^ GPIO_NUMBER in hex
#define WAKEUP_GPIO_2           GPIO_NUM_2       // Only RTC IO are allowed - 
#define WAKEUP_GPIO_15          GPIO_NUM_15      // Only RTC IO are allowed 

// Define bitmask for multiple GPIOs
uint64_t bitmask = BUTTON_PIN_BITMASK(WAKEUP_GPIO_2) | BUTTON_PIN_BITMASK(WAKEUP_GPIO_15);

Identify the GPIO that Caused the Wake-up

We create a function called print_GPIO_wake_up() that prints the GPIO that caused the wake-up:

void print_GPIO_wake_up(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(2), 0);
}

The esp_sleep_get_ext1_wakeup_status() function returns a bitmask with the GPIO that caused the wake-up. We can get the GPIO number as follows:

log(GPIO_reason))/log(2)

Print the Wake-Up Reason

We modified the print_wakeup_reason() function to print the GPIO that caused the wake-up when the wake-up source is ext1:

case ESP_SLEEP_WAKEUP_EXT1:
  Serial.println("Wakeup caused by external signal using RTC_CNTL");
  print_GPIO_wake_up();
  break;

Enable ext1 as a Wake-Up Source

Enable ext1 as a wake-up source by passing the GPIOs bitmask and wake-up mode.

esp_sleep_enable_ext1_wakeup_io(bitmask, ESP_EXT1_WAKEUP_ANY_HIGH);

Don’t forget to disable any internal pull-up resistors and enable pull-down resistors on the GPIOs used as a wake-up source.

rtc_gpio_pulldown_en(WAKEUP_GPIO_2);
rtc_gpio_pullup_dis(WAKEUP_GPIO_2);
rtc_gpio_pulldown_en(WAKEUP_GPIO_15);
rtc_gpio_pullup_dis(WAKEUP_GPIO_15);

Enable Deep Sleep

Finally, call esp_deep_sleep_start() to put the ESP32 in deep sleep mode.

esp_deep_sleep_start();

Testing the Sketch

After uploading the code to the board, the ESP32 will be in deep sleep mode. You can wake it up by pressing the pushbuttons.

ESP32 external wake-up multiple GPIOs

Open the Serial Monitor at a baud rate of 115200. Press the pushbuttons to wake up the ESP32. On the Serial Monitor, you should get the wake-up reason and the GPIO that caused the wake-up.

ESP32 External Wake-up Multiple GPIOs

Wrapping Up

In this tutorial, you learned to wake up the ESP32 using an external wake-up. This means that you can wake up the ESP32 by changing the state of a GPIO pin.

In summary:

  • You can only use RTC GPIOs as an external wake-up;
  • You can use two different methods: ext0 and ext1;
  • ext0 allows you to wake up the ESP32 using one single GPIO pin;
  • ext1 allows you to wake up the ESP32 using multiple GPIO pins.

To learn more about deep sleep with the ESP32, take a look at our complete guide: ESP32 Deep Sleep with Arduino IDE and Wake Up Sources.

If you like ESP32, you may also like the following resources:

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 »

Enjoyed this project? Stay updated by subscribing our newsletter!

55 thoughts on “ESP32 External Wake Up from Deep Sleep”

  1. When waking from deep sleep, where does the program begin execution within the loop or does it go through all the initialization and setup again?
    Thanks

    Reply
    • Hi Erik.
      The code goes through all the initialization and setup again. Like if you had restarted the ESP32.
      Regards,
      Sara

      Reply
  2. there is a bug in:
    int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
    you must use:
    uint64_t GPIO_reason = esp_sleep_get_ext1_wakeup_status();
    otherwise GPIO port numbers higher than 31 will not be
    printed correctly

    Reply
    • Hi.
      Unfortunately not.
      These are the only options:
      ESP_EXT1_WAKEUP_ALL_LOW: wake up when all GPIOs go low;
      ESP_EXT1_WAKEUP_ANY_HIGH: wake up if any of the GPIOs go high.
      Regards,
      Sara

      Reply
  3. Hi many thanks for this tutorial. Would it be possible to use a vibration sensor such as the sw-420 to wake the esp32 from sleep?

    Reply
    • Hi.
      Yes. You can place it in the loop().
      Once it finds the instructions to go to sleep, the loop() is interrupted.
      When the ESP32 wakes up, it will run the code from the start.
      Regards,
      Sara

      Reply
  4. A few remarks:

    Calculating the mask can be much easier :

    define WAKEBUTTON 27 // button connected to GPIO27

    define BUTTON_PIN_BITMASK (1<<WAKEBUTTON)
    If ESP_EXT1_WAKEUP_ALL_LOW is used no information is available on what buttons are pressed when esp_sleep_get_ext1_wakeup_status() is called.
    Use of an external pull-up or pull-down resistor (e.g. 10k) on the pin prevents random wakeups.

    Reply
    • Also, all the conversion from decimal to hex is totally unnecessary. A number is a number, it does not matter which base one uses to display it as long as the proper prefixes are there.

      Reply
  5. Hello Sara,
    I need to restart esp (ESP.restart() ) after External Wake Up (ext0). I know how to do it with Touch wake up but not with external wake up. Do you have any hint on how to execute a function after external wake up?
    Thank you in advance.
    Said

    Reply
    • Hi.
      I don’t know if that’s possible with external wake up. Because you would have to put the function at the beginning of your code, which would result in the board constantly restarting.
      Regards,
      Sara

      Reply
  6. Hello
    First of all, I want to thank you a lot for the great tutorial.
    I have implemented this and it is working great.
    However, after multiple sleep and wakeups, the device goes to sleep and does not get back up with the trigger. The only way to fix it is by pressing the reset button.
    The number of iterations seems to be random, sometimes after 50, and other times less.
    Is there any solution for this?
    please let me know
    Thank you!

    Reply
  7. Hi,

    Thanks so much for this tutorial, it is really quite helpful. I have a question about RTC wakeup though. It seems like ESP_SLEEP_WAKEUP_EXT0 uses a signal over the RTC pin, however I cannot sort out how to use the RTC to wake it up. Ultimately I need to set the RTC, and then put the ESP32 into DeepSleep until a specific time, wake up, run the program, and go back to sleep until the next specific time. The answer might be to set the RTC, calculate a timer for the specific wake time, and use the timer wake up, but that seems unnecessary if it is possible (and more accurate) to use the RTC itself. Any suggestions?

    Reply
  8. Instead of doing the calculations and conversions for bitmask, why not letting the C compiler do the job?
    This uses the left bit shift operator (<<) and the bitwise or operator (|):
    1<<n will evaluate to 2^n

    Instead of:
    #define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
    use:
    #define BUTTON_PIN_BITMASK (1<<33)

    Instead of:
    #define BUTTON_PIN_BITMASK 0x8004
    use:
    #define BUTTON_PIN_BITMASK (1<<15 | 1<<2)

    Reply
  9. Hi!
    There is a bug in section “External Wake Up – Multiple GPIOs”
    As “pietro pizzi” noticed, “int” must be replaced with “uint64_t” in line: “int GPIO_reason = esp_sleep_get_ext1_wakeup_status();”
    “int” is 32 bit. So if we use pins 32, 33… and higher, we will get result: “GPIO that triggered the wake up: GPIO inf”, where GPIO is “inf” instead of number.
    Also, it can be a solution for https://rntlab.com/question/esp32-deep-sleep-with-external-wake-up/

    Thanks for great tutorial!

    Reply
    • Hi Alex.
      Thanks for pointing that out.
      We’ll fix the example.
      Thanks for taking the time to let us know.
      Regards,
      Sara

      Reply
  10. Hi,
    I’m having quite a problem with random wake ups that I cannot fix. My script is configured for 3 ext1 triggers on pins 33,13 and 4. All connections are made exactly like on the picture. Pushing buttons wakes up esp32 like it should, showing correct pin numbers, however every now and then (sometimes constantly) console says that there was a wakeup caused by external signal using RTC_CNTL on GPIO inf. Could this be happening because of faulty cable connections, broken breadboard or maybe power supply? I’m using power from pc through usb cable. I’ve tested it on 3 different esp32 modules, 2 different usb cables with different pins and it’s happening on all of them regardless of setup.

    Reply
  11. Hello, Thank you first for the support you can give me. I need help developing a code with ESP32 that allows me to use two or more pins with the ESP_SLEEP_WAKEUP_EXT0 function, so far it works fine with one, but when trying to do it with another it no longer works. The initial code that works with the GPIO2, if I do change it by GPIO4 also works, but not works together. In both GPIO 2 and 4, I have connected static buttons and they can be in High or LOW by minutes, hours, days, or weeks independallity. Sorry if something it’s wrong, it’s my first topic in this forum. Please see the follwing functional code with GPIO2 Pin:

    https://docs.google.com/document/d/158TqtkX-o9dMnx2a2PK4MNxyE71c9w4-vAD6SS8frbI/edit?usp=sharing

    Reply
    • Hi Freddy.
      To use more than one pin, you need to use the ESP_SLEEP_WAKEUP_EXT1 function.
      Scroll down the article to the “ext1” heading. Everything is explained of how to use multiple GPIOs.
      Regards,
      Sara

      Reply
      • Hello Sara, and thanks for your prompt answer. I also thought of the EXT1, and I tried with this function, but but the problem is that I need to work with static switches, and they can be in Low or High State each one anytime and for a long time ie: Can be one minute, one hour, or until one month in the same position (low or HigH), and this EXT1 not work because all time are waking up, EXT1 it’s good to work for pulsed switches.

        Reply
  12. Can two different Interrupt methods, i.e. Timer & EXT(0) , be combined in one program to wake the esp32 up if either condition is met

    Reply
  13. Is this terminal output wrong or no?

    rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:2
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load:0x40078000,len:10124
    load:0x40080400,len:5828
    entry 0x400806a8
    Boot number: 7
    Wakeup caused by external signal using RTC_IO
    Going to sleep now

    Reply
  14. In ext1 mode, after pressing the button the pin goes to HIGH. how to make the pin go back to LOW?
    (Turn on the led, turn off the led. On the same button)
    Thanks….

    Reply
    • You can activate from Telegram by calling a sleep function upon reeiving a message.
      However, when the ESP32 is sleeping, it won’t be able to receive any messages from Telegram.
      Regards,
      Sara

      Reply
  15. Hi Stefano
    Yes, on CodeProjec site there is a my article:
    codeproject.com/Articles/5300124/Power-Reduction-and-Wake-Up-Techniques-on-ESP32-Bo
    Where you can download the .ino project.
    You cam also get it, with other Arduino/Esp32 .ino(s) projects from my site:
    condorinformatique.com
    Regards

    Reply
  16. Hi,
    I suppose that the GPIO used for the wakeup must be declare as input somewhere. It is not in the main code so I suppose it is in the function:
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
    Does it mean that we could use this GPIO as output during the life of the program and we have to call the esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); just before call the deepsleep ?
    Could it work like this ?
    Thanks,
    Laurent

    Reply
  17. In the article we read: “The ext0 wake up source option uses RTC GPIOs to wake up. So, RTC peripherals will be kept on during deep sleep if this wake up source is requested.”

    With the same logic, why RTC Peripherals are not automatically kept on in ext1 wake up source option as well?

    (I remind what is mentioned in the article about the ext1 wake up source: “with this wake up source, you can only use pins that are RTC GPIOs.” namely exactly what is mentioned about ext0)

    Reply
  18. Hi,
    Great article but leaves out using analog ADC inputs to wake, specifically hal and voltage detect.
    Can you do an article covering using Input Signals Measured Using the ADC Instruction as outlined on page 659-660 of the esp32 technical reference manual?
    my application is automotive so sleep below 13.5v and wake above 14v, I am using pin35 for voltage sense already as indicated in Table 30­4. the datasheet is incomprehensible to me still though. I’m sure battery powered applications would like to be able to wake and transmit a low battery warning before the battery dies among other ADC wake usages.

    Thanks for your consideration!

    Reply
  19. Hi,
    I m trying to use deep sleep while preserving a string in RTC memory but heavily failing as all the data from RTC memory dissapear upon waking up. At the end, I stuck with the example for Deep sleep for ESP32 (in my case Xiao ESP32-CÂŁ and S3 modules, several different units), getting the next output on serial terminal. As you can notice, the bootcount variable does not increment and I am getting a 0 as a reboot reason, which is not fully clear:
    14:27:26.849 -> ESP-ROM:esp32c3-api1-20210207
    14:27:26.849 -> Build:Feb 7 2021
    14:27:26.849 -> rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT)
    14:27:26.849 -> Saved PC:0x4200e85e
    14:27:26.849 -> SPIWP:0xee
    14:27:26.849 -> mode:DIO, clock div:1
    14:27:26.849 -> load:0x3fcd5810,len:0x438
    14:27:26.849 -> load:0x403cc710,len:0x918
    14:27:26.849 -> load:0x403ce710,len:0x25f4
    14:27:26.849 -> entry 0x403cc710
    14:27:33.929 -> Boot number: 1
    14:27:33.929 -> Wakeup was not caused by deep sleep: 0
    14:27:33.929 -> Setup ESP32 to sleep for every 1 Seconds
    14:27:33.929 -> Going to sleep now
    14:27:46.373 -> ESP-ROM:esp32c3-api1-20210207
    14:27:46.373 -> Build:Feb 7 2021
    14:27:46.373 -> rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT)
    14:27:46.373 -> Saved PC:0x4200e85e
    14:27:46.374 -> SPIWP:0xee
    14:27:46.374 -> mode:DIO, clock div:1
    14:27:46.374 -> load:0x3fcd5810,len:0x438
    14:27:46.374 -> load:0x403cc710,len:0x918
    14:27:46.374 -> load:0x403ce710,len:0x25f4
    14:27:46.415 -> entry 0x403cc710
    14:27:53.481 -> Boot number: 1
    14:27:53.481 -> Wakeup was not caused by deep sleep: 0
    14:27:53.481 -> Setup ESP32 to sleep for every 1 Seconds
    14:27:53.481 -> Going to sleep now…

    Any suggestion?

    Reply
      • Hi Sara,
        and thank you for replying.
        The example I am trying to run is
        …Arduino15\packages\esp32\hardware\esp32\2.0.10\libraries\ESP32\examples\DeepSleep\TimerWakeUp
        So TimeWakeUp.ino for ESP32.
        So, my friend and me have tried this code to run on beforementioned XIO products but both failed in the same way as the Boot number does not increase with the time.

        Reply
        • I have just downloaded good ol’ trial version of Hypeterminal and immediately got the right results – The boot counter is regularly incrementing. As soon as I use the Arduino IDE serial monitor something else is causing this unregular waking up, thus clearing the counter. Main concern here is clearing the value stored in RTC memory which I would use in my project to retain relevant data during deep sleep.
          Now I am confused…

          Reply
  20. Thank you for the tutorial, it was very helpful. I was able to set up an on/off system with a long press of a push button thanks to it. Well, I’m not sure if it’s entirely streamlined, but it works.

    Reply
  21. Hi

    When I power a LIVE D1 Mini ESP32 through the USB either from PC or USB-PSU, I see that the deep sleep works and I see bootCount increasing and wakeup reason is 4 (timer).
    bootCount,wakeupreason
    1,0
    2,4
    3,4
    4,4

    However if I power the ESP32 card VCC pin directly from a 4.2 LiOn cell everything works and the card wakes up by timer as requested BUT bootCount does not increment and wakeup reason is 0
    bootCount,wakeupreason
    1,0
    1,0
    1,0
    1,0

    What is the reason for this ? I would like to run the card on the battery…

    Reply
  22. The text description for External Wake Up (ext0) states “The ext0 wake up source option uses RTC GPIOs to wake up. So, RTC peripherals will be kept on during deep sleep if this wake up source is requested”.

    while 


    The text description for External Wake Up (ext1) states “This wake up source is implemented by the RTC controller. So, RTC peripherals and RTC memories can be powered off in this mode”.

    Yet the example code for BOTH modes uses RTC memory to save the boot count:
    RTC_DATA_ATTR int bootCount = 0;

    That tells me that RTC memory is powered on in BOTH modes. What am I missing?

    Reply
  23. Hi!
    Can I use another esp32 for example and trigger the wakeup by using pins of the other esp32.
    For example, esp32-A will have a GPIO output pin connected to esp32-B and will serves as input pin. and I will just put output pin to HIGH, so that the other esp32 will wake up.

    Reply
  24. Hello Sara and Rui,

    I’m working on the second part of the tutorial. Whatever I test, I always get
    ‘Wakeup caused by external signal using RTC_CNTL
    GPIO that triggered the wake up: GPIO inf
    Going to sleep now’
    I’ve tried changing inputs, ESP32, etc…. The assembly is constantly trigged without pressing any of the buttons. When I upload the first code (a single input), it works fine. I used an ESP32-Wroom-32 from AZ-Delivery. Could this be the reason?


    Philippe

    Reply
  25. Hi Sara and Rui,

    Just qucik question about the hardware setup. As you’ve enabled pull down resistors:

    rtc_gpio_pulldown_en(WAKEUP_GPIO)

    Is is necessary to have the 10K Ohm resistors in the physical setup?

    Thanks and congratulations for your work.!

    Reply
  26. I have a doubt. I have searched in many forums, but I can’t find it. How is it possible to wake up the esp32 by means of a LORA device? That is, how does an esp32 send a signal to wake up another esp32?
    Thank you very much for your attention!

    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.