概要
ESP32の特徴の一つに、”簡単にWiFiにつながる” が有ります。でもそのせいか自身の消費電力が若干大きい様に思えます。 そこで”DeepSleep" の出番です。
DeepSleepとは
Deep Sleepは、ESP32の主要な電源を落とし、RTC(Real-Time Clock)ドメインとRTCメモリのみを動かし続けるモードです。
- 停止する部分。
- メインCPU (Pro / App CPU)
- Wi-Fi および Bluetooth チップ
- ほとんどの標準GPIO (Digital GPIO)
- SRAM (メインメモリ)
- 稼働し続けている部分
- RTC関係
- RTCタイマー
- RTCコントローラー
- RTC周辺回路 (RTC_PERIPH)。 RTC GPIO を含む
- RTCメモリ
- ULPコプロセッサ
- RTC関係
実装のステップ
- ウェイクアップソースの設定
- 何をもってスリープを解除するかを、スリープに入る前に定義
手段 内容 タイマー復帰 指定した時間(マイクロ秒単位)で復帰
esp_sleep_enable_timer_wakeup()外部ピン復帰 特定のRTC GPIOの状態変化で復帰
esp_sleep_enable_ext0_wakeup() - 状態の維持
- DeepSleepに入る前にピンの状態をロックします。 gpio_hold_en();
- Deep Sleepスタート
- 関数 esp_deep_sleep_start(); でDeep Sleepスタート
- 復帰
- プログラムの続きからではなく setup() から再スタート
- setup() の冒頭で gpio_hold_dis() を呼ばないと、プログラムから再びピンを操作出来ない。
サンプルスケッチ
Timerをトリガーにした場合
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 5 //Time ESP32 will go to sleep (in seconds)
RTC_DATA_ATTR int bootCount = 0;
void setup(){
Serial.begin(115200);
delay(1000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
//Set timer to 5 seconds
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
" Seconds");
//Go to sleep now
esp_deep_sleep_start();
}
void loop(){
}
//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
- 4行: RTC_DATA_ATTR int bootCount = 0;
- RTC_DATA_ATTR:ディープスリープ中も値を保持する変数を宣言するための属性
- 12行: Serial.println("Boot number: " + String(bootCount));
- Bootの回数を表示
- 15行:ウェイクアップソースを表示
- 18行:esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
- タイマーを選択。ここでセットしています。
- 23行:esp_deep_sleep_start();
- ディープスリープ開始
下記はシリアルモニタの表示。 リブートの度に bootCount が増ると同時にリブートの原因を表示しています。
TimerをトリガーにRTC_GPIOの値を保持する場合
サンプルプログラムがここ=>確認に有ります。 参照下さい。
外部ピンを使う場合
ext0 External Wake-upと呼ばれる最もシンプルな外部信号復帰。
- 使用できるピン:0,2,4,12-15,25-27,32-39
- 使用関数: esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
- gpio_num: 復帰に使用するGPIO番号
- level: 復帰させる論理レベル。
- 1: HIGH になったら復帰。
- 0: LOW になったら復帰。
下記の回路とスケッチで動作を確認しました。
RTC_DATA_ATTR int bootCount = 0;
void setup(){
Serial.begin(115200);
delay(1000);
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
//Configure GPIO33 as ext0 wake up source for HIGH logic level
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
//Go to sleep now
esp_deep_sleep_start();
}
void loop(){}
//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
- 15行:esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
- ここでトリガーを設定しています。ポート33がHighになったらトリガーがかかる
プッシュボタンを押したら(Highになったら)トリガーがかかるスケッチとハードです。 問題無く動きました。
最後に
自作機器では電力消費を抑える為に DeepSleep をよく使用します。しっかり理解したい機能です。