今回は Raspberry Pi 5 と M5Stack CoreS3 を使って、卓上の天気パネルを作ってみました。
デスクやガレージに置いておくと、今日と明日の天気が常に表示される小型ディスプレイです。
表示される内容はこんな感じ。
・今日 / 明日の天気
・最低気温 / 最高気温
・降水確率
・最大風速
・UV指数
・予報の取得時刻
・現在日時(RTC)
しかもこのデバイス、ラズパイを起動しておけば 10分ごとに自動更新されます。
systemdで常駐させているので、再起動しても自動復帰。
完全に 「置いておくだけの天気家電」 みたいな感じで使えています。

完成イメージ
画面には次のような情報が表示されます。
きょうの天気 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
画面の下部には
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 + 仮想環境で構成しています。
プロジェクトディレクトリ
~/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では
forecast_days = 2
を指定して 今日と明日の2日分を取得。
取得時刻は
datetime.now().strftime("%Y/%m/%d %H:%M")
で生成しています。
systemdで自動更新
ラズパイ起動後に自動で動くように systemdサービス化しました。
更新間隔
10分
処理内容
天気取得
↓
UART送信
↓
sleep
これをループします。
仮想環境を使っているので、
ラッパーシェルを挟む構成にしています。
run_weather_loop.sh
cd ~/concierge
source .venv/bin/activate
python weather_loop.py
これを systemd から実行します。
CoreS3 側の実装
CoreS3 は Arduino IDE + M5Unified + M5GFXで作りました。
ボード設定
M5STACK_CORES3
日本語フォント
使用フォント
fonts::lgfxJapanGothic_20
setTextSize(1)のままでも十分読みやすいサイズです。
TextSize=2にすると画面に入りきらないので、
フォントサイズを大きくする方がレイアウトしやすいと感じました。
UART受信
CoreS3では UART2 を使用します。
RX = 18
TX = 17
115200bps
受信データは String バッファに貯めて、
200msほど通信が止まったら1回分のデータと判断
して画面を更新します。
RTCの現在時刻表示
画面下部には 現在日時を表示しています。
RTC取得
M5.Rtc.getDateTime()
表示フォーマット
YYYY/MM/DD (曜) HH:MM
曜日
日 月 火 水 木 金 土
フッターだけ
fillRect()
で更新しているので、
天気パネルは再描画されません。
RTCの時刻合わせ
RTCは 最初に一度だけNTP同期しました。
別スケッチで
Wi‑Fi接続
↓
NTP取得
↓
RTC書き込み
を実行。
configTzTime("JST-9", "ntp.nict.jp")
取得した時刻を
m5::rtc_datetime_t
に変換して
M5.Rtc.setDateTime()
でRTCに保存します。


実際の使い勝手
ラズパイを起動すると
systemdが weather_loop を起動
↓
10分ごとに天気取得
↓
CoreS3に送信
CoreS3の画面には
・今日の天気
・明日の天気
・気温 / 降水確率 / 風 / UV
・予報取得時刻
・現在日時
が表示されます。
systemdのおかげで 再起動しても自動復帰します。
結果として、
完全に「置きっぱなしの天気パネル」になりました。
ハマりポイント
いくつか小さい落とし穴もありました。
フォントサイズ
TextSize=2だと大きすぎる
RTC型rtc_datetime_tではなくm5::rtc_datetime_t
systemd + 仮想環境
ラッパーシェルを作ると楽
手動更新
python weather_to_uart.py