MicroPython: ESP32 Deep Sleep and Wake Up Sources

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.

MicroPython Deep Sleep with ESP32 timer wake up 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.

Prerequisites

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:

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:

machine.deepsleep(sleep_time_ms)

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)

View raw code

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).

machine.deepsleep(10000)

After 10 seconds, the ESP32 wakes up and runs the code from the start, similarly to when you press the EN/RST button.

Demonstration

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!

Schematic Diagram

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.

ESP32 pushbutton external wake up micropython ext0

Script

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()

View raw code

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:
    • WAKEUP_ANY_HIGH
    • WAKEUP_ALL_LOW

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:

machine.deepsleep()

Demonstration

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

ESP32 micropython 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:

Schematic Diagram

Wire the circuit by following the next schematic diagram.

ESP32 ext1 external wake up source micropython deep sleep

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.

Script

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()

View raw code

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:
    • WAKEUP_ANY_HIGH
    • WAKEUP_ALL_LOW

After defining the wake up source, you can put the ESP32 in deep sleep:

machine.deepsleep()

Wrapping Up

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:

Thanks for reading.



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

Recommended Resources

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

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

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

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

4 thoughts on “MicroPython: ESP32 Deep Sleep and Wake Up Sources”

  1. Hello,

    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 :/

    Reply
  2. 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.

    Reply
    • Set the led pin value to 0 to turn it off, then hold the state.

      Example:

      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)

      Reply
  3. Hi,
    thx for your tutorial but
    which could be reason why
    deepsleep(300000) makes my esp32 sleep for 15 minutes instead of 5 ? and this happens consistently
    Thanks
    Bruno

    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.