共计 1690 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点:为什么需要 PID 控制
刚接触电机控制时,很多人会直接用 PWM 信号驱动电机,但很快会发现两个问题:

- 负载变化时转速波动明显(比如机械臂关节受力时速度下降)
- 相同占空比下转速受电压波动影响(电池电量下降时跑得慢)
这就是开环控制的缺陷——系统无法感知实际输出状态。520 编码器通过正交信号反馈电机真实转速(每转输出 520 个脉冲),为闭环控制提供了数据基础。
算法选型:位置式 PID vs 增量式 PID
两种 PID 实现方式的对比:
- 位置式 PID(本文采用方案)
- 直接计算目标控制量(如 PWM 占空比)
- 代码直观易理解
-
需处理积分饱和问题
-
增量式 PID
- 计算控制量的变化值
- 对电机冲击小
- 需额外做累加运算
初学者建议从位置式入手,更容易观察各参数影响。
核心实现:Arduino 代码框架
硬件连接示例
#include <Encoder.h>
// 编码器接在 2,3 号引脚(支持中断)Encoder myEnc(2, 3);
// 电机驱动使用 5 号 PWM 引脚
const int motorPWM = 5;
抗饱和 PID 算法实现
// PID 参数
float Kp=0, Ki=0, Kd=0;
int targetRPM = 0;
void updatePID() {
static long lastPos = 0;
static unsigned long lastTime = 0;
static float integral = 0;
// 1. 获取当前状态
long currPos = myEnc.read();
unsigned long currTime = millis();
float deltaT = (currTime - lastTime) / 1000.0; // 转为秒
// 2. 计算误差项
float error = targetRPM - getActualRPM(currPos, lastPos, deltaT);
// 3. 积分项限幅(防饱和)integral += error * deltaT;
if(integral > 100) integral = 100; // 根据实际调整
else if(integral < -100) integral = -100;
// 4. 计算 PID 输出
float output = Kp*error + Ki*integral + Kd*(error-lastError)/deltaT;
output = constrain(output, -255, 255); // PWM 范围限制
// 5. 更新状态
analogWrite(motorPWM, abs(output));
lastPos = currPos;
lastTime = currTime;
lastError = error;
}
实测波形对比(建议用串口绘图器观察)
- 纯比例控制 (P)
- 响应快但存在稳态误差
-
像开车时永远差 10 米到目标位置
-
比例积分控制 (PI)
- 消除稳态误差
-
可能出现超调(像刹车太猛冲过停车线)
-
完整 PID 控制
- 微分项抑制超调
- 系统稳定时间缩短
调参方法论:从菜鸟到老手
临界比例法整定步骤
- 先将 Ki、Kd 设为 0
- 逐渐增大 Kp 直到系统持续震荡
- 记录此时的临界增益 Ku 和震荡周期 Tu
- 根据 Ziegler-Nichols 公式:
- Kp = 0.6*Ku
- Ki = 1.2*Ku/Tu
- Kd = 0.075KuTu
响应优化技巧
- 减小超调 :适当降低 Kp 或增大 Kd
- 加快响应 :增大 Kp 但需配合积分限幅
- 推荐稳态误差控制在±2RPM 内
避坑指南:血泪经验总结
电机堵转保护
当编码器值长时间不变化时:
- 立即清零积分项
- 触发报警或降低 PWM 输出
- 添加电流检测更可靠
编码器消抖处理
硬件方案:
– 在信号线对地加 0.1μF 电容
软件方案:
// 在中断服务函数中
if(micros() - lastInterruptTime > 200) { // 200μs 消抖
// 处理计数
}
时序匹配原则
- 采样周期建议为电机机械时间常数的 1 /10~1/20
- 对于普通直流电机,通常取 10-50ms
- PWM 频率建议 8kHz 以上(避免可闻噪音)
进阶建议:下一步优化方向
当基本 PID 满足需求后,可以尝试:
- 前馈控制 :根据负载变化预先调整输出
- 模糊 PID:自动调节参数适应不同工况
- 离线参数整定 :通过 MATLAB 等工具仿真
最后提醒:PID 调参需要耐心,建议每次只调整一个参数并做好记录。遇到问题时,回退到上一个稳定状态再重新分析。
正文完
