这一章在干嘛?
前 9 章的所有铺垫——PWM 驱动(5 章)、采集(6 章)、编码器测速(7 章)、PID 算法(8 章)、参数整定(9 章)——在本章第一次拧成一个真正的闭环:你设定目标转速,系统自动把电机「拽」到那个转速。
10.1 速度环 PID 控制原理
原理一句话:把 PID 控制流程里的「控制对象」换成电机转速。设定目标转速 → 与实际转速求偏差 → 偏差送进 PID 三环节 → 输出控制 PWM 占空比 → 占空比改变电机转速,如此循环。
原书图 10.1.1:速度环 PID 控制流程
偏差: →
代码用宏 INCR_LOCT_SELECT 在两种形式间切换:0 = 位置式(本实验采用),1 = 增量式。两者数学上等价,增量式输出的是「占空比的变化量」。
符号的妙用:
目标速度的 正负决定转向 (+300 正转、−300 反转), 绝对值决定转速 。一个 PID 同时管方向和大小,这是编码器测速带来的能力。
10.2 硬件设计与接线
硬件与「编码器测速」实验完全一致,只是程序里多了 PID:
| 资源 | 引脚 | 作用 |
|---|---|---|
| TIM1 PWM | PA8 / PB13(互补) | 驱动 H 桥,8400 级分辨率 |
| SD 刹车 | PF10 | 高电平关断输出 |
| TIM3 编码器 | PC6 / PC7 | A/B 相计数反馈 |
| 串口 1 | PB6 / PB7 | 与 PID 调试助手通信 |
| LED0 / KEY0~2 | PE0 / PE2~PE4 | 指示与按键 |
注意:
PID 控制实验中串口 1 仅用于 PID 数据上传 ,不要再往串口打印其他调试信息,否则会污染波形数据。
10.3 程序设计:六步配置与核心代码
配置步骤:① 配置驱动与编码器定时器(同前)→ ② 初始化串口 1 → ③ 定义 PID 结构体变量 g_speed_pid → ④ pid_init() 清零并装参数 → ⑤ debug_init() 准备上位机 → ⑥ 在 TIM6 更新中断里做 PID 计算。
/* pid.h:位置式参数(本实验实际使用)与结构体 */
#define KP 10.0f /* P 参数 */
#define KI 6.00f /* I 参数 */
#define KD 0.5f /* D 参数 */
#define SMAPLSE_PID_SPEED 50 /* 采样周期 单位 ms */
typedef struct {
__IO float SetPoint; /* 设定目标 */
__IO float ActualValue; /* 期望输出值 */
__IO float SumError; /* 误差累计 */
__IO float Proportion; /* 比例常数 P */
__IO float Integral; /* 积分常数 I */
__IO float Derivative; /* 微分常数 D */
__IO float Error, LastError, PrevError; /* 最近三次偏差 */
} PID_TypeDef;
extern PID_TypeDef g_speed_pid;
/* dcmotor_time.c:TIM6 更新中断(1ms 一次) */
else if (htim->Instance == TIM6) {
int Encode_now = gtim_get_encode(); /* 读编码器累计值 */
speed_computer(Encode_now, 5); /* 每 5ms 算一次速度 */
if (val % SMAPLSE_PID_SPEED == 0) { /* 每 50ms 算一次 PID */
if (g_run_flag) {
g_motor_data.motor_pwm = increment_pid_ctrl(&g_speed_pid,
g_motor_data.speed);
if (g_motor_data.motor_pwm >= 8200) /* 输出限幅 */
g_motor_data.motor_pwm = 8200;
else if (g_motor_data.motor_pwm <= -8200)
g_motor_data.motor_pwm = -8200;
}
motor_pwm_set(g_motor_data.motor_pwm); /* 设置占空比 */
}
val++;
}
两个节拍:
测速 5ms 一次(快)、PID 50ms 一次(慢)。采样周期太短 PID 频繁动作易振荡,太长则响应迟钝——50ms 是这个系统的甜点值。限幅 ±8200 是因为 PWM 周期为 8400,输出不能超过比较值范围。
10.4 下载验证与波形解读
按键:KEY0 目标速度 +30 RPM(上限 300),KEY1 −30 RPM,KEY2 停机并重置 PID。打开正点原子 PID 调试助手(如 COM7),勾选通道 1、2 点「开始」:
原书图 10.4.1:速度环 PID 控制波形:橙线为目标速度,红线为实际速度逐渐逼近
- 橙线先动(目标变了),红线慢慢跟上——这就是闭环在「拽」电机;
- 波形不动?先检查电机 M+/M− 有没有接反;
- PID 系数不是通用值,你的系统载荷、摩擦不同,需要按第 9 章的方法重新整定。
1. 速度环实验中,测速和 PID 各是多少毫秒执行一次?为什么分开?
测速每 5ms 一次、PID 每 50ms 一次(宏 SMAPLSE_PID_SPEED)。测速要快才能跟上变化;PID 周期要适中,太短易振荡、太长响应慢。
2. PID 输出为什么限幅在 ±8200?
PWM 计数周期为 8400(atim_timx_cplm_pwm_init(8400-1, 0)),比较值不能超出范围;8200 留了少量裕量,防止占空比超限失控。
3. 目标速度的正负号有什么含义?
正负决定电机正/反转,绝对值决定转速大小。本实验按键步进 30RPM,限速范围 ±300RPM。