M5PaperS3で、充電を忘れられる週間天気表示を作った
毎朝、天気予報を見るためだけにスマートフォンを開くのが少し面倒でした。知りたいのは、今日とこの先数日の気温、雨の可能性、傘が必要そうかどうかです。そこで、M5Paper / M5PaperS3 の電子ペーパー画面を使って、壁に掛けっぱなしにできる週間天気表示システムを作りました。
いまは M5PaperS3 で運用していて、数週間単位で充電せずに動いています。壁への取り付けには、別途公開している M5PaperS3WallMountを使っています。電子ペーパーなので表示が紙のように落ち着いていて、普段の生活空間に置いても違和感が少ないのが気に入っています。
ソースコードはこちらです。
何を表示しているか
表示しているのは OpenWeather の One Call API から取得した 7 日分の予報です。
- 天気アイコン
- 最高気温、最低気温
- 降水確率
- 降水量
- 更新時刻
- NTP 同期状態
- バッテリー残量と電圧
画面は横向きに使い、上部に天気アイコンと気温の折れ線、下部に降水確率と降水量のバーを置いています。スマートフォンの天気アプリほど細かい情報は載せず、朝に一目で判断できる情報だけに絞りました。
更新間隔は include/secrets.h の UPDATE_INTERVAL_SECONDS で指定します。私の環境では 6 時間ごとの更新で十分でした。更新時だけ Wi-Fi に接続し、天気データと NTP 時刻を取得し、描画したら Wi-Fi を切ってスリープに入ります。
構成
開発環境は PlatformIO + Arduino framework です。ライブラリは主に M5Unified と ArduinoJson を使っています。
platformio.ini には、M5Paper と M5PaperS3 の両方の環境を用意しました。
m5paperm5paper-lightsleepPaperS3
M5Paper は PlatformIO に専用 board 定義がないため、ESP32 + PSRAM が使える m5stack-fire をベースにしています。M5PaperS3 は esp32-s3-devkitm-1 を使い、PSRAM や USB CDC まわりの build flag を追加しています。
天気アイコンは data/icons/ に PNG を置く方式です。リポジトリにはアイコン画像そのものは含めず、data/icons/README.mdに必要なファイル名だけを記録しています。第三者素材をそのまま再配布しないためです。PNG がない場合でも、コード内の簡易ベクター描画にフォールバックするようにしてあります。
Codexを使った開発がかなりうまくいった
今回の開発では Codex が非常に役に立ちました。特によかったのは、組み込み機器の細かい試行錯誤を、コードとログを見ながら小さく前進させられたことです。
最初に欲しかったのは「電子ペーパーに天気を表示して、しばらく寝る」だけでした。しかし実際に動かすと、すぐに細かい課題が出てきます。
- M5Paper と M5PaperS3 で初期化や電源管理の挙動が違う
- Deep Sleep から期待通りに起きない個体や構成がある
- Wi-Fi 起動後にバッテリー電圧の読み取りが不安定になる
- 日本語フォント、曜日表示、ラベル位置の調整が必要
- OpenWeather API の JSON が大きく、メモリ確保に余裕が必要
- PaperS3 の Arduino-ESP32 3.0.5 では
HTTPClientの HTTPSbegin()が通らない構成がある
こうした問題は、ひとつひとつは小さいのですが、手で調べながら直すとかなり時間を使います。Codex には、実装を読ませて、ビルド設定やコードコメント、エラー時の表示、スリープの分岐を少しずつ整理してもらいました。
特に助かったのは、M5Paper では通常 Deep Sleep を使い、必要な場合だけ PAPER_FORCE_LIGHTSLEEP で Light Sleep に切り替える構成にしたところです。Light Sleep から戻った後は ESP.restart() して、アプリ全体を setup()から再実行する形にしています。これにより、通常動作のコードパスを単純に保てました。
また、失敗時の扱いも実用上は重要でした。Wi-Fi 接続や天気取得に失敗した場合、通常の 6 時間待ちではなく 10 分後に再試行するようにしています。画面にもエラー内容と再試行予定を表示するので、設置後に何が起きているか分かります。
難しかった点
一番難しかったのは、低消費電力動作と復帰の安定性です。電子ペーパー表示は、画面を書き換えない限り電力をほとんど使わないので、天気表示には非常に向いています。一方で、実用的に「壁に掛けっぱなし」にするには、Wi-Fi、RTC、バッテリー読み取り、スリープ復帰の順序をかなり気にする必要がありました。
現在の実装では、起動直後にバッテリー情報を読み、次に Wi-Fi 接続と NTP 同期を行い、OpenWeather から予報を取得し、画面描画後に Wi-Fi を切ってスリープします。バッテリー残量が API から取れない場合は、電圧から簡易推定します。
もうひとつの難所は HTTPS でした。PaperS3 の一部構成では HTTPClient が HTTPS の begin()を受け付けないため、現時点では OpenWeather API への接続を http:// にしています。これは README にも注意事項として書いてあります。家庭内の壁掛け天気表示としては許容していますが、将来的には Arduino-ESP32 側の更新や証明書処理を見直して HTTPS に戻したいところです。
使い方
使うには、まずリポジトリを取得します。
git clone https://github.com/mokjpn/M5PaperWeatherU.git
cd M5PaperWeatherU次に include/secrets.h-exampleを参考にして、include/secrets.h を作成します。
設定するのは以下です。
- Wi-Fi SSID
- Wi-Fi パスワード
- OpenWeather API キー
- 緯度、経度
- 表示用の都市名
- 更新間隔
天気アイコンを使う場合は、data/icons/README.mdに書かれている名前で PNG を用意し、PlatformIO の uploadfsで LittleFS に書き込みます。
M5PaperS3 に書き込む場合は、PlatformIO の環境として PaperS3 を選びます。M5Paper の場合は m5paper、Deep Sleep 復帰に問題がある個体では m5paper-lightsleep を試せるようにしてあります。
しばらく運用してみて
M5PaperS3 での運用はかなり良好です。更新頻度を数時間おきにすれば、画面は常時見えているのに、消費電力はかなり低く抑えられます。スマートフォンやスマートディスプレイと違って、通知も光も音もなく、ただ天気だけがそこにあるのがよいです。
壁マウントと組み合わせると、実験基板っぽさがかなり減ります。M5PaperS3WallMount は 3D プリント前提の簡単なマウントですが、壁に固定してしまうと「家電」らしい見た目になります。
今回のような小さな実用品は、Codex との相性がかなりよいと感じました。最初から完璧な設計を考えるより、動かして、ログを見て、気になるところを直していく。その反復を速く回せるのが大きいです。結果として、日常的に使えるものになりました。
リポジトリはこちらです。