ということで WiFi も接続できたので次は NTP へ。
この NTP 機能、 ntpdate みたいな実行するとその場で一回限りの時刻同期をするものなのかと思ったけれども、実際には一度動かすとバックグラウンドで動いて毎時同期するものらしい。
バッテリーのことを考慮して毎時都度 WiFi 接続して NTP で時刻同期することを考えていたのだけれど、それをやると逆に面倒くさそう。
あと、いろんな資料を見ると、
* WiFi の接続成功をポーリングで待つ
* NTP の処理を始めたらあとはほったらかし
という実装が主なのだけれど、M5Paper の時計への設定処理は自前でやらないといけないこともあって、いちいちポーリングをしないといけなくて面倒くさい。
ということで、最終的に以下の実装に:
* WiFi.onEvent でコールバックを登録して、WiFi 接続完了を検知。
* WiFi 接続完了を検知したら、NTP を開始。
* sntp_set_time_sync_notification_cb で、 NTP の同期完了イベントを受け付けるコールバックを登録。
* 同期完了イベントを受け取ったら時刻を設定。
* イケダム時計は裏で行われているそういう処理のことは気にせず勝手に動く。
NTP の利用は多くの資料で configTime() を使うということになっているのだけれど、それとは別に低水準の API sntp_xxxx のシリーズがあるようで、どうもさらにその sntp_xxxx も二系統あるように見えて(ヘッダファイルが別)、どうにもよくわからない。
が、とりあえず上記でなんとなく動いた。
なお、当初 sntp_set_time_sync_notification_cb で登録して呼び出されたコールバックから直接 M5.RTC.setTime() 等を呼び出していたのだけれども、どうもちゃんと時刻が設定できない問題があった。
どうやら loop() 側でも M5.RTC.getTime() を呼んでいたので、それとかち合ったみたい。
loop 以外で時計にアクセスするとやばい、ということだと思うので、コールバック側では呼び出し時点の millis() を記録して、 loop() 側で millis() の差分を補正しつつ時刻を設定する、という対処とした。
ちなみに M5Paper には時計用の RTC チップというのが積んであってそれを使っているのだけれども、どうも ESP32 自体にも時計がついているみたいでそっちは NTP で自動設定されるみたいなので、M5Paper の RTC チップは実は使わなくてもよいのかもしれない。
ということで WiFi と NTP に対応したイケダム時計。
https://github.com/ikedam/m5paper-ikedamclock/tree/v0.2.0