ESP32 と電子ペーパーで気象庁の天気図を表示する

ESP32 と電子ペーパーで気象庁の天気図を表示する

7.5インチの電子ペーパーに気象庁の実況天気図を表示し、壁に掛けておける小さな表示システムです。表示内容は電源を切っても残るので、ESP32 は決まった時刻だけ起きて Wi-Fi に接続し、天気図を更新したらまた deep sleep に戻ります。

完成した表面。壁に掛けた 7.5 インチ電子ペーパーに天気図が表示されている
完成した表面。壁に掛けた 7.5 インチ電子ペーパーに天気図が表示されている

リポジトリは 、ケースの3Dプリント用データも含めてGitHub で公開しています。

何をするシステムか

表示しているのは、気象庁の日本周辺域の実況天気図です。ESP32 側で画像処理をがんばるのではなく、Linux などで動かすリレーサーバが気象庁の画像を取得し、7.5インチ電子ペーパーにそのまま送れるサイズと形式に変換します。ESP32 は起床後にリレーサーバから manifest とバイナリ画像を取って、SPI で電子ペーパーに転送します。

現在の標準構成では、Waveshare の 7.5inch e-Paper 黒白 raw panel、800x480、4階調表示を使っています。リレーサーバは 800x480 の 2bpp gray4、96000 bytes のペイロードを返します。濃い等圧線や前線は黒に寄せつつ、薄い地図線やアンチエイリアスは中間グレーとして残すようにしています。

更新時刻は JST の 00:00、03:00、06:00、09:00、12:00、15:00、18:00、21:00 です。気象庁の天気図は観測時刻から少し遅れて公開されるので、このタイミングで起こすと直近の公開済み天気図を拾えます。Wi-Fi やリレー取得に失敗した場合は短い間隔で再試行し、MQTT に状態イベントも送ります。

使った部材

主な部材は以下です。

Waveshare の ESP32 Driver Board は、電子ペーパー向けの SPI 配線が固定されているため、一般的な ESP32 開発ボードとジャンパ線で組むより扱いやすいです。使用しているピンは DIN/MOSI=GPIO14、SCLK=GPIO13、CS=GPIO15、DC=GPIO27、RST=GPIO26、BUSY=GPIO25 です。このボードでは、USBシリアルへの電源共有もDIPスイッチで制御できるので、プログラム書き込み時にはONにしておき、運用時はOFFにすることでさらにバッテリー消費を低く抑えることができます。

バッテリーには cheero Canvas の IoT 向けモデルを使いました。微小電流でも給電を続けられるタイプなので、deep sleep を使う ESP32 と相性がよいです。ただし、このモデルの USB-C は入力専用なので、ESP32 Driver Board への給電は USB-A から USB-C への短いケーブルで行います。

ケースと組み立て

ケースは OpenSCAD で作りました。リポジトリには cad/waveshare_7in5b_esp32_case.scad と、出力済みの STL を入れています。

電子ペーパー取り付け前。背面ケースに ESP32 Driver Board とバッテリーを収め、短い USB ケーブルで接続している
電子ペーパー取り付け前。背面ケースに ESP32 Driver Board とバッテリーを収め、短い USB ケーブルで接続している

組み立ては次の順番が楽でした。

  1. frontback_battery を 3D プリントする。
  2. 背面ケースに ESP32 Driver Board を置き、USB-C コネクタとケーブルの逃げを確認する。
  3. cheero バッテリーを背面ポケットに入れ、短い USB-A to USB-C ケーブルで ESP32 Driver Board に給電する。
  4. 電子ペーパーの FPC を無理に折らないように Driver Board 側へ通す。
  5. 表示面を前面ベゼルから見える向きに合わせ、四隅を短い M2 ねじで固定する。
  6. 背面のキーホールを使って壁の押しピンに掛ける。

