This tutorial shows how to put the ESP32 in deep sleep mode and wake it up using different wake up sources using MicroPython firmware. We’ll cover timer wake up and external wake up.
The ESP32 can also be awaken from deep sleep using the touch pins by defining a threshold. Although this feature is already implemented in MicroPython, it is not working properly at the time of writing this tutorial. We’ll update this article as soon as it is working.
Deep sleep with the ESP8266 works a bit different than with the ESP32. So, we’ve created a dedicated article to deep sleep with ESP8266 using MicroPython.
If you have an ESP8266, we recommend reading our MicroPython ESP8266 Deep Sleep and Wake Up Sources Guide.
To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:
- Thonny IDE:
- uPyCraft IDE:
- Getting Started with uPyCraft IDE
- Install uPyCraft IDE (Windows, Mac OS X, Linux)
Learn more about MicroPython: MicroPython Programming with ESP32 and ESP8266 eBook
Introducing Deep Sleep
Having your ESP32/ESP8266 running on active mode with batteries it’s not ideal, since the power from batteries will drain very quickly.
If you put your ESP32 in deep sleep mode, it will reduce the power consumption and your batteries will last longer. Having the ESP32 in deep sleep mode means cutting with the activities that consume more power while operating but leave just enough activity to wake up the processor when something interesting happens.
When operating in deep sleep mode, the ESP32 have a current consumption on the μA range. With a custom and carefully designed board you can get a minimal comsumption of only 5 μA. However, if you use a full-feature ESP32 development board with built-in programmer, on-board LEDs, and so on (like the ESP32 DOIT board) you won’t be able to achieve such a low power state, but you can still save power.
Wake Up Sources
After putting the ESP32 into deep sleep mode, there are several ways to wake it up:
- You can use the timer: waking up the ESP32 after predefined periods of time.
- You can use an external wake up: this means the ESP32 can wake up when a change in the state of a pin occurs.
- You can use the touch pins: implemented, but not working as expected at the time of writing, so we won’t cover this at the moment;
- You can use the ULP co-processor to wake up: we haven’t tested this feature yet.
Timer Wake Up
The ESP32 can go into deep sleep mode, and then wake up at predefined periods of time. This feature is especially useful if you are running projects that require time stamping or daily tasks, while maintaining low power consumption.
To put the ESP32 in deep sleep mode for a predetermined number of seconds, you just have to use the deepsleep() function from the machine module. This function accepts as arguments, the sleep time in milliseconds as follows:
Let’s look at a simple example to see how it works. In the following code, the ESP32 is in deep sleep mode for 10 seconds, then it wakes up, blinks an LED, and goes back to sleep.
# Complete project details at https://RandomNerdTutorials.com from machine import deepsleep from machine import Pin from time import sleep led = Pin (2, Pin.OUT) #blink LED led.value(1) sleep(1) led.value(0) sleep(1) # wait 5 seconds so that you can catch the ESP awake to establish a serial communication later # you should remove this sleep line in your final script sleep(5) print('Im awake, but Im going to sleep') #sleep for 10 seconds (10000 milliseconds) deepsleep(10000)
How the Code Works
First, import the necessary libraries:
import machine from machine import Pin from time import sleep
Create a Pin object that refers to GPIO 2 called led. This refers to the on-board LED.
led = Pin (2, Pin.OUT)
The following commands blink the LED.
led.value(1) sleep(1) led.value(0) sleep(1)
In this case, we’re blinking an LED for demonstration purposes, but the idea is to add your main code in this section of the script.
Before going to sleep, we add a delay of 5 seconds and print a message to indicate that it’s going to sleep.
sleep(5) print('Im awake, but Im going to sleep')
It’s important to add a 5 seconds delay before going to sleep when we are developing the scripts. When you want to upload a new code to the board, it needs to be awake. So, if you don’t have the delay, it will be difficult to catch it awake to upload new code later on. After having the final code, you can delete that delay.
Finally, put the ESP32 in deep sleep for 10 seconds (10 000 milliseconds).
After 10 seconds, the ESP32 wakes up and runs the code from the start, similarly to when you press the EN/RST button.
Copy the code provided to the main.py file of your ESP32. Upload the new code and press the EN/RST button after uploading.
The ESP32 should blink the on-board LED and print a message. Then, it goes to sleep. This is repeated over and over again.
If you don’t know how to upload the script follow this tutorial if you’re using Thonny IDE, or this one if you’re using uPyCraft IDE.
External Wake Up
The ESP32 can also be awaken from sleep when there is a change on the state of a pin. There are two possibilities of external wake up with the ESP32: ext0 and ext1.
The ext0 mode allows you to use one GPIO as a wake up source. The ext1 mode allows you to set more than one GPIO as a wake up source at the same time.
Only RTC GPIOs can be used as a wake up source. The RTC GPIOs are highlighted with an orange rectangle box in the next diagram.
Learn more about the ESP32 GPIOs: ESP32 Pinout Reference: Which GPIO pins should you use?
External wake up – ext0
To illustrate how to use the external wake up ext0, we’ll use one pushbutton as a wake up source. The ESP32 awakes when you press the pushbutton.
For this example, you need the following components:
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!
Wire the circuit by following the next schematic diagram. In this example, we’re using GPIO14 to wake up the ESP32, but you can use any other RTC GPIO.
The following script shows how ext0 works: it uses one GPIO as an external wake up source.
# Complete project details at https://RandomNerdTutorials.com import esp32 from machine import Pin from machine import deepsleep from time import sleep wake1 = Pin(14, mode = Pin.IN) #level parameter can be: esp32.WAKEUP_ANY_HIGH or esp32.WAKEUP_ALL_LOW esp32.wake_on_ext0(pin = wake1, level = esp32.WAKEUP_ANY_HIGH) #your main code goes here to perform a task print('Im awake. Going to sleep in 10 seconds') sleep(10) print('Going to sleep now') deepsleep()
How the code works
First, you need to import the necessary modules. You need to import the esp32 module that contains the methods to set a pin as a wake up source.
After importing the necessary modules, define a wake up pin. In this case we’re using GPIO14 and we call it wake1. This GPIO should be set as an input (Pin.IN).
wake1 = Pin(14, mode = Pin.IN)
Then, set ext0 as a wake up source using the wake_on_ext0() method as follows:
esp32.wake_on_ext0(pin = wake1, level = esp32.WAKEUP_ANY_HIGH)
The wake_on_ext0() method accepts as arguments the pin and the level:
- pin: an object of type Pin (the GPIO that acts as a wake up source)
- level: defines the state of the GPIO that wakes up the ESP32. The level can be one of the following parameters:
In this case, we’re using the WAKEUP_ANY_HIGH method that wakes up the ESP32 when the GPIO goes HIGH.
Your main code to execute a task should go after defining the wake up source and right before going to sleep.
We add a 10 second delay before going to sleep. To put the ESP32 into deep sleep, you just need to use the deepsleep() method as follows:
Upload the code to the ESP32 main.py file. Press the EN/RESET button to run the code. The ESP32 should go to sleep.
Now, you can press the button to wake it up from deep sleep.
External wake up – ext1
External wake up ext1 works very similar to ext0 but it allows you to set more than one GPIO as a wake up source. To demonstrate how it works we’ll use two pushbuttons wired to different GPIOs.
For this example, you need the following components:
Wire the circuit by following the next schematic diagram.
In this case, we’re using GPIO14 and GPIO12. You can use any other suitable GPIOs, but these need to be RTC GPIOs, otherwise this method doesn’t work.
The following script shows how ext1 works: it uses two GPIOs as an external wake up source, but you can use more if you want.
# Complete project details at https://RandomNerdTutorials.com import esp32 from machine import deepsleep from machine import Pin from time import sleep wake1 = Pin(14, mode = Pin.IN) wake2 = Pin(12, mode = Pin.IN) #level parameter can be: esp32.WAKEUP_ANY_HIGH or esp32.WAKEUP_ALL_LOW esp32.wake_on_ext1(pins = (wake1, wake2), level = esp32.WAKEUP_ANY_HIGH) #your main code goes here to perform a task print('Im awake. Going to sleep in 10 seconds') sleep(10) print('Going to sleep now') deepsleep()
How the code works
The code is similar to the ext0 example, but it uses the wake_on_ext1() method instead.
esp32.wake_on_ext1(pins = (wake1, wake2), level = esp32.WAKEUP_ANY_HIGH)
The wake_on_ext1() method accepts as arguments the pins and the level:
- pins: a tupple or list with objects of type Pin (the GPIOs that act as a wake up source)
- level: defines the state of the GPIOs that will wake up the ESP32. The level can be one of the following parameters:
After defining the wake up source, you can put the ESP32 in deep sleep:
We hope you’ve found this tutorial about deep sleep with the ESP32 using MicroPython useful. We’ve covered timer wake up and external wake up. There is also the possibility to wake up the ESP32 using the touch pins. Although this is already available in the latest MicroPython firmware, it is not working as expected, so we didn’t include it in the tutorial. In the meanwhile, you can use ESP32 Touch Wake Up with Arduino IDE.
If you want to learn more about programming the ESP32 and ESP8266 boards with MicroPython, take a look our eBook: MicroPython Programming with ESP32 and ESP8266.
We have other tutorials related with deep sleep that you might be interested:
- Low Power Weather Station Datalogger (MicroPython)
- ESP32 Deep Sleep and Wake Up Sources (Arduino IDE)
- ESP8266 Deep Sleep (Arduino IDE)
- ESP8266 Deep Sleep and Wake Up Sources (MicroPython)
Thanks for reading.
3 thoughts on “MicroPython: ESP32 Deep Sleep and Wake Up Sources”
Thanks for a great tutorial. I followed it and noticed my ESP8266 NodeMCU v3 is waking for a random number ot times and after that stops sending messages (mqtt). In a debug.log which I created I see the last entry just before machine.deepsleep(10000) command.
And strange thing is that in theory it should be put into sleep but I can connect it using rshell so it is waken up but not rinning the code (sending mqtt).
Have no idea what is wrong :/
No real difference in DeepSleep between the ESP32 and 8266 except that the reset pin (RST) needs to be physically connected to GPIO16 (D2 on the board).
What irritates me is that on the ESP32 the PowerLED doesn’t turn off in DeepSleep which renders it pretty much useless for long term battery operation. If anyone knows how to turn it off I’d love to know.
Set the led pin value to 0 to turn it off, then hold the state.
run this at the beginning of your code
esp32 built in led pin==2
led = machine.Pin(2, machine.Pin.OUT, None)
run this at the end of your code before running deep sleep
led.value(0) # turn light off
led = machine.Pin(2, machine.Pin.OUT, machine.Pin.PULL_HOLD)