アーキテクチャ:カーネルとデータフロー

CRSFストリームが羽ばたきと尾になる仕組み:モジュール境界、2つのミキサーカーネル、リンク断でも翼竜を生かす状態機械。

信号経路

PteronautOS は ExpressLRS 4.x のフォークで、受信機の「PWM パススルー」末尾を専用の飛行制御レイヤーに置き換えました。データ経路は意図的に短く保たれています:

CRSF radio link
  │  2.4 GHz SX1280
  ▼
rx_main / CRSF decoder        → ChannelData[]  (raw 172…1811 µs-window values)
  ▼
Ornithopter::update()          → _readChannels() → voice* fields
  ▼  kernel select: activeProfile ≥ GEARBOX_2VTAIL_1RUD ?
_computeServoMixer()   OR   _computeGearboxMixer()
  ▼
_f[]  (indexed by ServoFunc tag, µs)
  ▼
PWM output stage               → funcMap channels → wing / rudder / motor servos

4 つの構造上のアイデアが機体を安定させ、コードを小さく保ちます:

  1. チャンネルは早い段階で正規化されます。 172–1811 の CRSF ウィンドウ内の生値はすべて −1…+1(_crsfToNorm)またはパーセントに一度だけ写像され、その単位だけがミキサーを流れます — マジック定数の繰り返しはありません。
  2. 出力は固定ではなくタグ付けされます。 ミキサーは _f[ServoFunc] に書き込みます。タグがどの物理 PWM 出力を駆動するかは、後でプロファイルの funcMap が決めます — 参照: ミキサー・リファレンス .モデルの配線を変えても、ミキサーの計算には一切触れません。
  3. カーネルはコンパイル時のファミリーであり、実行時の選択です。 波形フラッパーとギアボックス・コントローラーはどちらもバイナリ内にあり、アクティブなプロファイルが毎更新ティックでカーネルを選びます。
  4. フェイルセーフはイベントではなく状態です。 リンク断、ベンチモード、スティック上書きは update() 内の明示的なゲートなので、無線が沈黙している間サーボが暴走することはありません。

2つのカーネル:波形とギアボックス

カーネルとは、正規化されたチャンネルをサーボ機能の µs へ変えるブロックです。PteronautOS にはミキサー・プロファイル番号で区別される 2 つのファミリーがあります:

ファミリー プロファイル アクチュエータ モデル原型
波形(サーボ)カーネル 0 SERVO_2WING · 1 SERVO_2WING_1RUD · 2 SERVO_4WING 羽ばたき翼サーボ(2–4)、冠舵 ダイレクトドライブ・サーボのオーニソプター — 古典的な PteronautOS
ギアボックス・カーネル 3 GEARBOX_2VTAIL_1RUD · 4 GEARBOX_1MOT_2VTAIL · 5 GEARBOX_1MOT_2VTAIL_1RUD · 6 GEARBOX_1ELE_1RUD · 7 GEARBOX_1MOT_1ELE_1RUD モーター ESC、V テールまたはエレベーター + ラダー ギア駆動/モーター駆動フラッパーと一般的な尾翼面

選択は update() 内の単一テスト PROFILE_IS_GEARBOX(activeProfile ≥ 3)で行われます。プロファイル自体は実行時の値です:ビルドフラグ MIXER_PROFILE から始まり(旧 ORNITHOPTER_GEARBOX=1 は今もプロファイル 5 にマップ)、WebUI から setOrnithopterProfile() でライブ切替できます — 再フラッシュなしで新しい機体へ照準を移せます。プロファイルは全部で 8 つ。正確な funcMap レイアウトはミキサー・リファレンスに表でまとめられています。

波形カーネル(サーボ羽ばたき)

波形カーネルは、ほとんどの人が「PteronautOS」と呼ぶものです:2 つの翼サーボが位相連続の振動を実行し、その形は毎サイクル彫琢されます。その解剖:

ギアボックスカーネル(モーター+尾翼)

ギアボックス・カーネルは純粋な羽ばたきをモーター駆動系 + 一般的な尾翼面と交換します。モーターは連続回転するため、このカーネルはティックごとにステートレスで — オシレーターはなく — 代わりに:

1 つのオーニソプター機体が両方の性格を持てます:波形カーネルで羽ばたき発進し、ギアボックスで巡航する — 実行時プロファイル切替は update() 内のその 1 行です。

状態:リンク・ベンチ・フェイルセーフ

update() は WiFi/サーボループから固定 ~10 ms のケイデンスで呼ばれ、ミキサー実行前に 3 つのフラグをゲートします:

状態 条件 挙動
通常飛行 linkUp + アームチャンネル有効 カーネル出力全体がスティックに追従します
ベンチ/パネルモード benchMode(WebUI パネル、RC リンクなし) 中立スティックが注入され、スロットルはフラップ閾値未満に保持 — グライド + トリムの編集がライブで見えます
スティック上書き stickOverride(仮想チャンネル) ファームウェア注入のチャンネル値が CRSF を完全に置き換えます(サーボ掃引、テスト)
フェイルセーフ リンク喪失(onLinkDown / enterFailsafe) 全機能が 1500 µs に中央化され、オシレーターリセット、モーター → 最小;CRSF パケット喪失も RX レベルで中央化されます

喪失時中央化の挙動は意図的に 2 層へ重複させています:CRSF スタックがチャンネルデータをフェイルセーフし、Ornithopter 層が 幾何(振動状態を含む)をフェイルセーフします。したがって死んだ無線は、滑空可能で操縦可能な機体を残します — 決して暴れる機体ではありません。

ソースマップ

モジュール パス 責務
Ornithopter レイヤー src/lib/Ornithopter/ カーネル選択、ミキサー計算、波形オシレーター、プロファイル、トリム
飛行プロファイルと定数 src/lib/Ornithopter/OrnithopterConfig.h MixerProfile 列挙、ServoFunc タグ、funcMap、すべての数値デフォルト
オシレーター/形状 src/lib/Ornithopter/OrnithopterWaveform.h 位相積分、猛度成形、反転ロジック
Zephyrus(オプション) src/lib/Zephyrus/ MPU6050 + Mahony AHRS、デュアル PID、冠/尾翼補正
PWM 出力段 src/lib/ServoOutput/devServoOutput.cpp CRSF ティックに同期して µs を書き込みます
WebUI 設定 src/lib/WIFI/devWIFI.cpp 実行時プロファイル + チューニング永続化(/pteronautos)

1 つ下の層 — 数値が正確にどの波形を生み、各プロファイルが関数を PWM 出力へどう配線するか — は ミキサー・リファレンス にあり、サーボタイミング包絡線は サーボカーネル に記載されています。