Progress Log: Sensor Data Output Protocol (PC-Bound Transmission)¶
Task Description¶
ESP32から送られてくるセンサーデータをパソコンで安全に受け取るための方法を整理します。
何をするのか:
- いま、どのようにデータが送信されているのかを確認する
- 現在の方法の問題点を洗い出す
- より安全で信頼できる方法(プロトコル)を検討する
なぜ必要か:
現在のやり方は「スペースで区切られた数字を改行で終わらせる」という簡単なやり方です。 これだけでは、データが破損しても気づけませんし、データの開始位置も終了位置も明確ではありません。 より堅牢なプロトコル(= 送受信のルール)を作ることで、確実なデータ通信ができるようになります。
現状:送信データの形式¶
どんなときにデータが送信されるか¶
宇宙線を検出したときだけパソコンへデータを送信します。 周期的には送信しません(イベント駆動)。
データの形式¶
スペースで区切られた7つの数値です。最後は改行(\n)で終わります。
signal1 signal2 signal3 adcValue temperature pressure humidity
実際の例:
100 85 92 2048 25.35 1013.25 45.67
各データの説明¶
| フィールド | 意味 | 値の範囲 | どこから来たか |
|---|---|---|---|
| signal1 | 検出器1の強さ | 0~100 | GPIO12(100回測定) |
| signal2 | 検出器2の強さ | 0~100 | GPIO19(100回測定) |
| signal3 | 検出器3の強さ | 0~100 | GPIO27(100回測定) |
| adcValue | アナログ値 | 0~4095 | GPIO32のADC |
| temperature | 温度 | さまざま | BME280(℃) |
| pressure | 気圧 | さまざま | BME280(Pa) |
| humidity | 湿度 | さまざま | BME280(%) |
特別なルール¶
- signal1が0の場合: adcValueも必ず0になります(ハードウェアの制約)
- 常に同じ形式: ビルド環境がどうであれ、常にこの形式で送信されます
現在の問題点¶
問題1: データの開始位置と終了位置が曖昧¶
何が起きるか:
改行までが1つのデータだという約束ですが、データが来る前にノイズが混ざったらどうでしょう? パソコン側で「ここからデータが始まる」という目印がないので、正しい位置からデータを読み始められません。
例:
(ノイズ)100 85 92... ← データなのかノイズなのか判断できない
問題2: データが破損しても気づかない¶
何が起きるか:
送信中にノイズが混ざってデータが壊れても、受け取る側は「データが壊れた」と気づきません。 壊れたデータを使って計算してしまいます。
解決策:
データにチェックサムやCRCをつけておくと、壊れたかどうかを検出できます。
問題3: フォーマットの変更に対応しにくい¶
何が起きるか:
将来、新しいセンサーを追加して「8番目の値も送りたい」となったとき、古いパソコン用プログラムとの互換性を保つのが大変です。
解決策:
プロトコルにバージョン番号を含めておくと、「v1形式」「v2形式」と区別できます。
改善案の検討¶
案1: テキスト形式で開始マーク+チェックサムをつける¶
$DATA:100,85,92,2048,25.35,1013.25,45.67*CRC\n
メリット:
- テキスト形式なので、パソコンの画面でも読める
- デバッグしやすい
デメリット:
- データサイズが少し大きくなる
例:
$DATA:100,85,92,2048,25.35,1013.25,45.67*12AB\n
案2: バイナリ形式にする(コンパクト版)¶
[開始マーク][バージョン][データ長][7つの数値][チェックサム]
メリット:
- データサイズが小さい
- 高速に送受信できる
デメリット:
- 目で見て理解するのが難しい
- デバッグには専用ツールが必要
案3: 既存ライブラリを使う¶
- MessagePack: 汎用的なバイナリ形式(いろいろなプログラミング言語で対応)
- Protocol Buffers: Googleが作った形式(スキーマを定義して使う)
- JSON: 目で読みやすいテキスト形式(インターネットでよく使われる)
メリット:
- すでにできている仕組みを使えるので、バグが少ない
デメリット:
- ライブラリを組み込む必要がある(ESP32の容量確認が必要)
案4: 既存プロトコルを参考にした自作版¶
NMEA0183形式を参考にする(船やGPSで使われている形式):
$SENSOR,100,85,92,2048,25.35,1013.25,45.67*CRC\n
メリット:
- シンプルで分かりやすい
- データサイズも適度
- デバッグも容易
デメリット:
- 自分たちで動作確認を十分にする必要がある
案5: ATコマンド形式(RTOS/モデムで実績のある形式)¶
コマンド・レスポンス型プロトコル(マイコンやModemで広く使われている):
データ送信例:
+DATA:100,85,92,2048,25.35,1013.25,45.67\r\n
コマンド・レスポンス例:
AT+QUERY_DATA\r\n ← パソコン側からのコマンド
+DATA:100,85,92,...\r\n ← ESP32からのレスポンス
OK\r\n ← コマンド実行成功
メリット:
- モデムやマイコン通信で実績が豊富
- 双方向通信(クエリ+レスポンス)に対応しやすい
- エラーハンドリングが標準化されている(OK/ERROR/+CMSERRORなど)
- システムコマンド拡張が容易(新しいセンサーなら
AT+QUERY_NEWDATAなど追加可能) - ターミナルで手動テストが簡単
デメリット:
- データサイズがやや大きい(制御文字
\r\nが毎回必要) - 全文字列解析のため、バイナリより処理負荷が少し高い
- パースロジックを自作する必要がある
案6: COBS(Consistent Overhead Byte Stuffing)形式¶
フレーミング効率を重視したバイナリプロトコル(車載ネットワークやロボット通信で採用):
フレーム構造:
0x00 [COBS化されたペイロード] 0x00
エンコード例:
元のデータ: 0x64, 0x55, 0x5C, 0x00, 0x08, 0x00, 0x42, 0x43
(100, 85, 92, signal3の途中に0x00が含まれる)
COBS後: 0x00 0x04 0x64 0x55 0x5C 0x04 0x08 0x04 0x42 0x43 0x00
メリット:
- バイナリデータ内に0x00を含んでも正しく送受信できる(フレーム区切りに支障なし)
- オーバーヘッドが最小限(最大1/254のペイロードサイズ増加)
- フレーミング信頼性が高い(0x00が確実な区切り)
- バイナリで効率的、テキストほどサイズが大きくない
- ノイズから回復しやすい(フレーム同期が容易)
デメリット:
- COBSエンコード/デコードロジックを実装する必要がある
- テキスト形式より目で読みにくい
- チェックサム/CRCは別途追加が必要
各案の比較:フレーム区切りとチェックサムの観点¶
案1:テキスト形式¶
フレーム区切り:
- 開始点:
$DATA:という目に見えるマーク - 終了点:
\nで確定 - 信頼性:◎ 高(マークが明確)
チェックサム:
- 実装:CRC(
*CRCの後ろ) - 効果:データ破損を検出できる
- オーバーヘッド:4~8バイト増加
案2:バイナリ形式¶
フレーム区切り:
- 開始点:固定のバイナリヘッダー
- 終了点:チェックサムの後が終了
- 信頼性:◎ 高(ヘッダーが確実)
チェックサム:
- 実装:チェックサムまたはCRC(必須)
- 効果:確実なエラー検出
- オーバーヘッド:1~2バイト
案3:既存ライブラリ¶
フレーム区切り:
- 開始点・終了点:ライブラリが透過的に処理
- 信頼性:◎ 高(ライブラリが保証)
チェックサム:
- 実装:ライブラリの仕組みで自動実装
- 効果:非常に高度なエラー検出
- オーバーヘッド:ライブラリ依存
案4:NMEA0183参考¶
フレーム区切り:
- 開始点:
$SENSORという目に見えるマーク - 終了点:
*CRC\nで確定 - 信頼性:◎ 高(実績のある標準形式)
チェックサム:
- 実装:CRC(
*CRCの部分) - 効果:データ破損を検出できる
- オーバーヘッド:4~8バイト増加
案5:ATコマンド形式¶
フレーム区切り:
- 開始点:
+DATA:というマーク - 終了点:
\r\nで確定 - 信頼性:△ 中(エラーハンドリングはあるが、チェックサムない)
チェックサム:
- 実装:なし(エラー応答
ERRORでのみ検知) - 効果:データ破損の検出はできない
- オーバーヘッド:0バイト
補足:AT形式でもチェックサムを追加することは可能:+DATA:100,85,...*CRC\r\n
案6:COBS形式¶
フレーム区切り:
- 開始点:0x00のヌルバイト
- 終了点:0x00のヌルバイト
- 信頼性:◎ 高(ペイロード内に0x00が絶対来ないから確実)
チェックサム:
- 実装:COBSエンコードのみでは検出できない(別途追加推奨)
- 効果:CRCを追加すれば確実なエラー検出
- オーバーヘッド:COBSで最大1/254のペイロード増加+CRCなら4~8バイト
Outcome(分かったこと)¶
6つの改善案が出た¶
より堅牢なプロトコルを作る方法は大きく6つに分かれます:
- テキスト形式 — シンプルで分かりやすい(デバッグに向く)
- バイナリ形式 — 効率的だが専用ツールが必要
- 既存ライブラリ — 安定だがESP32のメモリが心配
- NMEA0183参考 — バランスが良さそう
- ATコマンド形式 — 実績豊富で双方向通信に対応
- COBS形式 — バイナリ効率とフレーミング信頼性の両立(推奨候補)
評価の視点¶
実装するなら、以下の点をチェックする必要があります:
- ESP32のFlashメモリに収まるか?(残容量は約3.1MB)
- ESP32のRAMに収まるか?(残容量は約290KB)
- パソコン側のプログラムが簡単に書けるか?
- デバッグ中に目で内容を確認できるか?
Next Steps(次にやること)¶
- 評価表を作成する — 6つの案を表にして、メリット・デメリット・実装コストを比較
- COBS実装の検証 — COBSエンコード/デコード実装の簡潔性と処理負荷を評価
- ATコマンド形式の調査 — モデムやRTOSでの実装例を調査し、ESP32への応用可能性を検討
- メモリ消費量を測る — 各ライブラリやエンコーダーのメモリ使用量を確認
- プロトタイプを実装する — 一番良さそうな案を試しに実装してテスト
- パソコン側のプログラムを書く — 受け取ったデータを正しく解析できるか確認