Sunday, June 25, 2017

Demo 24: How to bring ESP32 to low power-sleep mode to extend battery life

1. Introduction
- When deploying IoT applications in area where power supply is not well-prepared, we often use battery for IoT node. The power of battery is limited so we have to save it. In order to save power, we will bring ESP to sleep mode in which ESP will not consume much power.
- Sleep mode is not applicable when ESP is in Access Point mode.
- When ESP is in sleep mode it need a trigger to wake it up. There are some types of trigger:
+ by external signal using RTC_IO.
+ by external signal using RTC_CNTL.
+ by timer.
+ by touchpad.
+ by ULP program.
- I will make 2 demos that using timer and RTC_IO for waking up.
2. Demo 1 using timer to wake up
- In order to bring ESP to sleep mode and wake up by timer, just use the function "ESP.deepSleep(time_in_micro_seconds)" which time_in_micro_seconds is the time ESP will spend in sleep mode.
Note: trigger wake ESP up by resetting it. You can see this by watching the Terminal or the setup() function will be invoked again. So you need to backup data before going to sleep mode using Preferences or sdacrd.
- I will make a demo that has 2 states: SETUP and RUNNING. In SETUP state just print "SETUP state" and then move to RUNNING state, backup this state to Preferences and going to low power-sleep mode for 5 seconds. After waking-up ESP will read the state from Preferences and move to that state without running SETUP state again.
 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
#include <Preferences.h>

/* possible states */
typedef enum {
  SETUP = 1,
  RUNNING  
}State;

State state = SETUP;
Preferences preferences;

void setup() {
  Serial.begin(115200);
  Serial.println("I waked up");
  /* setup Preferences */
  preferences.begin("iotsharing", false);
  /* restoring state, if not exist return default SETUP sate */
  state = (State)preferences.getUInt("state", SETUP);
}
void loop() {
  switch(state){
    case SETUP:
      Serial.println("SETUP state");
      state = RUNNING;
      break;
    case RUNNING:
      Serial.println("RUNNING state");
      /* save current state */
      preferences.putUInt("state", state);
      /* Close the Preferences */
      preferences.end();
      Serial.println("Bring ESP to sleep mode 5 seconds");
      /* 5e6 is 5x10^6 microseconds */
      ESP.deepSleep(5e6);
      break;
  }
}
Figure: using timer to wake up
3. Demo 2 using external signal RTC_IO to wake up
In this demo, we will use a button to make an external signal LOW level to wake ESP up. We re-use the circuit in Demo 21 but ignoring the LED.
Connections:
[ESP32 GIO12 - BUTTON - GND]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include "esp_deep_sleep.h"

void setup() {
  Serial.begin(115200);
  Serial.println("I waked up");
  /* set up RTC_IO for GPIO12 */
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
  /* enable pullup resister */
  gpio_pullup_en(GPIO_NUM_12);
  /* disable pullup resister */
  gpio_pulldown_dis(GPIO_NUM_12); // not use pulldown on GPIO
  /* anable deep sleep with external wakeup
  and input level which will trigger wakeup is LOW on GPIO12 */
  esp_deep_sleep_enable_ext0_wakeup(GPIO_NUM_12, LOW);

  Serial.println("Bring ESP to sleep mode until get external signal");
  esp_deep_sleep_start();
}

void loop() {
}
Figure: when pressing button a LOW level will trigger ESP waking up.

3 comments:

Marcus said...

Why didn't you use the hibernation mode?

Manymany Many said...

Hi, Thanks for your blog.

Is it not better to use that ?

RTC_DATA_ATTR unsigned int state;

Flash also has limited number of write cycle.

Emmanuel

iotsharing dotcom said...

Hi Marcus, there is no concept Hibernation mode as I knew :https://www.esp32.com/viewtopic.php?t=770

Hi Emmanuel, you can RTC_DATA_ATTR but i do not know it is possible to use it in Arduino. I need time to check.