电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
电机控制进阶——PID速度控制
分 享
扫描二维码分享
电机控制进阶——PID速度控制
电机
PID
速度控制
码农爱学习
关注
发布时间: 2021-05-20
丨
阅读: 986
之前的几篇文章(电机控制基础篇),介绍的电机编码器原理、定时器输出PWM、定时器编码器模式测速等。 本篇在前几篇的基础上,继续来学习电机控制,通过PID算法,来进行电机的速度控制,并进行实验测试。 # PID基础 PID即:Proportional(比例)、Integral(积分)、Differential(微分)的缩写。 PID是经典的闭环控制算法,具有原理简单,易于实现,适用面广,控制参数相互独立,参数的选定比较简单等优点。 凡是需要将某一个物理量“保持稳定”的场合(比如维持平衡,稳定温度、转速等),PID都会派上大用场。 ![](https://cf01.ickimg.com/bbsimages/202105/1ea8bd61ef39b3abe5c4d50d9ccf57f3.png) ## PID算法分类 PID算法可分为位置式PID与增量式PID两大类。 在实际的编程应用中,需要使用离散化的PID算法,以适用计算机的使用环境,下面以电机转速控制为例,来看一下两种PID算法的基本原理。 ### 位置式PID 位置式PID是当前系统的实际位置,与想要达到的预期位置的偏差,进行PID控制 ![](https://cf01.ickimg.com/bbsimages/202105/1537b2c6408806374eab4b8df502b09c.png) - 比例P:e(k) 此次误差 - 积分I:∑e(i) 误差的累加 - 微分D:e(k) - e(k-1) 此次误差-上次误差 因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系。 **位置式PID算法的伪代码如下**: ```c //位置式PID(伪代码) previous_err = 0; integral = 0; loop: //根据目标值与测量值(如电机的设定速度与读到的编码器转后后的速度),循环计算更新输出值(如PWM) error = setpoint - measured_value; /@@*误差项:目标值-测量值*/ integral += error * dt; /@@*积分项:误差项的累计*/ derivative = (error - previous_error) / dt; /@@*微分项:误差的变化率*/ output = Kp*error + Ki*integral + Kd*derivative; /@@*三项分别乘以PID系数即为输出*/ previous_err = err; //更新误差 wait(dt); //等待固定的计算周期 goto loop; ``` ### 增量式PID ![](https://cf01.ickimg.com/bbsimages/202105/029dfbbb9ce18bceac3decd0180a5718.png) - 比例P:e(k) - e(k-1) 此次误差-上次误差 - 积分I:e(k) 此次误差d - 微分D:e(k) - 2e(k-1)+e(k-2) 这次误差-2×上次误差+上上次误差 注意增量式PID首先计算的是Δu(k),然后与上次的输出相加,才是此次的输出结果。增量式PID没有误差累加,控制增量Δu(k)的确定仅与最近3次的采样值有关。 **增量式PID算法的伪代码如下**: ```c //增量式PID(伪代码) previous02_error = 0; //上上次偏差 previous01_error = 0; //上次偏差 integral = 0; //积分和 pid_out = 0; //pid增量累加和 loop: error = setpoint − measured_value; /@@*误差项:目标值-测量值*/ proportion = error - previous01_error; /@@*比例项:误差项-上次偏差*/ integral = error * dt; /@@*积分项:误差项的累计*/ derivative = (error − 2*previous01_error + previous02_error) / dt;/@@*微分项:上次误差与上上次误差的变化率*/ /@@*或写成:derivative = ( (error − previous01_error)/dt - (previous01_error - previous02_error)/dt )*/ pid_delta = Kp × error + Ki × integral + Kd × derivative; //计算得到PID增量 pid_out = pid_out + pid_delta; //计算最终的PID输出 previous02_error = previous01_error; //更新上上次偏差 previous01_error = error; //更新上次偏差 wait(dt); //等待固定的计算周期 goto loop; ``` ## PID各项的作用 以这个弹簧为例(假设没有重力,只有空气阻力),先是在**平衡位置上(目标位置)**,拉它一下,然后松手,这时它会震荡起来。 ![](https://cf01.ickimg.com/bbsimages/202105/e11fdcd0058ba1955a7e5a017bff5d98.gif) ### P 比例 **P就是比例**的意思。这里就类比弹簧的弹力(回复力):`F=k*Δx` - 当物块距离平衡位置越远时,弹力越大,反之,离平衡位置越近,力越小。 - 当物块位于平衡位置上方时,弹性向下,当物块位于平衡位置下方时,弹性向上,即弹力总是使物块朝平衡位置施力。 ### D 微分/求导/变化率 只有P控制,物块一直在上下震荡,整个系统不是特别稳定。 这是因为空气阻力太小,想象一下整个把它放到水里,物块应该很快会静止下来。这时因为**阻力**的作用。 **D的作用就相当于阻力**: - 它与变化速度(单位时间内的变化量)有关,变化的越大,它施加的阻力也就越大 - 它的方向与目标值无关,比如,*当物块从下到上经过平衡位置时*,它的方向一直是朝下, 即先是阻止物块靠近平衡位置,再是阻止物块远离平衡位置(对比P的作用,始终阻止物块远离平衡位置) - 它的作用就是减小系统的超调量了(减少系统在平衡位置震荡) ### I 积分/误差累积 有了P的动力和D的阻力,这个物块就可以较快的稳定下来了,那I的作用是什么呢? 想象一下,如果有其它外力的影响,在某一时刻,物块将要到达平衡位置时,恰好P的动力与外力(与P的作用方向相反的恒定力)抵消,则之后物块将停在此处附近(因为此时D的力也趋近0,并很快变为0),一直到达不了平衡位置。 这时,**I的误差积分**作用就很有必要了: - 它计算的误差的累计,只要有误差,它就一直增加,开始可能很小,但只要没要到达平衡位置,该值就会越来越大 - 它的作用就是消除系统的静态误差了 ## PID参数整定 实际应用,进行PID参数调节时,一般使用试凑法,PID参数整定口诀如下: > 参数整定找最佳,从小到大顺序查, > > **先是比例后积分,最后再把微分加**, > > 曲线振荡很频繁,**比例**度盘要放大, > > 曲线漂浮绕大湾,**比例**度盘往小扳, > > 曲线偏离回复慢,**积分**时间往下降, > > 曲线波动周期长,**积分**时间再加长, > > 曲线振荡频率快,先把**微分**降下来, > > 动差大来波动慢,**微分**时间应加长, > > 理想曲线两个波,前高后低4比1, > > 一看二调多分析,调节质量不会低。 # 电机PID速度控制 上面介绍了PID的基础知识,接下来就使用位置式PID来实现对直流电机转速的控制。 ## 程序 ### 自定义PID结构体 ```c typedef struct { float target_val; //目标值 float err; //偏差值 float err_last; //上一个偏差值 float Kp,Ki,Kd; //比例、积分、微分系数 float integral; //积分值 float output_val; //输出值 }PID; ``` ### PID算法实现(位置式PID) ```c float PID_realize(float actual_val) { /@@*计算目标值与实际值的误差*/ pid.err = pid.target_val - actual_val; /@@*积分项*/ pid.integral += pid.err; /@@*PID算法实现*/ pid.output_val = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * (pid.err - pid.err_last); /@@*误差传递*/ pid.err_last = pid.err; /@@*返回当前实际值*/ return pid.output_val; } ``` ### 周期调用PID计算 ```c //周期定时器的回调函数 void AutoReloadCallback() { int sum = 0;/@@*编码器值(PID输入)*/ int res_pwm = 0;/@@*PWM值(PID输出)*/ /@@*读取编码器测量的速度值*/ sum = read_encoder(); /@@*进行PID运算,得到PWM输出值*/ res_pwm = PID_realize(sum); /@@*根据PWM值控制电机转动*/ set_motor_rotate(res_pwm); /@@*给上位机通道1发送实际值*/ set_computer_value(SEND_FACT_CMD, CURVES_CH1, &sum, 1); } ``` ## 上位机 这里使用**野火多功能调试助手**的"PID调试助手“来进行实验,用于显示PID调节时的电机转速曲线。 ![](https://cf01.ickimg.com/bbsimages/202105/bd8a2d262b7c70e42341d7397eb12e1a.png) ## 实验演示 目标速度值设为50(这里的目标值50使用的是编码器10ms捕获的脉冲数),通过体调节PID的参数,来测试电机能否较快的达到目标速度。 ### 先调节P P值先使用10看看效果,从速度曲线可以看出,达不到目标速度,且与目标速度相差较大。 | P | I | D | | ---- | ---- | ---- | | 10 | 0 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/3c29783c50a790588d0aaf3a0bb4f628.png) P值加大到100,从速度曲线可以看出,还是达不到目标速度。 | P | I | D | | ---- | ---- | ---- | | 100 | 0 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/d8b961cfcb709c3a90e6b147156954c5.png) 只使用P,会存在静差,始终达到不了目标值,这时就要使用积分项来消除静差了。 ### 再调节I P保持100,I使用0.2,从速度曲线可以看出,可以达到目标速度,但跟随的速度较慢。 | P | I | D | | ---- | ---- | ---- | | 100 | 0.2 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/dc2756d992b041a45d6f4c4352cbe7ff.png) P保持100,加大I,使用1.0,从速度曲线可以看出,可以达到目标速度,跟随的速度加快了。 | P | I | D | | ---- | ---- | ---- | | 100 | 1.0 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/ca7104670cb6e9e443856f1a4b822d63.png) P保持100,继续加大I,使用3.0,从速度曲线可以看出,可以达到目标速度,跟随的速度进一步加快了。 | P | I | D | | ---- | ---- | ---- | | 100 | 3.0 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/f6e62972a51235d68f74a6ac158a2fce.png) P保持100,再继续加大I,使用6.0,从速度曲线可以看出,可以达到目标速度,跟随速度也很快,但有一点过冲。 | P | I | D | | ---- | ---- | ---- | | 100 | 6.0 | 0 | ![](https://cf01.ickimg.com/bbsimages/202105/338ac641333067dd74d16cff228682e8.png) 对于过冲,可以再加入微分试试,微分D相当于阻力的效果 ### 最后调节D P保持100,I保持6.0,D使用3.0,从速度曲线上,好像看不出明显的变化。 | P | I | D | | ---- | ---- | ---- | | 100 | 3.0 | | ![](https://cf01.ickimg.com/bbsimages/202105/5423113e3e9b51a54159fcdbca845863.png) P保持100,I保持6.0,D加大到6.0,从速度曲线上看,过冲幅度减小了点。 | P | I | D | | ---- | ---- | ---- | | 100 | 6.0 | 6.0 | ![](https://cf01.ickimg.com/bbsimages/202105/83b1cc8dd2bcd7a98cc824a2bba1da36.png) ## 演示视频
## 总结 本篇简单介绍了PID的基础原理与参数整定,若想把PID参数调节好,还需要不断的实践与调试。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
码农爱学习
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交