miyoshitan’s blog

岐阜発。自動車サービス現場とPython・Flask・Raspberry Pi・M5Stackの実践記録。

AI・IoT・個人開発の実験ログと考察をまとめる技術ブログ

Raspberry Pi 5とM5Stack CoreS3を活用した天気パネル制作

 

今回は Raspberry Pi 5 と M5Stack CoreS3 を使って、卓上の天気パネルを作ってみました。

デスクやガレージに置いておくと、今日と明日の天気が常に表示される小型ディスプレイです。

表示される内容はこんな感じ。

・今日 / 明日の天気
・最低気温 / 最高気温
・降水確率
・最大風速
・UV指数
・予報の取得時刻
・現在日時(RTC)

しかもこのデバイス、ラズパイを起動しておけば 10分ごとに自動更新されます。
systemdで常駐させているので、再起動しても自動復帰。
完全に 「置いておくだけの天気家電」 みたいな感じで使えています。


完成イメージ

画面には次のような情報が表示されます。

text
きょうの天気 2026/03/12 21:50 最低 3.1℃ / 最高 12.4℃ 降水確率 20% 風 4.2km/h UV 3.5 あしたの天気 2026/03/12 21:50 最低 4.0℃ / 最高 14.1℃ 降水確率 30% 風 5.0km/h UV 4.1

画面の下部には

text
2026/03/12 (木) 21:50

という 現在日時を表示。

予報には 取得時刻も含めているので、「この予報いつの?」がすぐ分かるようにしています。


なぜ作ったのか

天気はスマホでも見られますが、
デスクやガレージでパッと見られる表示が欲しいと思ったのがきっかけです。

市販のスマートディスプレイでも似たことはできますが、

・余計な情報が多い
・カスタマイズしづらい
・常時表示に向かない

という問題がありました。

そこで今回は

「天気だけ表示する専用デバイス」

を作ることにしました。


システム構成

今回のシステムはとてもシンプルです。

Raspberry Pi が データ取得担当
CoreS3 が 表示担当です。

Raspberry Pi

・Open‑Meteo API から天気取得
・日本語テキストに整形
・UARTで送信

M5Stack CoreS3

・UARTでデータ受信
・日本語フォントで表示
・RTCで現在時刻表示

接続は 3.3V UARTです。

CoreS3
RX = 18
TX = 17

Raspberry Pi
/dev/ttyAMA0

つまり

ラズパイ = サーバー
CoreS3 = 表示端末

という構成です。


Raspberry Pi 側の処理

ラズパイ側は Python + 仮想環境で構成しています。

プロジェクトディレクトリ

text
~/concierge

使用ライブラリ

・openmeteo-requests
・requests
・pyserial

スクリプトは役割ごとに分けました。

weather_simple.py
天気データ取得

weather_to_uart.py
UART送信(単発)

weather_loop.py
10分ごとの更新ループ


天気データの取得

天気は Open‑Meteo API を使用しています。

取得地点

現在地周辺

緯度
12.3456

経度
789.1011

取得項目

・最高気温
・最低気温
・降水確率
・最大風速
・UV指数

APIでは

text
forecast_days = 2

を指定して 今日と明日の2日分を取得。

取得時刻は

text
datetime.now().strftime("%Y/%m/%d %H:%M")

で生成しています。


systemdで自動更新

ラズパイ起動後に自動で動くように systemdサービス化しました。

更新間隔

text
10分

処理内容

天気取得

UART送信

sleep

これをループします。

仮想環境を使っているので、
ラッパーシェルを挟む構成にしています。

text
run_weather_loop.sh
text
cd ~/concierge source .venv/bin/activate python weather_loop.py

これを systemd から実行します。


CoreS3 側の実装

CoreS3 は Arduino IDE + M5Unified + M5GFXで作りました。

ボード設定

text
M5STACK_CORES3

日本語フォント

使用フォント

text
fonts::lgfxJapanGothic_20

setTextSize(1)のままでも十分読みやすいサイズです。

TextSize=2にすると画面に入りきらないので、
フォントサイズを大きくする方がレイアウトしやすいと感じました。


UART受信

CoreS3では UART2 を使用します。

text
RX = 18 TX = 17 115200bps

受信データは String バッファに貯めて、

200msほど通信が止まったら1回分のデータと判断

して画面を更新します。


RTCの現在時刻表示

画面下部には 現在日時を表示しています。

RTC取得

text
M5.Rtc.getDateTime()

表示フォーマット

text
YYYY/MM/DD (曜) HH:MM

曜日

text
日 月 火 水 木 金 土

フッターだけ

text
fillRect()

で更新しているので、
天気パネルは再描画されません。


RTCの時刻合わせ

RTCは 最初に一度だけNTP同期しました。

別スケッチで

Wi‑Fi接続

NTP取得

RTC書き込み

を実行。

text
configTzTime("JST-9", "ntp.nict.jp")

取得した時刻を

text
m5::rtc_datetime_t

に変換して

text
M5.Rtc.setDateTime()

でRTCに保存します。



実際の使い勝手

ラズパイを起動すると

systemdが weather_loop を起動

10分ごとに天気取得

CoreS3に送信

CoreS3の画面には

・今日の天気
・明日の天気
・気温 / 降水確率 / 風 / UV
・予報取得時刻
・現在日時

が表示されます。

systemdのおかげで 再起動しても自動復帰します。

結果として、
完全に「置きっぱなしの天気パネル」になりました。


ハマりポイント

いくつか小さい落とし穴もありました。

フォントサイズ
TextSize=2だと大きすぎる

RTC型
rtc_datetime_tではなく
m5::rtc_datetime_t

systemd + 仮想環境
ラッパーシェルを作ると楽

手動更新

text
python weather_to_uart.py