Skip to content

Progress Log: Sensor Data Output Protocol (PC-Bound Transmission)

Task Description

ESP32から送られてくるセンサーデータをパソコンで安全に受け取るための方法を整理します。

何をするのか:

  1. いま、どのようにデータが送信されているのかを確認する
  2. 現在の方法の問題点を洗い出す
  3. より安全で信頼できる方法(プロトコル)を検討する

なぜ必要か:

現在のやり方は「スペースで区切られた数字を改行で終わらせる」という簡単なやり方です。 これだけでは、データが破損しても気づけませんし、データの開始位置も終了位置も明確ではありません。 より堅牢なプロトコル(= 送受信のルール)を作ることで、確実なデータ通信ができるようになります。

現状:送信データの形式

どんなときにデータが送信されるか

宇宙線を検出したときだけパソコンへデータを送信します。 周期的には送信しません(イベント駆動)。

データの形式

スペースで区切られた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つに分かれます:

  1. テキスト形式 — シンプルで分かりやすい(デバッグに向く)
  2. バイナリ形式 — 効率的だが専用ツールが必要
  3. 既存ライブラリ — 安定だがESP32のメモリが心配
  4. NMEA0183参考 — バランスが良さそう
  5. ATコマンド形式 — 実績豊富で双方向通信に対応
  6. COBS形式 — バイナリ効率とフレーミング信頼性の両立(推奨候補)

評価の視点

実装するなら、以下の点をチェックする必要があります:

  • ESP32のFlashメモリに収まるか?(残容量は約3.1MB)
  • ESP32のRAMに収まるか?(残容量は約290KB)
  • パソコン側のプログラムが簡単に書けるか?
  • デバッグ中に目で内容を確認できるか?

Next Steps(次にやること)

  1. 評価表を作成する — 6つの案を表にして、メリット・デメリット・実装コストを比較
  2. COBS実装の検証 — COBSエンコード/デコード実装の簡潔性と処理負荷を評価
  3. ATコマンド形式の調査 — モデムやRTOSでの実装例を調査し、ESP32への応用可能性を検討
  4. メモリ消費量を測る — 各ライブラリやエンコーダーのメモリ使用量を確認
  5. プロトタイプを実装する — 一番良さそうな案を試しに実装してテスト
  6. パソコン側のプログラムを書く — 受け取ったデータを正しく解析できるか確認