这一章在干嘛?

前 9 章的所有铺垫——PWM 驱动(5 章)、采集(6 章)、编码器测速(7 章)、PID 算法(8 章)、参数整定(9 章)——在本章第一次拧成一个真正的闭环:你设定目标转速,系统自动把电机「拽」到那个转速。

10.1 速度环 PID 控制原理

10.2 硬件设计与接线

10.3 程序设计:六步配置与核心代码

10.4 下载验证与波形解读

10.1 速度环 PID 控制原理

原理一句话:把 PID 控制流程里的「控制对象」换成电机转速。设定目标转速 → 与实际转速求偏差 → 偏差送进 PID 三环节 → 输出控制 PWM 占空比 → 占空比改变电机转速,如此循环。

原书图 10.1.1 原书图 10.1.1:速度环 PID 控制流程

偏差:

代码用宏 INCR_LOCT_SELECT 在两种形式间切换:0 = 位置式(本实验采用),1 = 增量式。两者数学上等价,增量式输出的是「占空比的变化量」。

符号的妙用:

目标速度的 正负决定转向 (+300 正转、−300 反转), 绝对值决定转速 。一个 PID 同时管方向和大小,这是编码器测速带来的能力。

10.2 硬件设计与接线

硬件与「编码器测速」实验完全一致,只是程序里多了 PID:

资源引脚作用
TIM1 PWMPA8 / PB13(互补)驱动 H 桥,8400 级分辨率
SD 刹车PF10高电平关断输出
TIM3 编码器PC6 / PC7A/B 相计数反馈
串口 1PB6 / PB7与 PID 调试助手通信
LED0 / KEY0~2PE0 / 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 原书图 10.4.1:速度环 PID 控制波形:橙线为目标速度,红线为实际速度逐渐逼近

  • 橙线先动(目标变了),红线慢慢跟上——这就是闭环在「拽」电机;
  • 波形不动?先检查电机 M+/M− 有没有接反;
  • PID 系数不是通用值,你的系统载荷、摩擦不同,需要按第 9 章的方法重新整定。