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:
WiFi.disconnect();
WiFi.forceSleepBegin();
delay(1); //For some reason the modem won't go to sleep unless you do a delay
you can restore WIFI with:
WiFi.forceSleepWake();
delay(1);
//Insert code to connect to WiFi, start your servers or clients or whatever
Remember that if you want use a delay in normal mode you must add this:
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.
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
#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}
const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";
//The setup function is called once at startup of the sketch
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("");
// Wait for connection
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.disconnect();
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("");
// Wait for connection
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); // Put the esp to sleep for 15s
}
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:
// Here all the code to put con light sleep
// the problem is that there is a bug on this
// process
//wifi_station_disconnect(); //not needed
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:
// Here all the code to put con light sleep
// the problem is that there is a bug on this
// process
//wifi_station_disconnect(); //not needed
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.
#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}
const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";
//The setup function is called once at startup of the sketch
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("");
// Wait for connection
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");
// Here all the code to put con light sleep
// the problem is that there is a bug on this
// process
//wifi_station_disconnect(); //not needed
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("");
// Wait for connection
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); // Put the esp to sleep for 15s
}
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
Light sleep can be wake up by GPIO interrupt, the command to set is
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.
wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
delay(1000);
The complete code can be like this
#include "Arduino.h"
#include <ESP8266WiFi.h>
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}
const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";
//The setup function is called once at startup of the sketch
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("");
// Wait for connection
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");
//wifi_station_disconnect(); //not needed
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("");
// Wait for connection
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); // Put the esp to sleep for 15s
}
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.
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.
ESP.deepsleep(0) // suspends the module until it is woken up by a spike on the RST pin
ESP.deepsleep(5 * 1000000) // wake up the module every 5 seconds
ESP.deepsleep(5000000, RF_DISABLED) // wakes up the module every 5 seconds without re-activating the WiFi modem
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.
#include "Arduino.h"
//The setup function is called once at startup of the sketch
void setup() {
Serial1.begin(115200);
while(!Serial1) { }
Serial1.println();
Serial1.println("Start device in normal mode!");
delay(5000);
// Wait for serial to initialize.
while(!Serial1) { }
// Deep sleep mode for 10 seconds, the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board) is connected to the RESET pin
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:
#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}
const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";
//The setup function is called once at startup of the sketch
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("");
// Wait for connection
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("");
// Wait for connection
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
- OTA update with Arduino IDE
- OTA update with Web Browser
- Self OTA uptate from HTTP server
- Non standard Firmware update
- esp32 and esp8266: FAT filesystem on external SPI flash memory
- i2c esp8266: how to, network 5v, 3.3v, speed, and custom pins
- […]