Skip to content

Instantly share code, notes, and snippets.

@GOROman
Created March 8, 2026 00:03
Show Gist options
  • Select an option

  • Save GOROman/948e7573035c17dea1ac489da350ce4f to your computer and use it in GitHub Desktop.

Select an option

Save GOROman/948e7573035c17dea1ac489da350ce4f to your computer and use it in GitHub Desktop.
ELRS の調査を GPT-5.4 XHigh にやらせてみたテスト

ELRS プロトコル仕様メモ(ESP32 連携向け)

この文書の対象範囲

この文書は、ExpressLRS(ELRS)を 外部 MCU(ESP32 など)から扱う ための実装メモです。

ELRS には大きく 2 つの層があります。

  1. ELRS の無線 OTA リンク
    TX モジュールと RX の間で動く無線プロトコル
  2. CRSF シリアルプロトコル
    ELRS TX モジュールや ELRS 受信機と UART で接続するときに使う制御用プロトコル

外部 MCU から ELRS を扱う場合、実装対象として現実的で安定しているのは CRSF over UART です。
ELRS の OTA パケット形式は、ファームウェア世代、RF モード、周波数帯、ハードウェア構成に依存するため、この文書では OTA 層は高レベルの説明に留め、UART 側の CRSF を中心に整理します。

1. ELRS とは何か

  • ELRS は、FPV ドローンやロボットで広く使われる低遅延 RC リンクです。
  • 2.4 GHz900 MHz、一部 デュアルバンド ハードウェアをサポートします。
  • 公式情報では最大 1000 Hz のパケットレートが案内されています。
  • ELRS は以下を運びます。
    • RC 操作データ
    • テレメトリ
    • デバイス設定や管理トラフィック

2. ESP32 から使うときの推奨構成

2.1 地上側で ESP32 が送信元になる場合

ESP32 -> UART -> ELRS TX モジュール -> OTA 無線 -> ELRS RX

ESP32 から RC 指令を生成したい場合の構成です。
実際には ESP32 から ELRS TX モジュールへ CRSF 0x16 RC_CHANNELS_PACKED フレームを送り、必要に応じてリンク統計などの返答を受け取ります。

注意:

  • 汎用 CRSF の仕様では、送信機から TX モジュールへの接続は 単線 half-duplex として説明されています。
  • ELRS TX モジュールによっては、モジュールベイ信号ではなく通常の UART に近い形でアクセスできる場合があります。
  • もしモジュールがベイ用の half-duplex 信号や反転信号しか出していないなら、レベル変換や極性変換は使用者側で対応が必要です。

2.2 機体側で ESP32 が受信側になる場合

ELRS RX -> UART -> ESP32

ESP32 が制御対象そのものになる場合の構成です。最も扱いやすい構成でもあります。

  • ELRS 受信機のシリアル出力を CRSF に設定する
  • ESP32 側で RC チャンネルを UART から受信する
  • 必要なら ESP32 からテレメトリを上流へ返す

カスタムロボット、ローバー、ジンバル、独自制御機器では、この構成が最も実用的です。

3. ELRS OTA 層で外部 MCU が意識すべきこと

ESP32 から見た場合、ELRS の無線リンクは次のような性質を持つブラックボックスとして扱えます。

  • 双方向の低遅延パケット通信である
  • パケットレート、テレメトリ比率、スイッチモード、モデルマッチ設定によって内部挙動が変わる
  • 最大 16 チャンネルの制御情報を扱える
  • ただし RF 側のスイッチ圧縮やフル解像度モードは ELRS 設定に依存する

そのため、外部 MCU から ELRS の RF パケットを直接生成しようとするより、CRSF を話す 方が正しい実装方針です。

4. UART / 電気仕様

4.1 汎用 CRSF の UART モード

接続区間 トポロジ 標準ボーレート フォーマット 信号
送信機 -> TX モジュール 単線 half-duplex 400000 baud 8N1 ハード依存で反転/非反転
RX -> FC / 車載 MCU 2 線 full-duplex 416666 baud 8N1 非反転

4.2 ELRS 実機での実用設定

ELRS まわりでは、受信機と下流コントローラの接続に 420000 baud が実用上よく使われます。
このリポジトリのサンプルコードも次の前提にしています。

  • 420000 baud
  • 8 data bits
  • no parity
  • 1 stop bit
  • 3.3V UART

ESP32 を ELRS 受信機につなぐ場合の基本配線:

  • ESP32 の TX -> ELRS RX の RX
  • ESP32 の RX -> ELRS RX の TX
  • GND 共通
  • 非反転 UART

5. CRSF フレーム形式

CRSF の UART 通信はフレーム単位です。

5.1 通常フレーム(broadcast frame)

+--------+--------+------+---------+------+
| Sync   | Length | Type | Payload | CRC8 |
+--------+--------+------+---------+------+

5.2 拡張フレーム(extended frame)

