第 09 章「組み込みを作る ── Pythonで考え、Claudeに翻訳させる」の 2 番目の角度: 実機の前段(データ可視化と異常検知)を Python で完成させる。
章のどの主張に対応するか
センサデータの可視化: 自前で Web ダッシュボードを作ると 1 週間。 Python の
matplotlibでplot()1 行 + Claude に「これを HTML レポートにして」と 頼むと 30 分で実用レベル。
(章本文「実例: 数字で見る」より)
example-1 が「温度制御ロジックの C 翻訳」、これは データ収集 → 可視化 → 判定 → レポート までの周辺パイプラインを実演する。
やること
collect.py: 1 週間ぶん(7×24×12 = 2,016 件 × 3 センサ = 6,048 件)を SQLite に投入(実機がまだ無くても、データの形を決めて先にコードを書く)analyze.py: SQL で集計 + matplotlib で 3 段グラフ + 自動観察コメント- 出力:
out/sensor.db── 生データout/sensor.png── 温度・湿度・土壌水分の推移グラフ(日本語タイトル)out/report.md── 統計表 + 観察コメントの Markdown
構成
example-2/
├── README.md
├── collect.py ── 模擬センサーから SQLite へ 6,048 件
├── analyze.py ── SQL 集計 + matplotlib グラフ + Markdown
├── Makefile
├── results.md
└── out/
├── sensor.db ── SQLite(約 220 KB)
├── sensor.png ── 3 段グラフ(温度/湿度/土壌)
└── report.md ── 自動観察コメント付き
実行
pip install matplotlib
sudo apt install fonts-noto-cjk
make clean && make all
数秒で 6,048 件投入 + グラフ + レポートが完成。
なぜこれが「実例」になるのか
組み込み開発で詰まりやすい順:
- ハードを買う(数日〜数週間、調達待ち)
- 配線・はんだ付け(物理作業)
- ファーム書き込み(実機ループの遅さ ── 章 example-1 の主題)
- データを集める(動き始めたが、見方がわからない)
- 可視化(ここで詰まる)
このフォルダが (4) と (5) を実機抜きで完成させる:
- スキーマ(
measurements (sensor, value, unit, ts))を Python で先に固定 - 集計クエリ(min / avg / max / 1 時間平均)を先に書ける
- グラフのレイアウトも先に決まる
- 実機を繋いだ瞬間、
INSERTを 1 行送るだけ
これは章 09 の主軸 ── 「Python で全部完成 → 実機側は最後の一行だけ」 の 周辺パイプライン版。
自動観察コメント
analyze.py の最後にあるルール:
if t["max"] - t["min"] > 8:
md.append(f"- 温度の日内変動が **{t['max']-t['min']:.1f}℃** ── 大きい。")
if sm["max"] - sm["min"] > 5:
md.append(f"- 土壌水分が低下 ── 灌水が必要。")
数値しきい値で「気づき」を Markdown に出す。これは エージェントを呼ばずに 判断ができる例 ── 章 10「コードに凍結する」と一致する。 基準が変わったら if 文を書き換えるだけ。
計測結果 — 第 09 章 example-2
実行環境: Linux 6.18 / Python 3.11 / matplotlib 3.x / SQLite 3.45 / Noto Sans CJK JP
データ投入
=== センサーデータ投入 ===
期間 : 2026-04-25 〜 2026-05-01 (7 日)
サンプリング : 5 分間隔 × 3 センサ
投入件数 : 6,048 件 (DB: 220 KB)
投入時間 : 約 30 ms
| センサ | 件数 |
|---|---|
| temperature | 2,016 |
| humidity | 2,016 |
| soil_moisture | 2,016 |
集計結果(out/report.md より)
| センサ | 最小 | 平均 | 最大 |
|---|---|---|---|
| temperature (°C) | 10.9 | 20.0 | 29.3 |
| humidity (%) | 38.4 | 69.9 | 100.0 |
| soil_moisture (%) | 21.3 | 30.0 | 39.6 |
グラフ(out/sensor.png)
3 段表示で温度・湿度・土壌水分の 1 週間ぶん:
- 薄い線: 5 分間隔の生データ(2,016 点)
- 濃い線: 1 時間平均(SQL の
GROUP BY strftime)
日内サイクル(温度: 朝低い → 昼高い)が見える。土壌水分はじわっと 低下していて、最終日に灌水が必要。
SQL クエリの例
-- 1 時間ごとの温度平均
SELECT strftime('%Y-%m-%d %H:00', ts) AS hour, AVG(value)
FROM measurements
WHERE sensor = 'temperature'
GROUP BY hour
ORDER BY hour;
これだけで 2,016 点 → 168 点 に集約。グラフの「重なって読めない」を 解消する。
自動観察コメント(out/report.md の末尾)
## 観察(自動)
- 温度の日内変動が **18.4℃** ── 大きい。換気またはシェード検討。
- 土壌水分が **39.6% → 21.3%** に低下 ── 灌水が必要。
これは エージェントを呼ばずに 判断ができる典型例。閾値で気づきを 出す。閾値はコードに 3 行。
エージェントに「このデータをどう思う?」と毎回聞くと、
- 1 回約 $0.05(コンテキスト 6,000 行を渡す)
- 365 日で $18
このスクリプトは:
- 1 回 $0(LLM を呼ばない)
- 365 日で $0
コードに凍結できるものはエージェントに任せない(章 10 と一致)。
来月の運用
cron に登録:
*/5 * * * * curl http://esp32.local/sensor | python3 ingest.py # 実機収集(別途)
0 7 * * 1 cd /home/me/greenhouse && make analyze # 毎週月曜 7:00 に集計
毎週月曜の朝、out/report.md と out/sensor.png が更新される。それを
LINE に投げれば「気づき通知」も自動。
章本文との対応
1 週間 → 30 分 (matplotlib + Claude)
このフォルダは:
- データ収集パイプライン: 30 行
- グラフ作成: 50 行
- Markdown レポート: 30 行
- 合計: 約 110 行
実プロジェクトでも、ここから 50 行追加すれば Slack 通知 / メール送信 / HTML ダッシュボードに発展できる。
再現手順
pip install matplotlib
sudo apt install fonts-noto-cjk
make clean && make all