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

CH8通道抖动导致状态机重复重置问题修复

问题描述

实车测试时,车辆在原点和第二个路径点之间反复切换,无法正常完成路径跟踪。Log显示状态机反复从follow_path回到goto_start

根本原因

CH8通道(自动模式开关)剧烈抖动,在1024和1800之间反复跳变。

从log分析(python/hitl/runlog.txt):

[HOST=1764923751.607s] CH8 crossed threshold: 1800 -> 1024
[HOST=1764923751.686s] *** Auto mode triggered! Resetting to GOTO_START ***
[HOST=1764923751.688s] CH8 crossed threshold: 1024 -> 1800
[HOST=1764923752.166s] CH8 crossed threshold: 1800 -> 1024
[HOST=1764923752.387s] *** Auto mode triggered! Resetting to GOTO_START ***
[HOST=1764923752.389s] CH8 crossed threshold: 1024 -> 1800

每次CH8跨越阈值1500时,都会触发自动模式的开关,导致状态机被MC_Init重新初始化到GOTO_START

触发频率

在短短10秒内,CH8跨越阈值触发了**50+次**"Auto mode triggered",导致:
- 车辆无法完成路径跟踪
- 目标点在原点和第二个路径点之间反复切换
- 状态机不断被重置

解决方案:CH8迟滞(Hysteresis)

原理

使用**施密特触发器**原理,为CH8设置两个阈值:

手动模式状态:
  - 保持手动,直到 CH8 > 1600 (高阈值)
  - 当 CH8 > 1600 时 → 切换到自动模式

自动模式状态:
  - 保持自动,直到 CH8 < 1400 (低阈值)
  - 当 CH8 < 1400 时 → 切换到手动模式

死区(1400-1600):
  - 在此区间内,保持之前的状态不变
  - 避免在阈值附近抖动时反复切换

实现代码

文件:STM32H743/APL/motion_control_task.c

static HIDO_BOOL s_ch8_auto_state = HIDO_FALSE;  /* CH8迟滞状态 */

/* CH8迟滞阈值定义 */
#define CH8_THRESHOLD_ENTER  1600  // 进入自动模式的阈值
#define CH8_THRESHOLD_EXIT   1400  // 退出自动模式的阈值

if (s_ch8_auto_state == HIDO_FALSE)
{
    /* 当前在手动模式,检查是否应该进入自动模式 */
    if (ch8 > CH8_THRESHOLD_ENTER)
    {
        s_ch8_auto_state = HIDO_TRUE;
    }
}
else
{
    /* 当前在自动模式,检查是否应该退出自动模式 */
    if (ch8 < CH8_THRESHOLD_EXIT)
    {
        s_ch8_auto_state = HIDO_FALSE;
    }
}

/* 使用迟滞状态而不是直接使用CH8值 */
HIDO_BOOL current_auto_condition = (sbus_valid == HIDO_TRUE && 
                                   s_ch8_auto_state == HIDO_TRUE && 
                                   gps_ready == HIDO_TRUE);

优化后的日志输出

修改前:
[MC_CTRL] CH8 crossed threshold: 1800 -> 1024 (threshold=1500) [MC_CTRL] CH8 crossed threshold: 1024 -> 1800 (threshold=1500) ... (每次跨越1500都记录,输出大量重复信息)

修改后:
[MC_CTRL] CH8 entered MANUAL zone: 1800 -> 1024 (<1400) [MC_CTRL] CH8 entered AUTO zone: 1024 -> 1800 (>1600) ... (只记录真正的状态切换,简洁清晰)

修改内容

1. 添加CH8迟滞逻辑(第219-243行)

  • 定义了s_ch8_auto_state静态变量来保存CH8的迟滞状态
  • 定义了CH8_THRESHOLD_ENTER(1600)和CH8_THRESHOLD_EXIT(1400)
  • 实现了施密特触发器逻辑

2. 修改自动模式条件判断(第245行)

  • 从:ch8 > MOTION_SBUS_AUTO_THRESHOLD_US (1500)
  • 改为:s_ch8_auto_state == HIDO_TRUE(使用迟滞状态)

3. 优化日志输出(第272-287行)

  • 只记录CH8状态真正改变的情况(跨越迟滞边界)
  • 减少了日志噪音,便于调试

4. 增强触发日志(第251-254行)

  • 在"Auto mode triggered"时,额外输出CH8迟滞状态的变化
  • 便于确认迟滞逻辑是否正常工作

预期效果

修复前

  • CH8在1024和1800之间跳动
  • 每次跨越1500都触发重新初始化
  • 短时间内触发50+次
  • 车辆无法完成路径跟踪

修复后

  • CH8必须超过1600才能进入自动模式
  • CH8必须低于1400才能退出自动模式
  • 在1400-1600区间内,状态保持稳定
  • 即使CH8在此区间抖动,也不会触发重新初始化
  • 车辆能正常完成路径跟踪

测试验证

  1. 编译并烧录最新代码
  2. 测试场景1:正常切换
  • 手动模式(CH8=1000)
  • 推高遥控器拨杆,CH8上升到1700 → 应该只触发一次"Auto mode triggered"
  • 车辆开始自动运行
  1. 测试场景2:抖动测试
  • 将遥控器拨杆置于1500附近(死区内)
  • 轻微抖动,CH8在1400-1600之间波动
  • 应该**不会**触发"Auto mode triggered"
  • 状态保持稳定
  1. 测试场景3:退出自动模式
  • 自动模式运行中(CH8=1800)
  • 拉低遥控器拨杆,CH8下降到1300 → 应该切换到手动模式
  • 状态机保持当前状态(不重新初始化)

技术细节

为什么选择1600/1400?

  • 原阈值1500:CH8在此附近抖动最剧烈
  • 死区200:根据log观察,CH8抖动幅度约±100-300
  • 1600/1400:提供足够的死区,避免误触发

迟滞的优势

  1. 抗干扰:对EMI、ADC噪声、机械抖动不敏感
  2. 稳定性:一旦进入某个状态,需要明确的操作才能退出
  3. 用户体验:避免在临界点附近的不确定行为

适用场景

迟滞逻辑特别适用于:
- 模拟开关输入(如PWM通道)
- 温度控制(恒温器)
- 电池电量检测
- 任何需要避免在阈值附近反复切换的场景

相关文件

  • STM32H743/APL/motion_control_task.c - 主要修改
  • BUGFIX_HEADING_CONTROL.md - 之前修复的航向控制问题
  • DEBUG_GOTO_START_LOOP.md - 问题诊断文档

总结

通过为CH8通道添加迟滞逻辑,彻底解决了因通道抖动导致的状态机反复重置问题。这是一个经典的**去抖动(Debouncing)**应用案例,使用施密特触发器原理提高了系统的稳定性和鲁棒性。

关键教训:对于任何模拟开关输入,特别是可能在阈值附近抖动的信号,都应该考虑添加迟滞或时间延迟来提高稳定性。