先插句广告,本人QQ522414928,不熟悉PID算法的可以一起交流学习,随时在线(PID资料再我的另一篇博客里)
倒立摆资料连接↓
https://www.cnblogs.com/LiuXinyu12378/p/11222614.html
PID视频资料连接↓
https://www.cnblogs.com/LiuXinyu12378/p/11214174.html
在正式进入正文前,补充一下本人学习PID算法的背景,先自我介绍一下:本人之前是一名电子专业的学生,上学期间一直在做PID,现在工作主要做神经网络,大学期间做过帆板角度控制系统,做过平衡车,做过倒立摆,做过板球控制系统,做过openmv小球追踪系统,还做过四旋翼等……,可以说现在已经很熟悉PID算法,包括单级的PID算法和多级的PID算法。到现在感觉其实这个PID算法还是很经典,很有用的,那么简简单单的几行代码,就能实现自动追踪,自动跟随,平衡等操作,用途广泛。如果你不会PID算法,大多数控制其实你是实现不了的,如果这个经典而又简单的算法你不会,别的控制类的算法估计你也不会。可能让你做一件产品或是参加某些控制类比赛,显然,不会PID这些算法,你只能做简单的逻辑控制,而逻辑控制又太简单,几个if()语句判断显然是不满足控制类设计的需要的。另外,很多不需要PID算法的设计其实也是可以加入PID算法的,这能让你的设计更有稳定性,有些必须需要PID算法的设计,没有PID不能形成闭环控制,是根本不能完成的。
扯淡的不多说,本人就喜欢简单粗暴,喜欢把复杂的东西简单化,很多的电子教程虽然把PID算法介绍的很全面,但是写的复杂的不得了,今天本人就用通俗易懂的语言把复杂的问题简单化:
先解释一下传统的位式算法,也就是简单的逻辑算法:位式算法的输出要么是0,要么是1,也就是在一定条件下是全速运行,不满足这个条件就完全停止或反向全速运行。
①先拿恒温烧水系统来说,假如说你要把水烧到80度,简单的逻辑做法是在水里加一个温度传感器和电热烧水器,然后用单片机测温,如果if(温度<80度),那你就给电热烧水器加热烧水,如果if(温度>80度),那我就停止加热。思考一下,最后你得到的水温一定会是80(可以上下有微小差别)度吗?答案肯定是否定的。(这里说明一下,不要教条,不要问你为什么会把水烧到80度)这是为什么?我来解释一下,当传感器测到温度达到80度时,单片机控制加热器停止加热,虽然加热器断电了,但是加热器的余温还是比水的温度要高,所以加热器不会立即停止加热,而是继续给水加热一会儿直到和水的温度一样,此时水的温度会高于80度,可能电热器的余温就把水加热到了90度,对吧!然后水和加热器又一起降温,所以当水的温度下降到80度时,这时传感器检测到水温低于80度,单片机又控制加热器加热,但是加热器现在凉了需要预热一下再给水加热,在预热的这段时间里水的温度可能又降到了75度才开始加热。所以,水的温度不能保持在80度上下轻微浮动的范围内,水温一直都是在75度到90度之间浮动的!
②再拿平衡车系统来说,你需要一个陀螺仪传感器,比如(mpu6050),先说下平衡车的原理,避免有些人不懂,平衡车为什么两个轮子能站着不到,大家一定都军训过,站过军姿,站军姿的时候教官让你身体前倾,但是只能轻微的前倾,如果你能前倾45度,那你一定控制不住身体平衡,需要往前迈步才能达到平衡。平衡车跟这个原理是一样的,如果车要往前倒,那我让车轮前转来维持平衡,如果车往后倒,那我让车轮后传来维持平衡,原理都应该明白了吧!(如果这个原理还不明白建议多思考一下,理解清楚)继续,假设车上的陀螺仪角度0度时车是平衡的,如果角度大于0度我就让车轮前转,如果角度小于0度我就让车轮后转,显然这样做,车是平衡不了的,由于车的惯性作用,一下可能就过调了,直接倒了。原理跟烧水差不多,不多说了。
再来解释下PID算法:
1.刚才介绍了半天位式算法,位式算法的输出就是简单的逻辑输出,不是0就是1,比如烧水,小于80度就接通烧水器的继电器,功率直接达到最大,当水温大于80度时,继电器就直接断开,功率直接降到最低。在平衡车上用位式算法解读就是,车的倾角<0度,电机控制器给-1,电机反向全速运转,车的倾角>0度时,电机控制器给+1,电机正向全速运转,位式算法的特点就是要不就全速运行,要不就直接停止。
2.PID算法就不一样了,PID算法通常输出的都是可以调节输出功率大小的,比如输出的PWM或直接输出电压值大小DAC(PWM即脉宽调速占空比),假设PWM的周期是255,当高电平占空比为255(100%)时相当位式算法输出的1,即全速运行,当高电平占空比为128(50%)时,输出的功率理论上为全速的一般。说到这大家就应该明白了,PID的输出是可以控制方向以及大小的。
下面开始说PID算法:
先说PID三个参数,P是比例,I是积分,D是微分;很多人都知道这三个参数,只是不了解其背后代表的含义,为啥用比例积分微分。不着急听我慢慢给你介绍,只要我介绍完,你一下就懂了。
首先介绍一下P,P代表比例,光用一个比例算法其结构是这样的:
err(误差)=setpoint(设定值)-actual_value(传感器测量的实际值) (误差这个概念大家应该都明白)
output(输出值比如PWM)=p(比例系数)*err(误差)
比例反应的是现在的状态。
这个比例系数P,需要你大概估测一下值是多少,比如平衡车,光一个比例控制就能让平衡车站半天了。比如设置平衡点为0度,此时实际的值为8度,此时误差就为-8度,输出的PWM值就等于(-8)*P。PWM=(-8)*P,这个P的具体值就需要你根据周期和占空比来估计决定,比如此时的PWM值应该是64才能让平衡车具有恢复平衡的能力,那么P的值就应该为8.0。这下大家应该明白了P这个参数该如何来设定。
在介绍一下积分I,积分分为好几种,这里先介绍两种:
1.普通的
一般滴,没有单独用一个I控制的模型,所以这里用PI控制:
err(当前误差)=setpoint(设定值)-actual_value(传感器测量的实际值)
err_integral(误差的积分值)=err_integral(误差的积分值)+err(当前误差)
output(输出值比如PWM)=p(比例系数)*err(误差)+I(积分系数)*err_integral(误差的积分值)
这里介绍一下积分的作用,
积分反应的是过去的状态。
积分的意义:积分的作用就在于对误差的累加,我就根据实际情况来解释,比如说,我光用一个比例P来控制一个模型的运转,在误差较大的时候这个比例的作用起的很大,还是说平衡车,当角度误差值为8时,假定预测P=8.0,PWM=角度误差*P,此时PWM值为64,这时候电机可以按一定的速度转动起来,当偏差为0.5时,PWM的值就为4,当PWM为4的时候,根据电机的特性,可能因为这个4太小,电机根本连转的力气都没有,这时候本来平衡点应该是0,可到了0.5电机因为pwm值太小而不起作用,这样就始终达不到平衡点。那我现在加上积分,积分的作用就是把一个个的误差加起来,因为误差有正也有负,所以积分不会只朝着一个方向增大(正或负),比如误差在0.5时比例就失去了调节能力,那么此时积分就起作用了,积分会把这个0.5累加直到PWM值能够给电机充足的能量去达到0这个平衡点。一般积分I这个系数的值设为P*1/200.
2.积分分离算法
普通的PI算法积分,积分会一直起作用,不管误差有多大,而当误差太大的时候,积分的一直累加运行会让系统产生过冲,一个普通的PID算法做的平衡车一上电时因为手持摆放的位置离平衡点太远会引起过冲,让平衡车一上电电机就猛地往一边冲,过一会儿才能好。
为了解决这个问题可以用积分分离的方式,误差太大时,积分就不起作用,当误差小的时候,积分再起作用。能有效避免过冲。
err(当前误差)=setpoint(设定值)-actual_value(传感器测量的实际值)
if(err(当前误差)<某个值时)
{err_integral(误差的积分值)=err_integral(误差的积分值)+err(误差)}
else
{err_integral(误差的积分值)=err_integral(误差的积分值)+ 0(0误差,不让误差累加到积分上)}
output(输出值比如PWM)=p(比例系数)*err(当前误差)+I(积分系数)*err_integral(误差的积分值)
最后咱们说微分D
微分反应的是误差的变化率
微分预测将来的状态。
err(当前误差)=setpoint(设定值)-actual_value(传感器测量的实际值)
if(err(当前误差)<某个值时)
{err_integral(误差的积分值)=err_integral(误差的积分值)+err(误差)}
else
{err_integral(误差的积分值)=err_integral(误差的积分值)+ 0(0误差,不让误差累加到积分上)}
differential(微分)=err(当前误差)-last_err(上一次误差)
执行完这句后
last_err(上一次误差)=err(当前误差)
output(输出值比如PWM)=p(比例系数)*err(当前误差)+I(积分系数)*err_integral(误差的积分值)+D(微分系数)*differential(微分)
总结,PID的算法基本含义就是,要观测当前的误差并进行调整,还要总结过去的误差来摆脱现状,还需预测未来的误差趋势加快调整。