ESP32[26] RTC

ESP32にはRTCが内蔵されています。内臓RTCはDeep Sleep する前に起きる時間をマイクロ秒で指定します。

esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);

time_in_us の型は uint64_t(64ビット符号なし整数)なので、理論上の最大値は

2^64 - 1 = 18,446,744,073,709,551,615(マイクロ秒)

ですが、実際にESP32のハードウェアが対応できる最大値はもっと小さいです。
これは、RTCタイマーの精度と上限に依存します。

実際の最大値(目安)
多くのESP32系では、スリープの最大時間は約71分(~4,294,967,295μs ≒ 約4295秒)が限界です。

この値は32ビットのRTCタイマーを使っていることに由来します。

結論(実用上の最大値):
ESP32の場合、esp_sleep_enable_timer_wakeup() に指定できる実用上の最大値は:

time_in_us <= 4294967295 // 約71分

なので、これ以上の間寝かしておくには工夫が必要です。そんな場合は、

基本アイデア

  1. NVSに残りスリープ時間を保存
  2. 起動するたびにその時間を読み出し、再スリープ
  3. 時間が来たら通常処理を行う
#include <esp_sleep.h>

#define MAX_SLEEP_SEC   180    // 1回にスリープできる最大時間(例:3分 = 180秒)
#define TOTAL_SLEEP_SEC 10800  // 最初のスリープ時間(例:3時間 = 10800秒)

RTC_DATA_ATTR int total_sleep_sec = TOTAL_SLEEP_SEC;  // トータルスリープ時間を保持(スリープ状態でもデータ保持)

void setup() {
  Serial.begin(115200);
  delay(1000);

  // スリープから復帰後の処理
  Serial.println("=== ESP32 起動 ===");

  // RTCメモリから最初のスリープ時間を読み込む
  int initial_sleep = total_sleep_sec;

  // 残りスリープ時間を計算(最初のスリープ時間からMAX_SLEEP_SEC秒までスリープ)
  int sleep_now = (initial_sleep > MAX_SLEEP_SEC) ? MAX_SLEEP_SEC : initial_sleep;
  total_sleep_sec -= sleep_now;  // 残りスリープ時間を更新

  // 残りスリープ時間がある場合、次にスリープする
  if (total_sleep_sec > 0) {
    Serial.printf("次に %d 秒スリープします。残り %d 秒。\n", sleep_now, total_sleep_sec);
    esp_sleep_enable_timer_wakeup((uint64_t)sleep_now * 1000000ULL);
    Serial.flush(); // 出力完了を待つ
    esp_deep_sleep_start(); // ここでディープスリープに入る
  } else {
    // 残りのスリープ時間がない場合は、スリープなしで起動
    Serial.println("スリープ時間終了");
  }
}

void loop() {
  // 3分間のスリープ設定(MAX_SLEEP_SEC)
  int sleep_now = MAX_SLEEP_SEC;

  // スリープ時間を RTCメモリに保存(最初に設定したスリープ時間を保存)
  total_sleep_sec = TOTAL_SLEEP_SEC;

  // スリープ設定
  esp_sleep_enable_timer_wakeup((uint64_t)sleep_now * 1000000ULL);
  Serial.printf("最初のスリープ時間: %d秒\n", sleep_now);
  Serial.flush();

  // 最初のディープスリープに入る
  esp_deep_sleep_start();

  // ここには戻らない(スリープ後に再起動され、setup() が呼ばれる)
}

目的の時間まで何回も起きるので、IOが初期化されます。なので、すぐに、設定しなおしてまた寝る。確かにESP32の内臓RTCは使い方が簡単ですが、このように長期に寝る場合は、外付けのRTCをつけて、RTCに時間になったらESP32のIOをたたいて起こしてやる必要があるかもしれません。まさか、最大71分しか寝られないとは思いませんでした。3日はまりました。