The most common power-saving mode for ESP32 is deep sleep, and here we will see what deep sleep is and the difference between hibernate variants.
ESP32 practical power-saving deep sleep and hibernation
A hibernation-like sleep modem is a logical definition that you have to manage. There is no specific command, it is “activated” by applying a certain logic, and since this mode offers excellent advantages, it can push you to change the logic of your code.
In deep sleep mode, CPUs, most of the RAM, and all the digital peripherals, managed from the clock of the Advanced Peripheral Bus (APB_CLK), are powered off. The only parts of the chip which can still be powered on are real-time clock (RTC) controller, RTC peripherals, Ultra-Low Power (ULP) coprocessor, and RTC memories (slow and fast).
Function Block diagram Espressif esp32 Wi-Fi Bluetooth Microcontroller
In this table from the datasheet of esp32, there is information about group sleep mode.
Power mode
Description
Power
consumption
Active (RF working)
Wi-Fi Tx
packet
78 mA ~ 90 mA without communication
For TX RX more info in the next table
Wi-Fi/BT
Tx packet
Wi-Fi/BT Rx and
listening
Modem-sleep
The CPU
is powered on.
240 MHz *
Dual-core chip(s)
30 mA ~ 68 mA
Single-core chip(s)
N/A
160 MHz *
Dual-core chip(s)
27 mA ~ 44 mA
Single-core chip(s)
27 mA ~ 34 mA
Normal speed: 80 MHz
Dual-core chip(s)
20 mA ~ 31 mA
Single-core chip(s)
20 mA ~ 25 mA
Light-sleep
–
0.8 mA
Deep-sleep
The ULP
co-processor is powered on.
150 µ A
100
µ A @1% duty 10 µ A
ULP
sensor-monitored pattern
RTC timer + RTC
memory
Hibernation
RTC timer
only
5 µ A
Power off
CHIP_PU is set to
low level, the chip is powered off.
1 µ A
Deep sleep
Deep sleep is the most efficient way to put your device to sleep. Still, there is a big difference from light sleep, making it less usable. The state is cleared, so if you had set a variable when restarting your device, the variable is reset, and the program restarted from the initial setup.
Function Block diagram Espressif esp32 deep sleep
But you must pay attention; in my block diagram, I give color on peripheral because the only real difference from hibernate is what functional unit must remain active, here what write Espressif.
RTC IO module contains logic to trigger wakeup when one of RTC GPIOs is set to a predefined logic level. RTC IO is part of RTC peripherals power domain, so RTC peripherals will be kept powered on during deep sleep if this wakeup source is requested.
From Espressif documentation
So if we are going to use an external wake-up source, we will use a deep sleep; if we use nothing or only the RTC, we have a hibernation.
So here is a simple sketch to test deep sleep.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include
<WiFi.h>
#include
<BluetoothSerial.h>
#include
"driver/adc.h"
#include
<esp_bt.h>
#include
<esp_wifi.h>
#include
<esp_sleep.h>
#define
STA_SSID
"<YOUR-SSID>"
#define
STA_PASS
"<YOUR-PASSWD>"
BluetoothSerial SerialBT;
int
variable
=
0
;
void
setup
() {
Serial2.begin(
115200
);
while
(
!
Serial2){
delay
(
500
);}
SerialBT.begin(
"ESP32test"
);
SerialBT.println(
"START BT"
);
Serial2.println(
"START WIFI"
);
WiFi.begin(STA_SSID, STA_PASS);
while
(WiFi.status()
!
=
WL_CONNECTED) {
delay
(
500
);
Serial2.print(
"."
);
}
Serial2.println(
""
);
Serial2.println(
"WiFi connected"
);
Serial2.println(
"IP address: "
);
Serial2.println(WiFi.localIP());
delay
(
1000
);
Serial2.print(
"Initial Variable value = "
);
Serial2.println(variable);
variable
+
=
10
;
Serial2.print(
"Variable updated = "
);
Serial2.println(variable);
Serial2.println();
Serial2.println(
"DEEP SLEEP ENABLED FOR 5secs"
);
delay
(
100
);
esp_sleep_enable_timer_wakeup(
5
*
1000
*
1000
);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,
1
);
esp_deep_sleep_start();
Serial2.println();
Serial2.println(
"DEEP SLEEP WAKE UP"
);
Serial2.print(
"Variable = "
);
Serial2.println(variable);
}
void
loop
() {
}
void
disableWiFi(){
adc_power_off();
WiFi.disconnect(
true
);
WiFi.mode(WIFI_OFF);
Serial2.println(
""
);
Serial2.println(
"WiFi disconnected!"
);
}
void
enableWiFi(){
adc_power_on();
WiFi.disconnect(
false
);
WiFi.mode(WIFI_STA);
Serial2.println(
"START WIFI"
);
WiFi.begin(STA_SSID, STA_PASS);
while
(WiFi.status()
!
=
WL_CONNECTED) {
delay
(
500
);
Serial2.print(
"."
);
}
Serial2.println(
""
);
Serial2.println(
"WiFi connected"
);
Serial2.println(
"IP address: "
);
Serial2.println(WiFi.localIP());
}
void
disableBluetooth(){
btStop();
esp_bt_controller_disable();
delay
(
1000
);
Serial2.println(
"BT STOP"
);
}
When launching the sketch, we denote the first difference from light sleep, the variable state is not preserved in deep sleep mode, and the program flow restart from setup()
.
As you can see, the variable’s value is 0, and it is reset every time. And every time the esp32 comes out of deep sleep, it restarts from the initial. setup()
.
Now we are going to test this sketch with our three devices.
DOIT DEV KIT v1
esp32 dev kit pinout v1
For more information on the device, refer to “DOIT ESP32 DEV KIT v1 high resolution pinout and specs “.
Here is the connection schema we used.
Power the esp32 to the 5v pin and GND pin with an external power supply and disconnect the USB. To log, we use the Serial2 port, but if you want to use the Serial port, you must only move the FTDI converter to the TX pin instead TX2 pin; you can’t use USB because it powers the device, and the multimeter gets the wrong amperage.
Data
Again the result is not good; this device in hibernate consumes 12.19mA , very, very, very far from the 150µA declared from Espressif.
As happened for light sleep at first, I was depressed, but from the experience of light sleep, I understand that the device I use is not designed for production; in a dev board, there is a lot of other components that can change the result , like LEDs, voltage regulators, etc.
I try to do the same test with two famous boards vendors that have devices with battery management and other features, not only for development.
TTGO T8
First, I want to try a TTGO, one of the most famous productor of this kind of device, with many variants; I use one of its better products, the TTGO T8.
The power source at 5v from the specified pin gives a lousy result of 9.63mA . Still, when powered only with a battery, the board excludes some functional units like led, voltage regulator, etc., so the same test with battery power reaches 4.56mA more likely result.
WeMos LOLIN32
ESP32 WeMos LOLIN32 pinout
For more information on the device, refer to “ESP32 WeMos LOLIN32 high resolution pinout and specs “.
The wiring diagram
ESP32 WeMos LOLIN32 powered to 5V and Serial2 to debug amperage multimeter check
Wiring diagram with battery.
Then the WeMos LOLIN32; I love WeMos as a manufacturer, I believe I have a good set of devices, and these are very versatile with various sizes.
The result with the power source at 5v from the specified pin gives a better result, 2.92mA , and the board, when powered only with the battery, reaches 1.81mA .
Device Mode Power DOIT DEV KIT v1 Power to VIN pin 12.19mA TTGO T8 Power to 5V pin 9.63mA Power via Battery 4.56mA WeMos LOLIN32 Power via 5V pin 2.92mA Power via Battery 1.81mA
Hibernation
Hibernation is similar to deep sleep, but you have to give up some wake-up possibilities like external sources.
Function Block diagram Espressif esp32 hibernation
I create a simple sketch to test the hibernation performance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include
<WiFi.h>
#include
<BluetoothSerial.h>
#include
"driver/adc.h"
#include
<esp_bt.h>
#include
<esp_wifi.h>
#include
<esp_sleep.h>
#define
STA_SSID
"<YOUR-SSID>"
#define
STA_PASS
"<YOUR-PASSWD>"
BluetoothSerial SerialBT;
int
variable
=
0
;
void
setup
() {
Serial2.begin(
115200
);
while
(
!
Serial2){
delay
(
500
);}
SerialBT.begin(
"ESP32test"
);
SerialBT.println(
"START BT"
);
Serial2.println(
"START WIFI"
);
WiFi.begin(STA_SSID, STA_PASS);
while
(WiFi.status()
!
=
WL_CONNECTED) {
delay
(
500
);
Serial2.print(
"."
);
}
Serial2.println(
""
);
Serial2.println(
"WiFi connected"
);
Serial2.println(
"IP address: "
);
Serial2.println(WiFi.localIP());
delay
(
1000
);
Serial2.print(
"Initial Variable value = "
);
Serial2.println(variable);
variable
+
=
10
;
Serial2.print(
"Variable updated = "
);
Serial2.println(variable);
Serial2.println();
Serial2.println(
"DEEP SLEEP ENABLED FOR 5secs"
);
delay
(
100
);
esp_sleep_enable_timer_wakeup(
5
*
1000
*
1000
);
esp_deep_sleep_start();
Serial2.println();
Serial2.println(
"DEEP SLEEP WAKE UP"
);
Serial2.print(
"Variable = "
);
Serial2.println(variable);
}
void
loop
() {
}
void
disableWiFi(){
adc_power_off();
WiFi.disconnect(
true
);
WiFi.mode(WIFI_OFF);
Serial2.println(
""
);
Serial2.println(
"WiFi disconnected!"
);
}
void
enableWiFi(){
adc_power_on();
WiFi.disconnect(
false
);
WiFi.mode(WIFI_STA);
Serial2.println(
"START WIFI"
);
WiFi.begin(STA_SSID, STA_PASS);
while
(WiFi.status()
!
=
WL_CONNECTED) {
delay
(
500
);
Serial2.print(
"."
);
}
Serial2.println(
""
);
Serial2.println(
"WiFi connected"
);
Serial2.println(
"IP address: "
);
Serial2.println(WiFi.localIP());
}
void
disableBluetooth(){
btStop();
esp_bt_controller_disable();
delay
(
1000
);
Serial2.println(
"BT STOP"
);
}
To put the devices in hibernation instead of Deep sleep, I remove the external wake-up source ext0. Remember ext0 put in deep sleep, but ext1 prevent the use of deep sleep.
DOIT DEV KIT v1
The hibernation has better results concerning deep sleep, and DEV KIT v1 consumes 3.46mA , but It’s very far from the 5µA declared from Espressif.
I try to do the same test with two famous boards vendor devices with battery management and other features, not only for dev.
TTGO T8
The result with the power source at 5v from the specified pin gives a bad result of 7.95mA , but the same test with battery power reach 3.33mA, relatively better than the first result and then DOIT DEV KIT v1.
WeMos LOLIN32
The result with the power source at 5v from the specified pin gives a better result of 1.26mA , but the board, when powered only with a battery, reaches 160µA, which is a perfect result.
Results
The data is unequivocal, and the DOIT DEV KIT v1 is the loser and the LOLIN32 winner. TTGO has the highest price cannot be considered up to par.
Device Mode Power DOIT DEV KIT v1 Power to VIN pin 3.46mA TTGO T8 Power to 5V pin 7.95mA Power via Battery 3.33mA WeMos LOLIN32 Power via 5V pin 1.26mA Power via Battery 160µA
Thanks
ESP32: pinout, specs and Arduino IDE configuration
ESP32: integrated SPIFFS Filesystem
ESP32: manage multiple Serial and logging
ESP32 practical power saving
ESP32 practical power saving: manage WiFi and CPU
ESP32 practical power saving: modem and light sleep
ESP32 practical power saving: deep sleep and hibernation
ESP32 practical power saving: preserve data, timer and touch wake up
ESP32 practical power saving: external and ULP wake up
ESP32 practical power saving: UART and GPIO wake up
ESP32: integrated LittleFS FileSystem
ESP32: integrated FFat (Fat/exFAT) FileSystem
ESP32-wroom-32
ESP32-wroom-32: flash, pinout, specs and IDE configuration
ESP32-CAM
ESP32-CAM: pinout, specs and Arduino IDE configuration
ESP32-CAM: upgrade CamerWebServer with flash features
ESP32: use ethernet w5500 with plain (HTTP) and SSL (HTTPS)
ESP32: use ethernet enc28j60 with plain (HTTP) and SSL (HTTPS)
How to use SD card with esp32
esp32 and esp8266: FAT filesystem on external SPI flash memory
Firmware and OTA update management
Firmware management
ESP32: flash compiled firmware (.bin)
ESP32: flash compiled firmware and filesystem (.bin) with GUI tools
OTA update with Arduino IDE
ESP32 OTA update with Arduino IDE: filesystem, firmware, and password
OTA update with Web Browser
ESP32 OTA update with Web Browser: firmware, filesystem, and authentication
ESP32 OTA update with Web Browser: upload in HTTPS (SSL/TLS) with self-signed certificate
ESP32 OTA update with Web Browser: custom web interface
Self OTA uptate from HTTP server
ESP32 self OTA update firmware from the server
ESP32 self OTA update firmware from the server with version check
ESP32 self-OTA update in HTTPS (SSL/TLS) with trusted self-signed certificate
Non-standard Firmware update
ESP32 firmware and filesystem update from SD card
ESP32 firmware and filesystem update with FTP client
Integrating LAN8720 with ESP32 for Ethernet Connectivity with plain (HTTP) and SSL (HTTPS)
Connecting the EByte E70 to ESP32 c3/s3 devices and a simple sketch example
ESP32-C3: pinout, specs and Arduino IDE configuration
Integrating W5500 with ESP32 Using Core 3: Native Ethernet Protocol Support with SSL and Other Features
Integrating LAN8720 with ESP32 Using Core 3: Native Ethernet Protocol Support with SSL and Other Features
Dallas ds18b20:
Guide to I2C on ESP32: Communication with Heterogeneous 5V and 3.3V Devices, Additional Interface Management and Scanner