Network applications consume a lot of power. If such applications are battery-powered, there is a risk of the battery running out due to the high power demands of network functions.
Often, power is also wasted on non-essential microcontroller activities. For example, power can remain on for multiple integrated peripherals regardless of their use or relevance in the application. Fortunately, Wi-Fi development boards like ESP8266 and ESP32 offer sleep modes to save net power consumption, which are recommended in networking applications.
This saves battery power for the app rather than wasting it on the controller's peripherals. Here we will discuss sleep modes on ESP8266 and ESP32 boards and explore how they can be used in MicroPython.
Sleep modes
In ESP8266, there are three sleep modes:
1. Modem suspension. Wi-Fi turns off in modem sleep mode while the CPU, system clock, and RTC remain on. In this state, the substrate current consumed by the SoC is 15 mA.
If each beacon transmits the Delivery Traffic Indication Message (DTIM) through the Wi-Fi module, the power consumption will be approximately 16.2 mA. If every three beacons transmit DTIM, the power consumption will be approximately 15.4 mA. And if DTIM is transmitted every 10 beacons, the power consumption will be approximately 15.2 mA.
Note that the DTIM message is transmitted by the Wi-Fi module every three beacons by default.
2. Light sleep
The CPU remains in soft sleep mode when Wi-Fi and system clock are off. The RTC responsible for maintaining the date and time remains activated. In this state, the substrate current consumed by the SoC is 0.4 mA. If each beacon transmits the DTIM through the Wi-Fi module, the power consumption will be approximately 1.8 mA. If every three beacons transmit DTIM, the power consumption will be approximately 0.9 mA. And if DTIM is transmitted every 10 beacons, the power consumption will be about 0.55 mA.
Again, the default DTIM value in the network settings is three.
3. Deep sleep
In deep sleep mode, the CPU, system clock and Wi-Fi are turned off and only RTC remains on to maintain the date and time. The controller remains in an idle state and no DTIM is transmitted. Normal controller operations resume only when the controller “wakes up” from deep sleep. In this mode, the current consumed by the ESP8266 SoC is reduced to 20 uA.
Only the ESP8266 offers all sleep modes. By default, MicroPython only supports light and deep sleep modes. Therefore, a specific ESP module is required for modem sleep mode.
If an SoC enters deep sleep mode, the net power consumption of a breakout board may be in mA. Integrated components and peripherals – such as LEDs, power regulator, USB serial chip and other interfaces – can still consume significant power regardless of the fact that the SoC itself is in an idle state, consuming only a few micro-amps of current.
Waking up on ESP8266
Depending on the port, different activation sources are available. For example, in ESP8266, only two wake-up sources are available: timer and external.
In timer wake-up, the built-in RTC is used to wake up
the SoC goes into deep sleep after a specified period.
On external wake-up, the SoC goes into deep sleep until the reset button is pressed. On the ESP8266, the reset button must be connected to GPIO16 for the board to activate. On a breakout board, the reset button may already be connected to the onboard GPIO16 or require an external connection.
The deep sleep cycle
Deep sleep mode is useful in battery-powered network applications. The chip then remains in deep sleep or inactive, only waking up periodically to perform its assigned tasks. Tasks can include taking readings from a sensor, sending the sensor data to a server via an IoT protocol (such as MQTT or CoAP), and taking an on-site action based on the sensor readings or insights received over the network.
After the task is performed by the user application, the chip goes back to sleep. This cycle of deep sleep, waking up, doing embedded/IoT tasks, and going back to sleep goes on and on.
MicroPython
The MicroPython machine module provides these functions for power management of supported boards.
machine.lightsleep((time_ms)): puts the port in light sleep mode. If time in milliseconds is specified as an argument, soft sleep mode lasts for the maximum time specified. The port may activate before the timeout if a source triggers it. If no arguments are passed, soft sleep lasts until interrupted by a wake source.
machine.deepsleep((time_ms)): puts the port in deep sleep mode. If time in milliseconds is specified as an argument, deep sleep mode lasts for the specified maximum time. The port may activate before the timeout if a source triggers it. If no arguments are passed, deep sleep continues until interrupted by a wake source. Waking up from deep sleep mode is the same as a hard reset.
machine.wake_reason: This method returns the wake source. The return value can be machine.WLAN_WAKE, machine.PIN_WAKE, or machine.RTC_WAKE, depending on whether the wake source is WLAN, pin change, or RTC. This method can be used to record the activation reason in a variable or print the activation reason to the console.
However, the wake source must be configured before requesting light or deep sleep. Furthermore, machine.wake_reason can only be called after requesting light or deep sleep.
The machine module offers another useful function for port power management. This is machine.idle . Calling this method blocks the CPU clock, causing the port to go into sleep mode, where the port wakes up when an interrupt is received.
MicroPython Sleep Modes on ESP8266
The ESP8266 sleep mode can be accessed using the power-related functions of the machine module or the ESP8266 functions, which are available through the specially module.
These functions only allow the user to place the ESP8266 into light or deep sleep modes (as discussed above). But the specific functions of the ESP module allow the user to put the ESP8266 into light, deep or modem sleep.
The specially module can be imported into a MicroPython script using this statement: import esp
The specially module provides these functions to put the ESP8266 into different sleep modes…
esp.sleep_type((sleep_type)): Sets or gets the ESP8266 sleep mode. If the method is called with an argument, it sets the ESP8266 to the specified sleep mode. If the method is called without arguments, it returns the ESP8266 to sleep.
Parameters can be defined using these arguments: SLEEP_NONE, SLEEP_MODEM and SLEEP_LIGHT. If set to SLEEP_NONE, the ESP8266 remains in active mode or resumes active mode from sleep mode. If set to SLEEP_MODEM, the ESP8266 is placed in modem sleep mode. If set to SLEEP_LIGHT, the ESP8266 is put into light sleep mode.
esp.deepsleep(time_us=0, /): puts the ESP8266 into deep sleep for a specified time (in microseconds). If a sleep time is specified, the built-in RTC will be used as the timer. If time is not specified as an argument, the ESP8266 goes into deep sleep until there is an external wake-up.
Whether the ESP8266 is put into deep or light sleep using the power-related functions of the machine module or functions of the specially module, the GPIO16 must be connected to the reset button for the wake-up timer to work. This is typically done by an external circuit connection on most ESP8266 breakout boards.
Working the wake-up timer
To wake up with timer, connect GPIO16 to the ESP8266 reset button.
To detect wake-up, an LED will flash after the ESP8266 wakes up from any sleep mode. For this to work, connect an LED to GPIO2 as shown below.
To put the ESP8266 into modem sleep mode and then wake up from a timer, use the specially module. This MicroPython script puts the ESP8266 into modem sleep mode and blinks an LED, which is connected to GPIO2, every time the ESP8266 wakes up because of the timer.
import esp
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
def modem_sleep(msec):
rtc = machine.RTC
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msec)
esp.sleep_type(SLEEP_MODEM)
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to sleep with the modem')
#sleep for 10 seconds (10,000 milliseconds)
modem_sleep(10000)
To put the ESP8266 into soft sleep mode and then wake up from the timer, use the specially module or power-related functions of the machine module. This MicroPython script puts the ESP8266 into a soft sleep mode using the specially module and blinks an LED, which is connected to GPIO2, every time the ESP8266 wakes up because of the timer.
import esp
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
def light_sleep(msec):
rtc = machine.RTC
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msec)
esp.sleep_type(SLEEP_LIGHT)
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to get some sleep')
#sleep for 10 seconds (10,000 milliseconds)
light_sleep(10000)
This MicroPython script puts the ESP8266 into soft sleep mode using the machine module, blinking an LED connected to GPIO2 every time the ESP8266 wakes up because of the timer.
import machine
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
def light_sleep(msec):
rtc = machine.RTC
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msec)
machine.lightsleep
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to get some sleep')
#sleep for 10 seconds (10,000 milliseconds)
light_sleep(10000)
To put the ESP8266 into deep sleep mode and then wake up from the timer, use the specially module or power-related functions of the machine module. This MicroPython script puts the ESP8266 into deep sleep mode using the specially module and blinks an LED, which is connected to GPIO2 every time the ESP8266 wakes up because of the timer.
import esp
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
def deep_sleep(msec):
rtc = machine.RTC
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msec)
esp.deepsleep
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to sleep soundly')
#sleep for 10 seconds (10,000 milliseconds)
deep_sleep(10000)
This MicroPython script puts the ESP8266 into deep sleep mode using the machine module and blinks an LED, connected to GPIO2, every time the ESP8266 wakes up because of the timer.
import machine
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
def deep_sleep(msec):
rtc = machine.RTC
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msec)
machine.deepsleep
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to sleep soundly')
#sleep for 10 seconds (10,000 milliseconds)
deep_sleep(10000)
Working on external awakening
In ESP8266, external wake-up is triggered whenever the reset button is pressed. This wake-up is only useful when the ESP8266 is in deep sleep mode. The reset button on the breakout board can be pressed for external activation or a pull-up button can be connected to the reset pin.
To put the ESP8266 into deep sleep mode and then wake up via external, use the specially module or power related functions of the machine module. This MicroPython script puts the ESP8266 into deep sleep mode using the specially module and blinks an LED, connected to GPIO2, every time the ESP8266 wakes up from an external reset.
import esp
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to sleep soundly')
sleep (1)
esp.deepsleep
This MicroPython script puts the ESP8266 into deep sleep mode using the machine module and blinks an LED, connected to GPIO2, every time the ESP8266 wakes up from an external reset.
import machine
Machine Import Pin
of time matter sleep
led = Pin (2, Pin.OUT)
#LED flashes
led.value(1)
sleep (1)
led.value(0)
sleep (1)
# wait 5 seconds so you can wake up the ESP to establish serial communication later
# you must remove this suspend line in your final script
sleep (5)
print('I'm awake, but I'm going to sleep soundly')
sleep (1)
machine.deepsleep
For an external restart, the esp.deepsleep or machine.deepsleep methods are called without arguments. These calls place the ESP8266 into deep sleep until an external wake-up is detected via the reset button. The button connected to the external wake-up reset button must be pulled up.
Learn how to use ESP32 sleep and wake modes in MicroPython here .