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.
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:
- [Complete Guide] ESP32 Deep Sleep with Arduino IDE and Wake Up Sources
- ESP32 Touch Wake Up from Deep Sleep
- ESP32 Timer Wake Up from Deep Sleep
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:
- 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.
- 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.
- 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 (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:
- ESP32 DOIT DEVKIT V1 Board (read Best ESP32 development boards)
- 2x Pushbuttons
- 2x 10k Ohm resistor
- Breadboard
- Jumper wires
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
}
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.
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.
Try this several times, and see the boot count increasing with each button press.
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.
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
}
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.
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.
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:
- Learn ESP32 with Arduino IDE (eBook)
- ESP32 Web Server with BME280 â Mini Weather Station
- ESP32 Web Server with Arduino IDE – control outputs
- ESP32 DHT11/DHT22 Temperature Web Server
- >> More Free ESP32 Tutorials and Guides <<
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.
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
Hi Erik.
The code goes through all the initialization and setup again. Like if you had restarted the ESP32.
Regards,
Sara
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
‘ESP_EXT1_WAKEUP_ANY_LOW’ was not declared in this scope
Is wake up by any LOW possible?
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
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?
Hi Tim.
Yes, that sensor outputs a signal when vibration occurs. So, yes.
Regards,
Sara
Can this be placed in loop?
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
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.
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.
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
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
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!
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?
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)
Is it possible to wake it up with ds3221?
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!
Hi Alex.
Thanks for pointing that out.
We’ll fix the example.
Thanks for taking the time to let us know.
Regards,
Sara
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.
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
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
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.
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
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
It seems ok to me.
Regards,
Sara
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….
Hi, you can disable the sleep mode with an interrupt either on the falling or rising edge
It is possible activate or deactivate the sleep mode from Telegram ?
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
Hello!
is it possible to use the wake up with timer and wake up with pin at the same time?
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
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
Yes. That’s right.
Regards,
Sara
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)
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!
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?
Hi.
What is the example that you’re following?
Regards,
Sara
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.
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…
Hi.
That’s weird. I just tested the code on my ESP32 boards and everything is working as expected.
Do you have any peripherals connected to your board?
What is the model that you’re using?
Regards,
Sara
These two, without having anything connected.
https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32S3/img/4.jpg
https://files.seeedstudio.com/wiki/XIAO_WiFi/board-pic.png
Yesterday I have left one of these for some time on the Hyperterminal and there also a strange behaviour after some time. 2 different laptops, 3 different boards and the same behaviour…
Hi again.
Unfortunately, I’m not familiar with those models.
Maybe it’s something related to the hardware of that specific model…
Regards,
Sara
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.
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…
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?
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.
Hi.
Yes.
That should work.
Regards,
Sara
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
Hi.
We need to update this tutorial to be compatible with the latest version of the ESP32 core.
Meanwhile, I’m currently out of the office and I cant do that at the moment.
Use this code as a reference instead: https://pastebin.com/raw/bmGr2qhX
Regards,
Sara
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.!
Hi.
Thanks for your comment.
Maybe in this scenario, it is not strictly necessary.
Try it out and tell me your results.
Regards,
Sara
The resistors are not necessay. It worked fine without them.
Nando
Great.
Thanks for letting me know.
Regards,
Sara
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!