这一章在干嘛?
把 PID 的控制对象从「转速」换成「电流」。难点不在 PID(第 8 章早写好了),而在 电流怎么测得准 ——采样电阻上的电压小到毫伏级,本章的三级滤波就是为它定制的。
11.1 电流环 PID 控制原理
物理直觉:对直流电机,转矩 ∝ 电流。控住电流就等于控住「电机的力气」,这是后续三环控制里最内环的基石。
原书图 11.1.1:电流环 PID 控制流程:目标电流与实际电流求偏差,PID 输出占空比
其中 是电流通道滤波后的当前均值, 是**上电时(电机未转)**测得的零点参考值,ADC2CURT 是「ADC 数值 → 电流(mA)」的换算系数。先减零点再乘系数,电流才算得干净。
11.2 电流采集与三级滤波
采集链路:20mΩ 采样电阻 → 差分放大 6 倍 + 1.27V 偏置(第 6 章的电路)→ ADC1 通道 8(PB0)→ DMA 循环搬运。程序里做了三级平均 + 两道整形:
| 层级 | 做法 | 目的 |
|---|---|---|
| 一级 | 单次多通道采样取平均 | 去单点毛刺 |
| 二级 | 累计 15 次再平均 | 压随机噪声 |
| 三级 | 上电累计 16 次平均 → 存为零点参考 | 标定 ADC 零点 |
/* 采完参考值后,每轮计算一次电流 */
temp_c = (add_adc - init_adc_value) * ADC2CURT; /* 换算电流 */
/* 一阶低通:60% 旧值 + 40% 新值,波形更平滑 */
g_motor_data.current = g_motor_data.current * 0.60f + 0.40f * temp_c;
if (g_motor_data.current <= 20) /* ≤20mA 视为微弱浮动 */
g_motor_data.current = 0.0; /* 直接清零 */
为什么上电先测参考值?
放大电路自带 1.27V 偏置,还可能有失调。电机停转时电流应为 0,此刻的 ADC 读数就是「零点」,运行时减去它才得到真实的电流增量。
11.3 程序设计:参数与单向限幅
电流环参数:位置式 KP=10.0、KI=7.0、KD=2.0(增量式 0.0/6.0/4.0),采样周期 50ms,结构体 g_current_pid。初始目标电流设为 40mA——太小了电机根本转不起来。
/* TIM6 更新中断:50ms 算一次电流环 PID */
if (val % SMAPLSE_PID_SPEED == 0) {
if (g_run_flag) {
motor_pwm_temp = increment_pid_ctrl(&g_current_pid,
g_motor_data.current);
/* PID 输出再做一次低通(0.5/0.5),占空比不突变 */
g_motor_data.motor_pwm = (int32_t)((g_motor_data.motor_pwm * 0.5)
+ (motor_pwm_temp * 0.5));
if (g_motor_data.motor_pwm >= 8200) /* 上限 */
g_motor_data.motor_pwm = 8200;
else if (g_motor_data.motor_pwm <= 0) /* 下限是 0,不是 -8200 */
g_motor_data.motor_pwm = 0;
motor_pwm_set(g_motor_data.motor_pwm);
}
val = 0;
}
val++;
而不是 ±8200?
电流环只管「用力多少」(占空比大小), 不管方向 ——转向由后续三环里的方向信号单独控制。所以输出只需要单向。
11.4 下载验证
按键:KEY0 目标电流 +20mA(上限 120mA),KEY1 −20mA(小于 60mA 自动停机并重置 PID),KEY2 立即停机。
原书图 11.4.1:电流环 PID 控制波形:红线(实际电流)逐渐逼近橙线(目标电流)
实验经验:
① 上电/复位后等约 3 秒再启动电机(让零点参考值稳定);② 电流波形小幅振荡属正常,可调 PID 系数或增大滤波次数,但 滤波越多响应越慢 ,要在稳定与灵敏之间找平衡;③ 曲线乱成一团且调参数无效时,优先怀疑滤波不够。
1. 写出电流换算公式,并说明为什么要减去 init_adc_value。
。init_adc_value 是上电停转时 16 次平均的零点参考值,减去它才能去掉放大电路偏置与失调,得到真实电流增量。
2. 电流采集一共做了几级滤波?
三级平均(单次多通道平均、15 次累计平均、16 次参考值平均)加一阶低通(0.6 旧值 + 0.4 新值),最后 ≤20mA 直接清零。
?
电流无方向语义,电流环只控制占空比大小、不决定转向(转向由方向信号单独管),所以输出只需单向 0~8200。