知的好奇心 for IoT
ある日、XにSipeed社の超軽量AIアシスタント"PicoClaw"のポストが流れてきて、どういうものなのかを調べていたら、なぜか自分のMacにCursorやAntigravityなどのAIコーディングツールをインストールしていて、GoogleのNotebookMLも使い出していました。
そこで今回は、NotebookMLの使い方のテストとして、IoT電光掲示板の機能アップを題材としたブログを書かせてみることにしました。
- プロンプト
- ソース
- ここから、NotebookLMに作ってもらった文面とスライドです。
- 1. IoT電光掲示板の概要
- 使用している主なパーツ
- 2. なぜ機能を追加したか
- 3. 追加した機能の説明(天気予報APIの仕組み)
- データの構造
- 4. 実装のポイント(コード解説)
- 以前のコード(天気のみ)
- 新しいコード(気温を追加+nullチェック)
- 工夫した点:Nullデータの回避
- 5. 実際の表示例
- まとめ
- 1. IoT電光掲示板の概要
NotebookLMに入力したプロンプトは、Grokに相談しながら作りました。
ソースを元に以下の指示に従った、技術ブログ記事を書いてください。 - タイトル:「天気と電車の運行情報を表示するIoT電光掲示板」の表示に最低気温と最高気温を追加しました! - ターゲット:IoT初心者〜中級者、Arduino/ESP32に興味がある人 - トーン:親しみやすく、丁寧で実践的。自分の言葉で「やってみた」感を出す - 構成:IoT電光掲示板の概要 → なぜ追加したか → 追加した機能の説明 → 実装のポイント(コード抜粋) → 実際の表示例 → まとめ - IoT電光掲示板の概要では、プロジェクトの目的や使用しているハードウェア・ソフトウェアを簡単に説明し、仕組みのスライドを付けます。 - なぜ追加したかでは、受講者された方が最低気温と最高気温を表示する改良をされたが、うまく動作しなかったことがきっかけとなっています。 - 追加した機能の説明では、天気予報APIのデータ構造から最低気温と最高気温を表示するためにどのように追加したかを説明します。スライドを付けます。 - 実装のポイントでは、コードの抜粋を交えて、データにnullがある場合の対処を考慮した実装を説明します。コードブロックを活用します。 - 実際の表示例では、追加した機能がどのように表示されるかをスクリーンショットや動画で紹介します。 - まとめでは、今回の改良で得られた成果や今後の展望について簡潔にまとめます。 - WetherTrainOld.txtが元のコードで、WetherTrainNew.txtが新しいコードです。(拡張子をtxtに変更しています。) - 文字数目安:1500〜2500字 - Markdown形式で、見出し・箇条書き・コードブロックを活用 - 講座URLを自然に複数回入れる ソースNotebookMLのソース(参照データ)に指定したものは次です。
- 天気と電車の運行情報を表示する、文字が流れる電光掲示板を作ろう!の講座ページのURL
- 天気予報API(livedoor 天気互換)のURL
- LEDマトリックスライブラリのURL
- Arduino用美咲フォントライブラリのURL
- ATOM Liteのメーカー説明WikiのURL
- 変更前のソースコード全文
- 変更後のソースコード全文
本当に、これだけの情報しか与えていないのですが、以下の文章とスライドを作成してくれるんです。
ここから、NotebookLMに作ってもらった文面とスライドです。※赤字は私のコメントです。
皆さん、こんにちは!IoT電子工作を楽しんでいますか? 普段、私がストアカで開催している講座「天気と電車の運行情報を表示する、文字が流れる電光掲示板を作ろう!」では、M5Stackの「ATOM Lite」を使って、日常生活に便利な情報を表示するデバイスを作っています。
今回は、受講者様からの熱いリクエストにお応えして、これまでの「天気」と「運行情報」に加えて、「最低気温」と「最高気温」を表示できるようにアップデートしました!「今日、コートが必要かな?」と迷った時に、パッと見て判断できるので、さらに実用的になっています。
1. IoT電光掲示板の概要
このプロジェクトは、インターネットからリアルタイムに情報を取得し、LEDマトリックスに日本語で表示するものです。
使用している主なパーツ- コントローラー: ATOM Lite (ESP32-PICO-D4搭載)。非常にコンパクトながらWi-Fi機能を備えた強力なマイコンです。
- ディスプレイ: 4連8x8ドットLEDマトリックス (MAX7219)。文字を滑らかにスクロールさせることができます。
- フォント: 美咲フォントライブラリ。8x8ドットという限られたスペースで、美しい日本語(教育漢字など)を表示するために欠かせません。
仕組みとしては、ATOM LiteがWi-Fi経由で天気予報APIや運行情報にアクセスし、取得したデータを解析してLEDに送り出しています。
まずは、このプロジェクト全体の仕組みを理解するためのスライドを作成しました。
※これはかなり盛られたスライドです。実物は漢字4文字表示で縦が8ドットしかないため、細かい漢字は潰れて表示されます。
※ATOM Liteにモジュラージャックっぽいものが付いていたり、ケーブルが生えていたりしていますが、ご愛嬌ですね。
※配線の物理的な位置や、LEDマトリックスモジュールの形が実際とは違っていますが、ソースコードからGPIOの番号や信号線の名前を拾って作成しているようです。
※見方がいろいろありますが、概ねOKだと思います。
※「weather.tsukumijima.net」は天気予報APIの説明ページです。
※ソースコードを読み取って、このスライドを作るのには驚きました。
※LEDマトリックスは8ドットで合っているのに、表示されている漢字が16ドットになっているのが惜しいです。
※このスライドの書き方だと「Scroll Delay:50ms」はミスリードを誘う感じです。この値は文字の縦1列を表示後に待つ時間で、短くすると横スクロールが速くなります。
2. なぜ機能を追加したか
今回のアップデートのきっかけは、講座を受講された方からの「気温も表示してみたい!」というチャレンジでした。
その方は、ご自身でコードを書き換えて最低気温と最高気温の取得に挑戦されましたが、「特定の時間になるとエラーが出てうまく動かない」AIに聞いて気象庁からデータを取るように変えられていて、最低気温と最高気温が同じ値になるという壁にぶつかってしまいました。IoT初心者のうちは、APIから送られてくるデータの「特殊なパターン」への対応が意外と難しいものです。AI出力のコードがつぎはぎの状態で、他にもおかしな表示をする部分があり、助けて欲しいという感じでした。
そこで、誰でも安定して気温を表示できるように、ソースコードを全面的にブラッシュアップすることにしました。天気予報APIからJSONデータを取得して、天気メッセージを組み立てるgetWeather()関数だけ変更しています。
3. 追加した機能の説明(天気予報APIの仕組み)
今回利用している「天気予報 API(livedoor 天気互換)」は、非常に多機能なJSONデータを返してくれます。
最低気温と最高気温を取得するためには、JSONデータ内の forecasts 配列の中にある temperature オブジェクトを参照します。
データの構造- 最高気温: forecasts -> temperature -> max -> celsius
- 最低気温: forecasts -> temperature -> min -> celsius
ここで注意が必要なのは、「常にデータが存在するわけではない」という点です。例えば、午後の予報では「今日の最低気温」はすでに過去のことなので null(データなし)として返ってくることがあります。ここを考慮せずにプログラムを書くと、動作が不安定になる原因になります。
APIのデータ構造と、今回追加した取得ロジックをまとめたインフォグラフィックスライドを作成しました。
※明日の天気のデータ構造は今日の天気と一緒ですが、温度"temperature"の階層が飛ばされていました。しかし、これだけ綺麗なスライドを作ってくれるのには驚きました。
4. 実装のポイント(コード解説)
それでは、実際のコードを抜粋して解説します。 以前のコード(WetherTrainOld.txt)(NotebookLMにソースとして提供した際のファイル名です。.inoが対応していなかったため、.txtに変更しました。)では、天気(テロップ)のみを取得していましたが、新しいコード(WetherTrainNew.txt)では気温データを変数に格納し、「データが存在する場合のみ」メッセージに追加するようにしました。
以前のコード(天気のみ)※ものすごく短い抜粋だったため、関数全体に変更しました。
// 天気予報を取得する関数 void getWeather(struct tm *t) { String data; // URLから取得するデータ msg_wether = ""; // メッセージを空にする // JSONデータ取得 getHtmlData(data, WATHER_API); // データが取得できたときだけメッセージを作る if (data != "") { const char *wether; // 天気 // JSONをパース StaticJsonDocument<5120> doc; // JSONをパースするためのメモリを確保 DeserializationError error = deserializeJson(doc, data); // JSONをパース // 天気予報の今日・明日別の処理 if (t->tm_hour < SWITC_WETHER) { msg_wether = "今日は"; wether = doc["forecasts"][TODAY]["telop"]; // JSONから天気を返す } else { msg_wether = "明日は"; wether = doc["forecasts"][TOMORROW]["telop"]; // JSONから天気を返す } // LEDで表示できない文字を変換してメッセージを組み立てる msg_wether += conversion(wether, cnWether, sizeof(cnWether)/sizeof(Conversion)); msg_wether += "です。"; } } 新しいコード(気温を追加+nullチェック)※ものすごく短い抜粋だったため、関数全体に変更しました。
// 天気予報を取得する関数 void getWeather(struct tm *t) { String data; // URLから取得するデータ msg_wether = ""; // メッセージを空にする // JSONデータ取得 getHtmlData(data, WATHER_API); // データが取得できたときだけメッセージを作る if (data != "") { // JSONをパース StaticJsonDocument<5120> doc; // JSONをパースするためのメモリを確保 DeserializationError error = deserializeJson(doc, data); // JSONをパース // 天気予報の今日・明日の切り替え int day; // 今日と明日の配列データ切り替え用 if (t->tm_hour < SWITC_WETHER) { day = TODAY; } else { day = TOMORROW; } // JSONデータから各種データを取得する const char *label = doc["forecasts"][day]["dateLabel"]; // 日付ラベル(今日、明日、明後日) const char *wether = doc["forecasts"][day]["telop"]; // 天気 const char *min = doc["forecasts"][day]["temperature"]["min"]["celsius"]; // 最低気温 const char *max = doc["forecasts"][day]["temperature"]["max"]["celsius"]; // 最高気温 // LEDで表示できない文字を変換してメッセージを組み立てる msg_wether = String(label) + "は"; msg_wether += conversion(wether, cnWether, sizeof(cnWether)/sizeof(Conversion)); if (min != NULL) { // 最低気温データがあるときのみメッセージに追加 msg_wether += ",最低気温は" + String(min) + "℃"; } if (max != NULL) { // 最高気温データがあるときのみメッセージに追加 msg_wether += ",最高気温は" + String(max) + "℃"; } msg_wether += "です。"; } } 工夫した点:Nullデータの回避APIの仕様上、取得できない値(null)をそのままString型に変換しようとすると、プログラムがクラッシュしたり、予期せぬ表示になったりします。 上記のように if (min != NULL) と判定を挟むことで、データがある時だけ表示するという、実践的で堅牢なコードに仕上げています。
5. 実際の表示例
今回の改良によって、電光掲示板には次のようなメッセージが流れるようになりました。
「3月20日(木) 今日はくもり,最低気温は8℃,最高気温は15℃です。 山手線は平常運転です。 (平常運転の場合は運行情報を表示しないようになっています。)」
美咲フォントの8x8ドットという極小サイズでも、「℃」の記号を含めてしっかり読み取ることができます。(実際は、細かい漢字は読みにくいです...) 実際に動いている様子を見ると、「自分で作ったデバイスが、こんなに便利な情報を教えてくれるんだ!」という感動がありますよ。
まとめ
今回の改良で、ただ「天気がわかる」だけでなく、「どんな服装で出かけるべきか」まで教えてくれる、よりパーソナルな情報デバイスへと進化しました。 受講者さんの「やってみたい」という声から生まれた今回のアップデートは、私にとっても非常に良い学びとなりました。
「自分でも作ってみたい!」「コードの中身をもっと詳しく知りたい!」という方は、ぜひ私の講座をチェックしてみてください。マンツーマンで丁寧にサポートします!
- 講座詳細はこちら: スマホ不要!天気・気温・電車遅延が流れるIoT電光掲示板を作ろう!
今後は、ゴミ出しの日の通知機能や、個別のカレンダー連携なども視野に入れています。皆さんも、自分だけのIoTデバイス作りを始めてみませんか?