電子ペーパーの raw panel は薄く割れやすいので、表示エリアの上から力をかけないことが重要です。必要なら表示領域の外側だけに薄いフォームテープを貼って、ケース内で暴れないようにします。

背面はこのようになっています。バッテリーを取り出せるように背面窓を設けました。

完成した背面。ケース背面の窓から cheero バッテリーにアクセスできる
完成した背面。ケース背面の窓から cheero バッテリーにアクセスできる

ファームウェアのビルド

ファームウェアは Arduino framework + PlatformIO です。通常使う環境は waveshare_esp32_epd で、現在はこれが default env になっています。

git clone https://github.com/mokjpn/waveshare-esp32-weather-epaper.git
cd waveshare-esp32-weather-epaper
cp include/app_secrets.example.h include/app_secrets.h

include/app_secrets.h に Wi-Fi、リレーサーバ、ログ出力用のMQTT の設定を書きます。

ビルドは次の通りです。

PLATFORMIO_CORE_DIR=/tmp/pio-core pio run

アップロード例です。

PLATFORMIO_CORE_DIR=/tmp/pio-core pio run -e waveshare_esp32_epd -t upload --upload-port /dev/tty.usbmodemXXXX

表示確認用には waveshare_esp32_epd_diag も用意しています。まず診断用の縦縞パターンで電子ペーパーと SPI 経路が動くことを確認してから、通常ファームウェアを書き込むと切り分けが楽です。

リレーサーバの設置

ESP32 に画像取得、TLS、リサイズ、クロップ、4階調化を全部やらせると重いので、Python のリレーサーバで処理します。リレーサーバは気象庁の near_monochrome.now の PNG を取得し、800x480 にフィットさせて、電子ペーパー用の gray4 バイナリに変換します。

ローカルで動かす場合は次の通りです。

cd relay_server
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python3 weather_relay.py --bind 0.0.0.0 --port 8080

ESP32 側の APP_RELAY_BASE_URL には、ESP32 から見えるリレーサーバの URL を指定します。

サーバに常駐させる場合は systemd user service にするのが簡単です。例:

[Unit]
Description=Weather e-paper relay
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/lib/weather-epaper-relay
ExecStart=%h/lib/weather-epaper-relay/.venv/bin/python %h/lib/weather-epaper-relay/weather_relay.py --bind 0.0.0.0 --port 24840 --threshold 200 --output-format gray4 --access-log-file /tmp/epaperrelay-access.log
Restart=always
RestartSec=10

[Install]
WantedBy=default.target

有効化は次のようにします。

systemctl --user daemon-reload
systemctl --user enable --now epaperrelay.service
loginctl enable-linger $USER

動作確認は manifest と binary の両方を見ます。

curl http://127.0.0.1:24840/healthz
curl http://127.0.0.1:24840/api/weather-map/latest.json
curl -I http://127.0.0.1:24840/api/weather-map/latest.bin

標準構成なら manifest は width: 800height: 480format: gray4bytes: 96000 を返します。binary endpoint の Content-Length も 96000 bytes になっていれば、ファームウェア側と契約が合っています。

再現時の注意点

電子ペーパーの種類が似ていても、同じ 7.5 インチで解像度や色数が違うものがあります。このリポジトリの標準は black/white の 800x480、4階調対応パネルです。古い 1bpp 経路や 640x384 の 7.5inch e-Paper (B) 向け環境も残していますが、まずは標準の waveshare_esp32_epdgray4 の組み合わせで揃えるのが安全です。

また、ケースは手元の個体とプリンタに合わせた寸法です。特に FPC の逃げ、USB ケーブルの曲げ半径、バッテリーの保持、前面ベゼルの窓位置は、実部品で一度仮組みしてから調整する前提で見てください。

低消費電力化で一番効くのは、普段は deep sleep に落とし、更新時だけ Wi-Fi を使うことです。電子ペーパーは表示保持に電力を使わないので、天気図のように数時間に一度更新すればよい用途にはかなり向いています。