编辑 | blame | 历史 | 原始文档

SBUS信号不稳定导致状态机反复重置 - 最终修复

问题持续存在

即使过滤了1024 failsafe值,问题依然存在。从最新log分析:

[MC_CTRL] CH8 entered MANUAL zone: 1800 -> 120 (<1400)
[MC_CTRL] *** Auto mode triggered! Resetting to GOTO_START ***
[MC_CTRL] CH8 entered AUTO zone: 120 -> 1800 (>1600)
[MC_CTRL] *** Stage transition: goto_start -> idle ***

[MC_CTRL] CH8 recovered from failsafe (1024), count=6, new value=1953

[MC_CTRL] SBUS valid changed: 1 -> 0
[MC_CTRL] SBUS valid changed: 0 -> 1

根本原因分析

SBUS信号质量极差,频繁丢失和恢复,导致:

  1. CH8值在多个异常值之间跳动:120、1024、1953、1800
  2. SBUS valid状态频繁切换:信号有效→丢失→恢复
  3. 每次恢复都触发"Auto mode triggered":导致状态机重置到GOTO_START

为什么1024不是唯一的failsafe值?

  • 1024:SBUS_CENTER_VALUE,信号丢失时的标准返回值
  • 120、1953等:信号恢复瞬间或干扰时的异常读数
  • 有效范围:SBUS协议定义为172-1811(对应PWM 1000-2000)

最终修复方案

修复1:扩展CH8异常值过滤

不仅过滤1024,过滤所有不在有效范围内的值:

/* 判断是否为有效SBUS值:172-1811范围内,且不是精确的1024 */
HIDO_BOOL is_valid = (ch8_raw >= 172 && ch8_raw <= 1811 && ch8_raw != 1024);

if (is_valid)
{
    ch8 = ch8_raw;  /* 只更新有效值 */
}
else
{
    /* 异常值,保持之前的值 */
    DBG_Printf("[MC_CTRL] CH8 failsafe detected (%u), keeping previous value=%u\r\n", 
               ch8_raw, ch8);
}

过滤范围:
- <172:低于SBUS最小值(如120)
- =1024:SBUS中心值(failsafe默认)
- >1811:高于SBUS最大值(如1953)

修复2:只在IDLE/FINISHED状态允许重新初始化

核心理念:正在执行任务时,忽略模式切换抖动

if (s_last_auto_condition == HIDO_FALSE && current_auto_condition == HIDO_TRUE)
{
    E_MCStage current_stage = g_motion_state.stage;
    
    if (current_stage == MC_STAGE_IDLE || current_stage == MC_STAGE_FINISHED)
    {
        /* 只有空闲或完成时才允许重新初始化 */
        MC_Init(&g_motion_state, &g_motion_config, g_motion_path_xy, g_motion_path_point_count);
    }
    else
    {
        /* 正在执行任务,忽略此次模式切换(可能是信号抖动) */
        DBG_Printf("[MC_CTRL] WARNING: Auto mode re-triggered during %d, ignoring (SBUS interference)\r\n", 
                   current_stage);
    }
}

逻辑:
- IDLE/FINISHED状态:允许重新初始化(用户真正想重新开始)
- GOTO_START/FOLLOW_PATH状态:忽略模式切换(认为是信号干扰)

为什么之前的修复不够?

迟滞方案(保留)

  • 目的:防止阈值附近的模拟量抖动
  • 局限:无法防止120→1800这种大幅跳变

1024过滤方案(已扩展)

  • 目的:过滤SBUS failsafe返回值
  • 局限:只过滤了1024,没有覆盖其他异常值(120、1953)

本次最终方案

  • 范围过滤:覆盖所有SBUS有效范围之外的值
  • 状态保护:只有在安全状态下才允许重新初始化

三层防护体系

第一层:CH8异常值过滤

if (ch8_raw < 172 || ch8_raw > 1811 || ch8_raw == 1024)
    → 忽略,保持last-known-good值

第二层:CH8迟滞

进入自动:CH8 > 1600
退出自动:CH8 < 1400
死区:1400-1600

第三层:状态保护

if (正在执行任务 && 检测到模式切换)
    → 忽略,认为是干扰

日志输出示例

检测到异常值

[MC_CTRL] CH8 failsafe detected (120), keeping previous value=1800
[MC_CTRL] CH8 failsafe detected (1953), keeping previous value=1800

信号恢复

[MC_CTRL] CH8 recovered from failsafe, count=56, new value=1800

忽略干扰

[MC_CTRL] WARNING: Auto mode re-triggered during 2, ignoring (SBUS interference)

根本解决方案(硬件)

软件修复只是workaround,真正需要:

立即检查:

  1. SBUS接收机天线:检查方向、连接、损坏
  2. 遥控器距离:测试时保持在可靠距离内
  3. 电磁干扰源
  • 电机/电调的EMI
  • GPS模块的干扰
  • 其他无线设备

长期优化:

  1. 使用高质量SBUS接收机:带failsafe hold功能
  2. 双接收机冗余:A/B接收机切换
  3. 信号强度监控:低于阈值时报警
  4. 备用控制模式:SBUS失效时切换到其他输入源

测试验证

场景1:正常启动

  1. 手动模式(CH8=1000)
  2. 推高遥控器拨杆到1800
  3. 预期:触发一次"Auto mode triggered",车辆开始运行

场景2:运行中信号抖动

  1. 自动模式运行中
  2. SBUS信号短暂丢失和恢复
  3. 预期
  • 看到"CH8 failsafe detected"
  • 看到"CH8 recovered from failsafe"
  • 不应该看到"Auto mode triggered"
  • 车辆继续当前任务,不重新初始化

场景3:运行中手动干预

  1. 自动模式运行中
  2. 遥控器拨杆拉低到手动模式
  3. 车辆停止自动控制
  4. 拨杆推回自动模式
  5. 预期:如果还在FOLLOW_PATH,忽略切换;如果已经FINISHED,允许重新初始化

修改文件

  • STM32H743/APL/motion_control_task.c - 扩展异常值过滤,添加状态保护

相关文档

  • BUGFIX_HEADING_CONTROL.md - 航向控制方向修复
  • BUGFIX_CH8_HYSTERESIS.md - CH8迟滞方案
  • BUGFIX_CH8_FAILSAFE_1024.md - 1024 failsafe过滤
  • DEBUG_GOTO_START_LOOP.md - 问题诊断过程

总结

这是一个**层层深入、逐步完善**的bug修复过程:

  1. 表象:车辆在原点和路径点之间来回
  2. 第一次分析:以为是模拟量抖动 → 添加迟滞
  3. 第二次分析:发现是1024 failsafe → 过滤1024
  4. 第三次分析:发现还有其他异常值(120、1953)→ 扩展过滤范围
  5. 最终方案:添加状态保护,防止任务执行中被重新初始化

关键教训:
- 复杂的问题往往需要多层防护
- 不要假设只有一个根本原因
- SBUS信号质量问题必须从硬件层面根本解决
- 软件要robust,能应对各种异常情况

本次修复应该能彻底解决状态机重复重置的问题!