先日、ESP32のディープスリープ時間の上限について調査しました(記事は こちら)。
「esp_sleep_enable_timer_wakeup()」でスリープ時間を指定するのですが、このスリープ時間を「32ビット符号なし整数」で指定してしまうと、スリープ時間の最大値が約71.5分になってしまうというものです。
スリープ時間を明示的に「64ビット符号なし整数」で指定することで、より長いスリープ時間を設定できることを確認しました。
さて、この調査の目的はそもそも、「Timer Camera」で1日に1回、毎朝8時に写真を撮りたいというものでした。
「esp_sleep_enable_timer_wakeup()」の引数に、「64ビット符号なし整数」で「24時間」と設定することで、USBで電源供給している際には所望のとおり写真撮影できるようになりました。
ところが、USBケーブルを外し、Timer Cameraを内蔵バッテリーで動かしたところ、写真が撮影できなくなってしまいました。
Timer Cameraを内蔵バッテリーで動かす場合、スリープ中はESP32は完全にオフになり、復帰時間はRTC(BM8563)で制御されます。
また、BM8563のスリープ時間は「bmm8563_setTimerIRQ()」で指定します。
つまり、Timer Cameraのスリープ時間設定には、USBで給電しているときのための「esp_sleep_enable_timer_wakeup()」と、内蔵バッテリーで動かしているときのための「bmm8563_setTimerIRQ()」のふたつがあるということです。
Timer Cameraを内蔵バッテリーで動かすと正常に復帰しないことから、「bmm8563_setTimerIRQ()」にもスリープ時間の上限があるのではないか?と考えました。
ライブラリを確認してみました。
「bmm8563_setTimerIRQ()」の引数(単位:秒)は「16ビット符号あり整数」となっていました。「16ビット符号あり整数」の最大値は「32767」なので、約9.1時間までしか設定できないことになります。
また、ライブラリのコメントに「max time is 255 * 60」と書かれていました。実際の最大値は「4.25時間」のようです。
よって、今回のように、1日に1回だけ処理を行いたいような場合でも、スリープ時間を「1日」などの大きな値にすることはできず、「4.25時間」以内に復帰して、所望の時間のときのみ処理を行うような、何らかの工夫が必要なようです。
今回は以下のような処理を行うことで対処しました。
- スリープモードから復帰する。
- インターネットに接続して現在時刻を取得する。
- 現在時刻が「午前8時(±10分)」であれば写真を撮影する。
- 変数「interval」を「現在時刻から午前8時までの時間」にする。
- 設定した「interval」が「4.25時間」より大きければ、「interval」を「4.25時間」に変更する。
- bmm8563_setTimerIRQ()の引数を「interval」にする(単位:秒)。
- スリープモードに移行する。
1日1回の間隔で写真撮影したいという、ごく単純な目的だったですが、処理内容は結構煩雑になってしまいました。