+--------+--------+------+-------------+--------+---------+------+
| Sync   | Length | Type | Destination | Origin | Payload | CRC8 |
+--------+--------+------+-------------+--------+---------+------+

5.3 各フィールドのルール

  • Sync
    • シリアル同期バイト 0xC8
    • またはデバイスアドレス 0xEC / 0xEE など
  • Length
    • 先頭 2 バイト(Sync, Length)を含まない
    • 有効範囲は 2..62
  • Sync と CRC を含めた最大フレーム長は 64 バイト
  • CRC8
    • 多項式は 0xD5
    • 計算対象は Type + Payload
    • SyncLength は CRC に含めない

6. 主要デバイスアドレス

意味 アドレス
Broadcast 0x00
Flight Controller / Serial Sync 0xC8
Remote Control 0xEA
CRSF Receiver 0xEC
CRSF Transmitter Module 0xEE

典型的な使い方:

  • ESP32 から ELRS TX モジュールへ RC を送るときは 0xEE
  • 車載 MCU から ELRS 受信機へテレメトリを返すときは 0xC8

7. ESP32 実装で重要なフレームタイプ

7.1 0x16 RC Channels Packed

用途:

  • コントローラ -> TX モジュール
  • 受信機 -> Flight Controller / 車載 MCU

Payload:

  • 16 チャンネル
  • 各チャンネルは 11 bit
  • 全体で 22 バイト
  • パック順は実質 LSB-first / little-endian 的なビット詰め

Flight Controller 側で一般的に使われる CRSF の変換式:

#define TICKS_TO_US(x) (((x) - 992) * 5 / 8 + 1500)
#define US_TO_TICKS(x) (((x) - 1500) * 8 / 5 + 992)

代表値:

  • 中立 1500 us -> 992
  • おおよそ 988 us -> 172
  • おおよそ 2012 us -> 1811

ELRS 実運用での慣例:

  • CH1..CH4 がメイン操作軸
  • CH5 (AUX1) が arm/disarm に使われることが多い

フェイルセーフ上の注意:

  • 0x16 フレームが来なくなったら、安全側へ遷移するべきです
  • 汎用 CRSF 仕様では、"cut" モード時に FC 側フェイルセーフを発火させるまで最大 1 秒 ほど見込む実装が案内されています

7.2 0x14 Link Statistics

Payload 構成:

Byte(s) 意味
0 uplink RSSI antenna 1 (dBm * -1)
1 uplink RSSI antenna 2 (dBm * -1)
2 uplink link quality (%)
3 uplink SNR(符号付き dB)
4 使用中アンテナ
5 RF プロファイル / モード index
6 TX 出力 enum/index
7 downlink RSSI (dBm * -1)
8 downlink link quality (%)
9 downlink SNR(符号付き dB)

リンク健全性を監視したいとき、ESP32 側で最も実用的なフレームです。

7.3 0x1C Link Statistics RX

受信機寄りの簡易リンク統計:

Byte(s) 意味
0 RSSI (dBm * -1)
1 RSSI (%)
2 link quality (%)
3 SNR(符号付き dB)
4 RF power(dBm)

7.4 0x1D Link Statistics TX

送信機寄りの簡易リンク統計:

0x1C と同じ内容に加えて:

Byte(s) 意味
5 frames per second / 10

7.5 0x21 Flight Mode

Payload:

  • NUL 終端文字列

単純で扱いやすいため、サンプルコードの「上流へ返すテレメトリ」の例として使いやすいフレームです。

8. ESP32 コードへ落とすときの指針

8.1 ESP32 が TX モジュールを駆動する場合

  1. UART を 420000 8N1 で初期化する
  2. 4 ms から 10 ms 周期で 0x16 RC フレームを送る
  3. 明示的に安全確認が取れるまで、スロットル低・CH5 低を維持する
  4. 戻りの 0x14 / 0x1C / 0x1D を読む

8.2 ESP32 が ELRS 受信機を読む場合

  1. 受信機のシリアル出力を CRSF に設定する
  2. 入ってくる 0x16 フレームをパースする
  3. 必要に応じて ticks を us に変換する
  4. チャンネル閾値でアプリケーション処理を行う
  5. 必要なら 0x21 Flight Mode のような単純なテレメトリを返す

9. このリポジトリに追加したファイル

  • ELRSSPEC.md
  • esp32/crsf.h
  • esp32/crsf.c
  • esp32/elrs_tx_to_module_example.c
  • esp32/elrs_rx_from_receiver_example.c
  • test/crsf_selftest.c

10. この文書とサンプルの非対応範囲

  • ELRS のネイティブ OTA パケット形式そのものは固定仕様として扱っていません
  • バインド、周波数ホッピング、RF チップ制御、ネイティブ OTA モデム処理は実装していません
  • サンプルコードは UART 側の CRSF に絞っています
    これは、単体 ESP32 アプリケーションが ELRS と連携するための正しい実装点だからです

参考資料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment