不要用超时保护开环步进电机

Babel36acl 嵌入式实战 无~ 7 次阅读 预计阅读时间: 7 分钟 发布于 1 天前 最后更新于 2 小时前 1516 字


不要用超时保护开环步进电机

> 脉冲溢出才是唯一可靠的硬保护——一段真实事故分析

## 一个看起来合理的保护

```
PRESS_OPEN: 轴2回 IN1 限位
1. 启动脉冲(连续模式,target_pulses=0)
2. 等待 IN1 触发
3. 10 秒超时 → 报警
```

这看起来天经地义。轴跑 10 秒还没碰到传感器?肯定出问题了,报警。

但这是错的。

## 开环步进的两个自我保护逻辑

开环步进轴(无限位开关、无原点传感器)只有两种停止条件:

1. **有限脉冲完成** — ISR 正常计步,到达目标脉冲数后自动停
2. **脉冲溢出** — 实际脉冲超出目标 + 保护余量,触发硬停止 + 报警

超时保护不在这张表里。原因很微妙:**超时信号和脉冲是同一个 ISR 产生的**。

如果 ISR 正常运转 → 脉冲计数正常 → 有限脉冲会先于超时结束
如果 ISR 挂了 → 脉冲不走了 → 超时也走不准

所以超时对于纯开环轴,本质上是靠不住的。

## 真实事故现场

在我们的四轴步进系统中,轴 1 负责出袋(BAG_OUT ≈ 50611 脉冲),轴 3/4 负责压口闭合(PRESS_CLOSE ≈ 3333 脉冲)。

轴 2 PRESS_RETRACT 的脉冲数计算有误差,实际需要的脉冲比配置值多。ISR 正常计步,但永远到不了 done。系统没有脉冲溢出保护,靠一个 10 秒超时兜底。

结果:超时触发→报警→停机。但是 ISR 明明没问题,脉冲一直在走。超时成了唯一的故障检测手段,而它触发的时候机械已经跑到不可预测的位置了。

## 正确的保护策略

### 开环轴(无传感器反馈)

```
唯一硬保护:脉冲溢出
目标脉冲 + 10000 脉冲(APP_CFG_STEPPER_PULSE_OVERFLOW_MARGIN)
超限 → 立即停轴 → APP_ALARM_STEPPER_PULSE_OVERFLOW

超时在此场景无意义,不加。
```

### 有传感器反馈的轴

```
第一道保护:传感器触发(IN1/IN2 限位)
第二道保护:脉冲溢出(传感器失灵时兜底)
辅助保护:超时(可保留,但仅作辅助)
```

### 轴 2 回 IN1 的特殊口径

```
轴 2 回位 → 连续模式(target_pulses=0)
→ IN1 触发即为成功
→ 脉冲溢出保护 = 20000 脉冲(IN1 失灵时防卡死)
→ 超时 10s 保留,仅作为 IN1 + 脉冲溢出双双失灵的最后兜底
```

## 反模式:隐式补丁

最危险的写法是在"快到了"时动手脚:

```c
// ❌ 反模式:剩余 2000 脉冲提前斩杀
if (remaining_pulses <= 2000) { bsp_stepper_stop(); } ``` 这个 2000 是哪里来的?为什么不是 1500 或 2500?下一个人看这段代码,不敢删,不敢改,只能往上叠加新的 magic number。 正确做法:用显式的 `finite_stop_mode_t` 字段建模。 ```c typedef enum { FINITE_STOP_TARGET, // 到目标脉冲停 FINITE_STOP_OVERFLOW, // 脉冲溢出停 FINITE_STOP_CONTINUOUS // 连续模式,外部触发停 } stop_mode_t; ``` 每个阶段的停止策略清晰声明,不依赖隐式阈值。 ## 总结 给开环步进轴加超时保护,就像给断了刹车线的车装喇叭——发声没问题,但停不下来。 真正可靠的保护链:**脉冲计步 ISR 正常 → 有限脉冲 done;ISR 异常 → 脉冲溢出报警**。没有第三条路。

此作者没有提供个人介绍。
最后更新于 2026-05-30