# CH8=1024 Failsafe值导致状态机重复重置问题修复 ## 问题回顾 实车测试时,车辆在原点和第二个路径点之间反复切换。Log显示: ``` [MC_CTRL] CH8 crossed threshold: 1800 -> 1024 [MC_CTRL] *** Auto mode triggered! Resetting to GOTO_START *** [MC_CTRL] CH8 crossed threshold: 1024 -> 1800 ``` **每次都精确地跳到1024,而不是随机抖动!** ## 真正的根本原因 **1024是SBUS协议的中心值,也是信号丢失时的failsafe默认返回值!** ### 代码分析 **`STM32H743/FML/SBUS.h` 第27行:** ```c #define SBUS_CENTER_VALUE 1024 // 通道中心值 ``` **`STM32H743/FML/SBUS.c` 第343-346行:** ```c HIDO_UINT16 SBUS_GetChannel(HIDO_UINT8 _u8Channel) { if (!SBUS_IsSignalValid(SBUS_TIMEOUT_MS)) { return SBUS_CENTER_VALUE; // 返回1024! } return g_stSBUSData.m_au16Channels[_u8Channel]; } ``` ### 问题链路 1. **SBUS信号短暂丢失**(可能原因:电磁干扰、遥控器距离、天线问题) 2. **`SBUS_IsSignalValid()` 返回FALSE** 3. **`SBUS_GetChannel(7)` 返回failsafe值 `1024`** 4. **`1024 < 1500`(阈值)** → 退出自动模式 5. **SBUS信号恢复** 6. **CH8回到正常值1800** → `1800 > 1500` → 触发"Auto mode triggered" 7. **`MC_Init`被调用** → 状态机重置到`GOTO_START` 8. **循环反复** ### 为什么之前校准正常? - 校准任务可能不使用CH8来判断模式切换 - 或者校准时SBUS信号更稳定(距离近、环境干净) - 或者校准任务没有"上升沿触发重置"的逻辑 ## 解决方案 ### 核心策略:过滤failsafe值1024 **不能将1024当作有效的CH8输入!** 它是信号丢失的指示,不是遥控器的真实位置。 **文件:`STM32H743/APL/motion_control_task.c`** ```c HIDO_UINT16 ch8_raw = SBUS_GetChannel(MOTION_SBUS_AUTO_CHANNEL); /* 过滤SBUS failsafe默认值1024:这是信号丢失时的返回值,不应触发模式切换 * 当ch8=1024时,保持之前的有效值不变 */ static HIDO_UINT16 ch8 = 1000; /* 默认手动模式 */ static HIDO_UINT32 s_ch8_failsafe_count = 0; if (ch8_raw != 1024) { ch8 = ch8_raw; /* 只更新非failsafe值 */ if (s_ch8_failsafe_count > 0) { DBG_Printf("[MC_CTRL] CH8 recovered from failsafe (1024), count=%u, new value=%u\r\n", s_ch8_failsafe_count, ch8); s_ch8_failsafe_count = 0; } } else { /* ch8=1024时保持之前的值,记录failsafe事件 */ s_ch8_failsafe_count++; if (s_ch8_failsafe_count == 1) { DBG_Printf("[MC_CTRL] CH8 failsafe detected (1024), keeping previous value=%u\r\n", ch8); } } ``` ### 原理 - **正常情况**:ch8_raw ≠ 1024,直接更新ch8 - **信号丢失**:ch8_raw = 1024,忽略这个值,保持之前的ch8不变 - **信号恢复**:ch8_raw回到正常值,更新ch8,记录恢复事件 ### 为什么这样修复是正确的? 1. **1024不是有效的遥控器位置** - SBUS的有效范围是172-1811(对应PWM 1000-2000) - 遥控器拨杆不会精确停在中点1024 - 即使停在中点,也会在1020-1030之间抖动,不会是精确的1024 2. **1024是协议层的failsafe标识** - 这是`SBUS_GetChannel`在信号丢失时的专用返回值 - 不应该被上层业务逻辑当作真实输入 3. **保持last-known-good策略** - 信号短暂丢失时,保持之前的有效状态 - 避免因瞬态干扰导致模式误切换 ## 与之前迟滞方案的对比 ### 之前的CH8迟滞方案(保留) ```c #define CH8_THRESHOLD_ENTER 1600 #define CH8_THRESHOLD_EXIT 1400 ``` - **目的**:防止在阈值附近的模拟量抖动 - **适用场景**:遥控器ADC噪声、拨杆机械抖动 - **局限性**:无法解决信号丢失导致的1024问题 ### 本次failsafe过滤方案 - **目的**:识别并忽略SBUS协议的failsafe返回值 - **适用场景**:SBUS信号短暂丢失、电磁干扰 - **优势**:直击根本原因 ### 两者关系 **互补,不冲突!** 建议同时保留: 1. **Failsafe过滤**:第一道防线,过滤协议层的异常值 2. **CH8迟滞**:第二道防线,防止真实的模拟量抖动 ## 日志输出 ### 正常运行 ``` (无输出,ch8正常更新) ``` ### 检测到failsafe ``` [MC_CTRL] CH8 failsafe detected (1024), keeping previous value=1800 ``` ### 信号恢复 ``` [MC_CTRL] CH8 recovered from failsafe (1024), count=5, new value=1800 ``` ## 根本解决方案(硬件层面) 软件修复只是权宜之计,真正应该: 1. **检查SBUS接收机天线**:方向、位置、损坏 2. **检查遥控器信号强度**:距离、方向、电池电量 3. **检查电磁干扰**:电机、电调、GPS模块的EMI 4. **检查SBUS线路**:接触不良、屏蔽不足 5. **考虑冗余设计**:双接收机、信号强度监控 ## 测试验证 1. **编译并烧录**最新代码 2. **测试场景1:模拟SBUS信号丢失** - 启动自动模式 - 遮挡接收机天线或关闭遥控器 - **预期**:看到"CH8 failsafe detected" - **预期**:车辆状态机不重置,保持当前状态 3. **测试场景2:信号恢复** - 恢复遥控器信号 - **预期**:看到"CH8 recovered from failsafe" - **预期**:车辆继续之前的任务,不重新初始化 4. **测试场景3:正常操作** - 手动切换CH8拨杆 - **预期**:模式正常切换,无"failsafe"日志 ## 相关文件 - `STM32H743/APL/motion_control_task.c` - 主要修复 - `STM32H743/FML/SBUS.c` - SBUS协议实现 - `STM32H743/FML/SBUS.h` - SBUS常量定义 - `BUGFIX_CH8_HYSTERESIS.md` - 之前的迟滞方案(保留) ## 总结 这是一个经典的**误把协议层failsafe值当作业务数据**的案例。1024不是遥控器的真实输入,而是SBUS协议在信号丢失时的特殊返回值,必须在业务层过滤掉。 **关键教训**: 1. 理解协议层的特殊值和failsafe机制 2. 区分"协议有效"(格式正确)和"数据有效"(来自真实输入) 3. 对异常值要追根溯源,不能只看表象 4. 用户的直觉往往是对的——"不可能是模拟量抖动" **感谢用户的坚持和正确判断!**