从第一次训练开始我们就接触到了一个新的名词——PID控制理论。接触这个理论时间还是挺早的。大二某天晚上与学长“促膝交谈”时他就有跟我提起过这个算法。当初他给我说的一个应用的场合就是在智能小车两个轮子速度的控制上,通过pid使得两个轮子的速度尽可能接近相等。那个时候就感觉很纠结,速度控制直接左边慢一点就给左边加速,反之给右边加速。但真正当第一个题目(恒温水壶)做出来的时候就发现,如果用传统的方法去做控制(即温度高则不加温,温度低则加温),控制的提升速度与控制值的超调范围无法达到两者兼顾的效果(这也是为什么最后我们做出来的结果都不怎么好的原因之一,因为我网上百度的pid算法是个伪的。)。理论上(PID到现在为止没有调试成功过),通过PID算法能够使被控制量兼顾效率与精度这两个我们所关注的量。
PID理论说白了就是三个量。Kp,Ki,Kd。
先说下Kp,K是常量的意思,p代表的比例(proportion),Kp可以说是PID算法中必不可少的一个量。没有它控制就不可能实现。它的作用是根据当前量与设定量的差值按照一定比例放大后得到控制量。比如一个温控系统,很自然的我们能够想到当温度越接近我们设定值时我们就越要放慢速度加热,kp就是起一个这样的作用。比如kp我设为10,我设定恒温的温度为60度,当前温度为49度,那么我输出的控制量(使用占空比对热得快实现控温)为10*(60-49)=110;如果当前温度为20度我输出为10*(60-20)=400,但由于400太大了,比最大控制值0xff(255)还大,我就直接255了。如果当前温度为61度我输出为10*(60-61)=-10<0我输出就为0。即不加热让其自然冷却。讲了这么多归纳一个公式就是UKp=Kp*(Uset-Unow),其中UKp是通过Kp这个参数计算所输出的控制量,Uset为设定温度,Unow为当前温度。
接下来就是Ki这个量,i代表的是integration,积分。空洞的说没意思,直接举栗子,依旧是温控系统,当我温度上升到59度时(设定温度是60度)这个时候我通过上面Kp得到的控制量是10,但此时环境温度很低。你10的控制量所提供的能量刚刚好能够抵消掉散失到空气中的热量,此时温度就恒定在59度了,当然这是与60度我们设定的值有了差距。这个时候KI就要开始起作用了,KI基本公式是从0到当前时刻(Uset-Unow)的积分值乘以Ki,但在单片机(计算机中也是)中只有数字量,于是分就变成了相乘,公式就成了UKi=UKi+KI*(Uset-Unow)*dt,dt是系统的采样周期,即Unow隔dt采样一次。这个值比较小,大多都不为整数,而众所周知的51单片机中浮点数运算较慢,于是我一般会将公式改为UKi=UKi+KI*(Uset-Unow)/F,F为频率,一般为比一大的整数,即F=1/dt。回到刚才的问题,积分的作用就非常明显了。系统恒定在59度这KI*(60-59)/F随着时间不断在积分在增加,当控制量超过一定值时系统温度就会开始上升了,由于在接近我们设定的点之前(Uset-Unow)较大,而这一部分的值依旧被积分到了Uk之中,所以Ki的作用会导致最终的控制量有一定的超调,也就是说Ki设置好之后可以稍微减少Kp的值。
最后就是Kd,d代表对时间微分(differential),即速度,是对未来趋势的一种预测,比如还是恒温系统,我停止加热之后温度并不会立即停止上升(热得快有余温还有就是水受热不均所致),此时通过微分量预测上升的速度对输出的控制量进行适当缩小,可以尽量避免“冲过头”这种事情发生。公式UKd=UKd+Kd*((Uset-Unow)now-(Uset-Unow)before)/dt。(Uset-Unow)now是现在的(Uset-Unow)值,(Uset-Unow)before是在前一刻(Uset-Unow)的值。把dt依旧转化成F即UKd=UKd+Kd*((Uset-Unow)now-(Uset-Unow)before)*F,UKd即为微分所对应的控制量。
好啦。。三个量都讲完了,最终的输出控制量Uk就是这三个量之和,即UK=UKp+UKi+UKd。但在51单片机中,浮点数运算会较慢,于是除了0以外我们最小只能设定PID的三个参数为1,大多数时候这个1都还是很大的一个值。所以在得到最终的输出值时我们一般都会对这个值做移位处理(右移)即移动n位相当于除以2的n次方。调整这个n可以使得输出在一个合适的值之内。