When you create a new IoT project probably you need to connect microcontroller to a battary power source, but if you don’t use a power saving options your battery will run out in no time.
As a lot of IoT microcontroller, WeMos D1 mini have some power saving mode.
To create a simple rechargeable power bank read “Emergency power bank homemade “.
Here the WeMos D1 mini WeMos D1 mini - NodeMCU V2 V2.1 V3 - esp01 - esp01 programmer
The sleep modes types are modem sleep , light sleep , and deep sleep . The table below shows the differences between each mode.
Item Modem-sleep Light-sleep Deep-sleep Wi-Fi OFF OFF OFF System clock ON OFF OFF RTC ON ON ON CPU ON Pending OFF Substrate current 15 mA 0.4 mA ~20 uA Average current (DTIM = 1) 16.2 mA 1.8 mA – Average current (DTIM = 3) 15.4 mA 0.9 mA – Average current (DTIM = 10) 15.2 mA 0.55 mA –
Modem sleep
This is the default state of esp8266, but normally you interrupt this state when connect device via WIFI. But if you don’t use WIFI for a while, the better thing is to put the device in Modem-sleep.
You can put your device in modem-sleep with this command:
1
2
3
WiFi.disconnect();
WiFi.forceSleepBegin();
delay(1);
you can restore WIFI with:
1
2
3
WiFi.forceSleepWake();
delay(1);
Remember that if you want use a delay in normal mode you must add this:
1
wifi_set_sleep_type(NONE_SLEEP_T);
Or you must disabled the auto sleep mode (better explained in the next paragraph) we are going to call this function.
1
wifi_fpm_auto_sleep_set_in_null_mode(NULL_MODE);
Here a complete sketch, pay attention I use Serial1 to debug, refer to Part 3 WeMos D1 mini (esp8266), debug on secondary UART
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
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern
"C"
{
#include "user_interface.h"
}
const
char
* ssid =
"<your-ssid>"
;
const
char
* password =
"<your-passwd>"
;
void
setup() {
Serial1.begin(115200);
while
(!Serial1) { }
Serial1.println();
Serial1.println(
"Start device in normal mode!"
);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
}
void
callback() {
Serial1.println(
"Callback"
);
Serial.flush();
}
void
loop() {
Serial1.println(
"Enter modem sleep mode"
);
uint32_t
sleep_time_in_ms = 10000;
WiFi.forceSleepBegin();
delay(sleep_time_in_ms + 1);
WiFi.forceSleepWake();
delay(1);
Serial1.println(
"Exit modem sleep mode"
);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
wifi_set_sleep_type(NONE_SLEEP_T);
delay(10000);
}
This type of sleep mode, as you can see in the video permit to get 20mA of power consumption from the device.
Light sleep
This type of sleep is quite usefully if you need to mantain the device active, and the big difference from the previous type is that you can wake up the device via interrupt on GPIO.
To put on light sleep mode you must use this code, there isn’t a simple way to activate It like modem sleep.
You must add this configuration to the sketch:
1
2
3
4
5
6
7
8
9
10
11
uint32_t
sleep_time_in_ms = 10000;
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
wifi_fpm_set_wakeup_cb(callback);
wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
delay(sleep_time_in_ms + 1);
At the same manner we can use this code to enter in MODEM_SLEEP mode:
1
2
3
4
5
6
7
8
9
10
11
uint32_t
sleep_time_in_ms = 10000;
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_set_wakeup_cb(callback);
wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
delay(sleep_time_in_ms + 1);
The device go in light mode with less use of battery and less temperature.
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
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern
"C"
{
#include "user_interface.h"
}
const
char
* ssid =
"<your-ssid>"
;
const
char
* password =
"<your-passwd>"
;
void
setup() {
Serial1.begin(115200);
while
(!Serial1) { }
Serial1.println();
Serial1.println(
"Start device in normal mode!"
);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
}
void
callback() {
Serial1.println(
"Callback"
);
Serial.flush();
}
void
loop() {
Serial1.println(
"Enter light sleep mode"
);
uint32_t
sleep_time_in_ms = 10000;
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
wifi_fpm_set_wakeup_cb(callback);
wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
delay(sleep_time_in_ms + 1);
Serial1.println(
"Exit light sleep mode"
);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
wifi_set_sleep_type(NONE_SLEEP_T);
delay(10000);
}
This type of sleep mode, as you can see in the video permit to get 20mA of power to the device, to obtain better power saving you must set the wake up via GPIO.
Light sleep GPIO wake up
WeMos D1 mini on light sleep and debug on Serial1 check ampere
Light sleep can be wake up by GPIO interrupt, the command to set is
1
gpio_pin_wakeup_enable(GPIO_ID_PIN(LIGHT_WAKE_PIN), GPIO_PIN_INTR_LOLEVEL);
Than you must set max sleep time and than put a delay to activate all.
1
2
wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
delay(1000);
The complete code can be like this
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
#include "Arduino.h"
#include <ESP8266WiFi.h>
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
extern
"C"
{
#include "user_interface.h"
}
const
char
* ssid =
"<your-ssid>"
;
const
char
* password =
"<your-passwd>"
;
void
setup() {
Serial1.begin(115200);
while
(!Serial1) { }
Serial1.println();
Serial1.println(
"Start device in normal mode!"
);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
}
void
callback() {
Serial1.println(
"Callback"
);
Serial.flush();
}
#define LIGHT_WAKE_PIN D5
void
loop() {
Serial1.println(
"Enter light sleep mode"
);
gpio_pin_wakeup_enable(GPIO_ID_PIN(LIGHT_WAKE_PIN), GPIO_PIN_INTR_LOLEVEL);
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
wifi_fpm_set_wakeup_cb(callback);
wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
delay(1000);
Serial1.println(
"Exit light sleep mode"
);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
wifi_set_sleep_type(NONE_SLEEP_T);
delay(10000);
}
The result is
As you can see in the video the power saving is better (6mA), and you can use interrupt to restore device.
Deep sleep
The most common and most used modality is deep-sleep, a pratical application is to send data to a server every predefined time period.
You must put your device in deep-sleep set a timer to wake wake send data put device in sleep
All esp8266 (except esp01) have a pin with wake label, and through this pin connected to the RESET it will be possible to wake up the microcontroller.
WeMos D1 mini esp8266 pinout mischianti low resolution
You can se various sleep option, check your better choiche.
system_deep_sleep_set_option(0) The 108th Byte of init parameter decides whether RF calibration will be performed after the chip wakes up from Deep-sleep. system_deep_sleep_set_option(1) The chip will make RF calibration after waking up from Deep-sleep. Power consumption is high. system_deep_sleep_set_option(2) The chip won’t make RF calibration after waking up from Deep-sleep. Power consumption is low. system_deep_sleep_set_option(3) The chip won’t turn on RF after waking up from Deep-sleep. Power consumption is the lowest, same as in Modem-sleep.
On WeMos D1 mini, as you can see, the pin for wake il D0.
1
2
3
ESP.deepsleep(0)
ESP.deepsleep(5 * 1000000)
ESP.deepsleep(5000000, RF_DISABLED)
To wake a microcontroller you must put LOW reset PIN.
You can use a Wake pin (D0) connected to Reset to wake after some time, or you can use external button (or other) pulled up and than go LOW on key press.
After putting the esp8266 into deep sleep mode, there are 2 ways to wake it up:
By setting a timer with a button that put low Reset pin.
WeMos D1 mini deep sleep and debug on Serial1 check Ampere
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Arduino.h"
void
setup() {
Serial1.begin(115200);
while
(!Serial1) { }
Serial1.println();
Serial1.println(
"Start device in normal mode!"
);
delay(5000);
while
(!Serial1) { }
Serial1.println(
"I'm awake, but I'm going into deep sleep mode for 10 seconds"
);
ESP.deepSleep(10e6);
}
void
loop() {
}
The power that use device is similar to light-sleep with wake up via GPIO (6mA).
Automatic mode
By default the esp device have auto sleep mode enabled. If you add the code for light sleep or modem sleep at the setup and not disable the auto mode WeMos go in sleep automaticalli after 10 seconds of delay like so:
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
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern
"C"
{
#include "user_interface.h"
}
const
char
* ssid =
"<your-ssid>"
;
const
char
* password =
"<your-passwd>"
;
void
setup() {
Serial1.begin(115200);
while
(!Serial1) { }
Serial1.println();
Serial1.println(
"Start device in normal mode!"
);
WiFi.mode(WIFI_STA);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
}
unsigned
long
interval = 30000;
unsigned
long
previousMillis = millis() + interval;
void
loop() {
unsigned
long
currentMillis = millis();
if
(currentMillis - previousMillis >= interval) {
Serial1.println(
"Enter delay"
);
delay(20000);
Serial1.println(
"Exit delay"
);
WiFi.begin(ssid, password);
Serial1.println(
""
);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(
"."
);
}
Serial1.println(
""
);
Serial1.print(
"Connected to "
);
Serial1.println(ssid);
Serial1.print(
"IP address: "
);
Serial1.println(WiFi.localIP());
previousMillis = currentMillis;
}
}
the result is this:
When execute delay command for the first 10 seconds nothing append, than after that sleep mode is automatic activated.
WeMos D1 mini (esp8266), specs and IDE configuration
WeMos D1 mini (esp8266), integrated SPIFFS Filesystem
WeMos D1 mini (esp8266), debug on secondary UART
WeMos D1 mini (esp8266), the three type of sleep mode to manage energy savings
WeMos D1 mini (esp8266), integrated LittleFS Filesystem
esp12 esp07 (esp8266): flash, pinout, specs and IDE configuration
Firmware and OTA update management
Firmware management
esp8266: flash firmware binary (.bin) compiled and signed
esp8266: flash firmware and filesystem binary (.bin) compiled with GUI tools
OTA update with Arduino IDE
esp8266 OTA update with Arduino IDE: filesystem, signed and password
OTA update with Web Browser
esp8266 OTA update with Web Browser: firmware, filesystem and authentication
esp8266 OTA update with Web Browser: sign the firmware and HTTPS (SSL/TLS)
esp8266 OTA update with Web Browser: custom web interface
Self OTA uptate from HTTP server
esp8266 self OTA update firmware from server
esp8266 self OTA update firmware from server with version check
esp8266 self OTA update in HTTPS (SSL/TLS) with trusted self signed certificate
Non standard Firmware update
esp8266 firmware and filesystem update from SD card
esp8266 firmware and filesystem update with FTP client
esp32 and esp8266: FAT filesystem on external SPI flash memory
i2c esp8266: how to, network 5v, 3.3v, speed, and custom pins
[…]