模式切换核心逻辑:基于RC通道的切换原理
飞行模式切换,说白了就是飞控怎么知道你现在想干什么。我刚开始做飞控时,总觉得这玩意儿很玄乎——遥控器一拨杆,飞机就从稳模式变成特技模式,背后到底发生了什么?
其实原理不复杂。遥控器发出的每一个指令,最终都会变成飞控能读懂的信号。这个信号,就是PWM。
PWM信号解析:飞控的“耳朵”
遥控器接收机输出的是PWM信号,也就是脉冲宽度调制信号。每个通道对应一个PWM值,范围通常在1000μs到2000μs之间。
举个例子:
- 油门杆最低时,PWM值约1000μs
- 油门杆最高时,PWM值约2000μs
- 中位时,约1500μs
飞控通过读取这些脉冲宽度,就知道遥控器各个通道的位置了。嗯,这里要注意——不同接收机输出的PWM范围可能略有差异,有的可能是1100-1900,有的可能是988-2012。所以飞控上电后第一件事,就是做PWM校准。
基于RC通道的切换原理
模式切换通常用一个三档开关来实现。这个开关占用一个RC通道,飞控通过读取该通道的PWM值来判断开关位置。
典型的映射关系是这样的:
| PWM范围(μs) | 开关位置 | 对应模式 |
|---|---|---|
| 1000 - 1300 | 低位 | 自稳模式 |
| 1300 - 1700 | 中位 | 定高模式 |
| 1700 - 2000 | 高位 | 悬停模式 |
为什么用三档开关?因为大多数飞控支持3-6种常用模式,三档开关配合其他通道的组合,就能覆盖所有需求。
模式映射表设计
模式映射表,就是一张“开关位置→飞行模式”的对照表。我习惯把它设计成可配置的,而不是写死在代码里。
一个典型的映射表结构:
// 模式映射表结构体
typedef struct {
uint16_t pwm_low; // PWM下限
uint16_t pwm_high; // PWM上限
flight_mode_t mode; // 对应的飞行模式
} mode_map_entry_t;
// 示例映射表
mode_map_entry_t mode_map[] = {
{1000, 1300, MODE_STABILIZE}, // 自稳
{1300, 1700, MODE_ALT_HOLD}, // 定高
{1700, 2000, MODE_LOITER}, // 悬停
};
这样做的好处是:换遥控器或者改手感时,只需要修改映射表的参数,不用动核心逻辑。
模式优先级与互斥规则
模式不是想切就能切的。有些模式之间天生互斥,比如“手动模式”和“自动降落模式”就不能同时存在。这就涉及到优先级和互斥规则。
我总结了一套规则,供你参考:
- 安全模式优先级最高: 比如“紧急降落”、“返航”等模式,一旦触发,其他模式全部让路。
- 手动模式优先级最低: 因为手动模式依赖操作员的技术,出错概率大。
- 互斥规则: 同一时刻只能有一个“位置控制类”模式(如悬停、定点)和一个“姿态控制类”模式(如自稳、特技)。
举个例子:飞机正在执行“自动航线”模式,此时遥控器切到“自稳模式”。飞控应该怎么做?
我个人习惯的做法是:
- 先判断新模式的优先级是否高于当前模式
- 如果高于,立即切换,并执行平滑过渡
- 如果低于,拒绝切换,或者等待当前任务完成后再切换
模式切换的完整流程
把上面这些串起来,模式切换的完整流程就是:
- 飞控读取RC通道的PWM值
- 查映射表,确定开关位置对应的目标模式
- 检查目标模式与当前模式是否互斥
- 检查目标模式的优先级是否允许切换
- 如果允许,执行模式切换(包括状态重置、参数重载等)
- 如果不允许,保持当前模式,并记录日志
这个流程看起来简单,但每个环节都有细节。比如状态重置——从“定高模式”切到“悬停模式”时,高度积分器要不要清零?我的建议是:不清零,但要做平滑过渡,否则飞机会猛地窜一下。
模式切换看起来是个小功能,但做不好会出大问题。我见过不少飞控炸机,原因就是模式切换逻辑有漏洞——要么切不过去,要么切过去后状态没重置对。
所以我的建议是:先把PWM解析和映射表调稳,再考虑优先级和互斥规则。一步一步来,别想一口吃成胖子。