架构:内核与数据流

CRSF 数据流如何化为扑翼与尾翼:模块边界、两个混控内核,以及在链路断开时让翼龙存活的有限状态机。

信号通路

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

四个结构性思路让这台野兽保持稳定、代码保持精简:

  1. 通道尽早归一化。172–1811 CRSF 窗口内的每个原始值都会一次性映射到 −1…+1(_crsfToNorm)或百分比,只有该单位流经混控器——不再重复魔法常量。
  2. 输出是打标签的,而非固定引脚。混控器写入 _f[ServoFunc]。某个标签驱动哪个物理 PWM 输出由配置文件的 funcMap 稍后决定——参见 混控器参考 .重新分配模型引脚绝不会触及混控器的数学运算。
  3. 内核是编译期家族、运行期选择。波形扑翼与变速箱控制器都存在于二进制中;活动配置文件在每个更新节拍选择内核。
  4. 失控保护不是事件,而是状态。链路丢失、台架模式与摇杆覆盖是 update() 中的显式闸门,因此无线电静默时伺服器绝不会失控。

两大内核:波形与齿轮箱

内核是将归一化通道转换为伺服函数 µs 的模块。PteronautOS 有两个族,由混控配置文件编号区分:

配置文件 执行器 机型原型
波形(伺服)内核 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 电机电调、V 尾或升降舵 + 方向舵 带常规尾翼的齿轮/电机扑翼机

选择发生在 update() 中,通过单一测试 PROFILE_IS_GEARBOXactiveProfile ≥ 3)。配置文件本身是运行时值:它始于构建标志 MIXER_PROFILE(旧式 ORNITHOPTER_GEARBOX=1 仍映射到配置文件 5),但可通过 setOrnithopterProfile() 从 WebUI 实时切换——固件无需重新烧录即可瞄准新机架。共有八个配置文件;其精确的 funcMap 布局已列于混控器参考中。

波形内核(舵机扑翼)

波形内核是大多数人所说的「PteronautOS」:两个机翼伺服器运行相位连续的振荡,其形状在每个周期被雕琢。其构造:

齿轮箱内核(电机+尾翼)

变速箱内核以电机驱动系加常规尾翼换取纯扑翼。由于电机连续旋转,该内核每个节拍无状态——无振荡器——取而代之:

一架扑翼机甚至可以同时携带两种性格:以波形内核扑翼起飞,以变速箱巡航——运行时配置文件切换就是 update() 中的那一行。

状态:链路、台架与失控保护

update() 以固定约 10 ms 节拍从 WiFi/伺服循环调用,并在任何混控器运行前通过三个标志进行闸控:

状态 条件 行为
正常飞行 linkUp + 武装通道在线 完整内核输出跟随摇杆
台架 / 面板模式 benchMode(WebUI 面板,无 RC 链路) 注入中立摇杆,油门停在扑翼阈值之下——滑翔 + 微调编辑实时可见
摇杆覆盖 stickOverride(虚拟通道) 固件注入的通道值完全取代 CRSF(伺服扫掠、测试)
失控保护 链路丢失(onLinkDown / enterFailsafe 所有函数居中到 1500 µs,振荡器复位,电机 → 最小;CRSF 丢包也在 RX 层居中

丢失时居中的行为被有意地重复于两层: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

再下一层——数字究竟产生何种波形,以及每个配置文件如何将函数接线到 PWM 输出——位于 混控器参考 ,而伺服时序包络记录于 伺服内核 一文。