Deep Sleep & Wake-up Sources

更新日: 2026.04.21

概要

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コプロセッサ

実装のステップ

  1. ウェイクアップソースの設定
    • 何をもってスリープを解除するかを、スリープに入る前に定義
    • 手段内容
      タイマー復帰指定した時間(マイクロ秒単位)で復帰
      esp_sleep_enable_timer_wakeup()
      外部ピン復帰 特定のRTC GPIOの状態変化で復帰
      esp_sleep_enable_ext0_wakeup()
  2. 状態の維持
    • DeepSleepに入る前にピンの状態をロックします。 gpio_hold_en();
  3. Deep Sleepスタート
    • 関数 esp_deep_sleep_start(); でDeep Sleepスタート
  4. 復帰
    • プログラムの続きからではなく setup() から再スタート
    • setup() の冒頭で gpio_hold_dis() を呼ばないと、プログラムから再びピンを操作出来ない。

サンプルスケッチ

Timerをトリガーにした場合

sample.ino arduino
#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 が増ると同時にリブートの原因を表示しています。

[ets Jul 29 2019 12:21:46 rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0030,len:4980 load:0x40078000,len:16612 load:0x40080400,len:3480 entry 0x400805b4 Boot number: 1 Wakeup was not caused by deep sleep: 1 Setup ESP32 to sleep for every 5 Seconds ets Jul 29 2019 12:21:46 rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0030,len:4980 load:0x40078000,len:16612 load:0x40080400,len:3480 entry 0x400805b4 Boot number: 2 Wakeup caused by timer Setup ESP32 to sleep for every 5 Seconds ets Jul 29 2019 12:21:46 rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0030,len:4980 load:0x40078000,len:16612 load:0x40080400,len:3480 entry 0x400805b4 Boot number: 3 Wakeup caused by timer Setup ESP32 to sleep for every 5 Seconds ets Jul 29 2019 12:21:46

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 になったら復帰。

下記の回路とスケッチで動作を確認しました。

Circuit diagram for ESP32 ext0 wakeup using GPIO33 and a push button
sample.ino arduino
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 をよく使用します。しっかり理解したい機能です。

SINCE 2026