概要
前回の記事では、ESP32C3とリードスイッチを使って郵便受けの開閉を検知し、Discordへ通知するところまで実装した。
ただ、この実装には大きな課題があった。
前回のコードでは loop() で常にリードスイッチの状態を監視しているため、ESP32C3が常時起動したままになる。
この状態だと電池消費が大きく、郵便受けのような電源がない場所で運用するには厳しい。
そこで今回は、バッテリー問題への対策としてESP32C3の Deep Sleep 機能を実装したので紹介する。
Deep Sleepとは?
ESP32C3には、バッテリー消費を抑えるための Deep Sleep 機能が搭載されている。
Deep Sleepを使うと、ESP32C3を低消費電力状態にできる。
今回作っている郵便受け開閉センサーでは、郵便受けが閉まっている時間の方が圧倒的に長い。
そのため、以下のように「普段はDeep Sleepで待機し、郵便受けが開いた時だけ起動する」構成にする。
普段 → Deep Sleep 開閉検知 ↓ 起動 ↓ Wi-Fi接続 ↓ Discord送信 ↓ Deep Sleep
これにより、常時起動する方式と比べてバッテリー消費をかなり抑えられる想定。
実装
Deep Sleepは以下のコードで実装できる。
const int reedPin = D2; void setup() { Serial.begin(115200); delay(3000); pinMode(reedPin, INPUT_PULLUP); // Deep Sleepから起床した理由を取得 esp_sleep_wakeup_cause_t wakeupReason = esp_sleep_get_wakeup_cause(); if (wakeupReason == ESP_SLEEP_WAKEUP_GPIO) { connectWiFi(); sendDiscordMessage("📬 郵便受けが開きました"); } // Deep Sleepから起床する条件を設定 esp_deep_sleep_enable_gpio_wakeup( 1ULL << GPIO_NUM_4, ESP_GPIO_WAKEUP_GPIO_HIGH); gpio_pullup_en(GPIO_NUM_4); gpio_hold_en(GPIO_NUM_4); gpio_deep_sleep_hold_en(); // Deep Sleep開始 esp_deep_sleep_start(); } void loop() { }
loopは空にする
Deep Sleepを使う場合は、前回のように loop() で常時監視する必要がない。
void loop() { }
起動後に必要な処理を実行し、最後に esp_deep_sleep_start() でDeep Sleepへ移行する。
そのため、loop() は空で問題ない。
起床理由を取得する
以下のコードで、ESP32C3がDeep Sleepから起床した理由を取得できる。
esp_sleep_wakeup_cause_t wakeupReason =
esp_sleep_get_wakeup_cause();
今回の実装では、GPIOによって起床した場合のみDiscord通知を送信する。
if (wakeupReason == ESP_SLEEP_WAKEUP_GPIO) { connectWiFi(); sendDiscordMessage("📬 郵便受けが開きました"); }
これにより、初回起動時には通知せず、郵便受けが開いたタイミングでDeep Sleepから起床した場合だけ通知できる。
Deep Sleepから起床する条件を設定する
Deep Sleepから起床する条件は esp_deep_sleep_enable_gpio_wakeup で設定する。
esp_deep_sleep_enable_gpio_wakeup( 1ULL << GPIO_NUM_4, ESP_GPIO_WAKEUP_GPIO_HIGH);
第一引数の 1ULL << GPIO_NUM_4 は、起床トリガーに使うピンを指定している。
今回はXIAO ESP32C3のD2ピンを使用しており、D2はGPIO4に対応しているため GPIO_NUM_4 を指定している。
第二引数の ESP_GPIO_WAKEUP_GPIO_HIGH は、GPIO4が HIGH になったらDeep Sleepから起床するという意味。
今回のリードスイッチの配線では、以下のような状態になる。
磁石あり ↓ LOW 磁石なし ↓ HIGH
つまり、郵便受けが開いて磁石がリードスイッチから離れるとGPIO4がHIGHになり、ESP32C3がDeep Sleepから起床する。
郵便受けが開く ↓ 磁石が離れる ↓ GPIO4がHIGHになる ↓ Deep Sleepから起床 ↓ Discord通知
内部プルアップ設定を保持する
以下のコードは、Deep Sleep中も内部プルアップの設定を保持するために記載している。
gpio_pullup_en(GPIO_NUM_4); gpio_hold_en(GPIO_NUM_4); gpio_deep_sleep_hold_en();
今回の検証ではこの設定で動作しているが、実運用では外付けの 10kΩ プルアップ抵抗 を付ける方が安定しそう。
外付け抵抗を使う場合、この内部プルアップ保持のコードは不要になる想定。
動作確認
上記の実装により、以下の流れで動作するようになった。
郵便受けが閉まっている ↓ ESP32C3はDeep Sleep状態 ↓ 郵便受けが開く ↓ リードスイッチから磁石が離れる ↓ GPIO4がHIGHになる ↓ ESP32C3が起床 ↓ Wi-Fi接続 ↓ Discord通知 ↓ 再びDeep Sleepへ移行
これで郵便受けが閉まっている間はDeep Sleepで待機し、開いた時だけ起動してDiscord通知を送信できるようになった。
まとめ
- ESP32C3のDeep Sleepを使うことで、常時起動を避けられる
esp_deep_sleep_enable_gpio_wakeupを使うとGPIOの状態変化で起床できる- 今回はD2(GPIO4)がHIGHになった時に起床するように設定
- 郵便受けが閉まっている間はDeep Sleep、開いた時だけ通知する構成にできた
