开环的隐含假设是「脉冲数 = 转角,永远成立」。现实中机械老化、突加较大负载、快速启停都会打破它——定子磁场跑太快,转子跟不上,就是失步;负载太大拖不动,就是堵转。控制器发出去的脉冲管不了实际转角,高精度场合不能忍。

| 方案 | 优点 | 缺点 |
|---|---|---|
| 开环 | 价格低、控制简单 | 无反馈不能纠偏、可靠性低 |
| 闭环(电机+编码器+PID) | 精度高、消除位置误差、噪音明显降低 | 价格贵、控制复杂 |
结构就是第 12 章的位置环换了个执行器:编码器反馈实际位置 → 与目标求偏差 → PID → 输出「期望脉冲速度」作用于步进电机。关键换算参数:
| 宏 | 值 | 含义 |
|---|---|---|
| PULSE_REV | 1600 | 步进电机每圈脉冲数(8 细分) |
| ENCODER_SPR | 2400 | 编码器每圈计数:600 线 × 4 倍频 |
| MPR | 5 | 丝杠导程 5mm/r |
| PPM | 480 | 2400/5 = 每毫米编码器脉冲数 |
| FEEDBACK_CONST | 1600/2400 | 编码器脉冲 → 步进脉冲的换算比值 |
PID 参数 L_KP=0.5、L_KI=0.05、L_KD=0,采样周期 20ms(TIM6);积分限幅 ±20、输出限幅 ±150。PID 输出的是「编码器脉冲期望值」,经 FEEDBACK_CONST 换算成步进脉冲数,再算每个脉冲的时间:
/* TIM6 更新中断(20ms 一次) */
if (g_run_flag) {
g_step_motor.location = gtim_get_encode(); /* 读编码器实际位置 */
g_motor_pwm = increment_pid_ctrl(&g_location_pid,
g_step_motor.location);
(g_motor_pwm > 0) ? (g_step_motor.dir = CW) : (g_step_motor.dir = CCW);
g_motor_pwm = abs(g_motor_pwm); /* 方向由符号决定 */
stepper_motion_ctrl(g_step_motor.dir, g_motor_pwm); /* 作用于电机 */
}实验:接口三驱动步进电机(TIM8_CH3=PI7),编码器接 TIM3(PC6/PC7),驱动器 8 细分、12~50V 供电。KEY0 启动/停止,KEY1 目标 +20×PPM(上限 60×PPM),KEY2 −20×PPM,初始目标 50×PPM(约 50mm)。可用 PID 调试助手在线整定并看波形:按 KEY0 后电机平稳转到目标位置,曲线近似斜线。