PID控制器
实现PD控制器之后,我们的目的已经达到。但是还有不足,那就是系统到达稳定状态的时间较长,还要经历多次震荡过程。能否减少震荡,加快到达稳态?回答是肯定的,微分控制器就是做这个事情的。说的形象点,前面的积分控制器表征了系统的历史,积累了多少误差,然后给它补上。相对的这个微分就是提前决定给多大的补充。微分作用与被调量的大小无关,与被调量的变化速率有关 系统变化越快,给出的调节值趋向无穷大。当然现实中不存在无穷大。
再次回到理论,这次总算是完整的公式了:
u(t)?Kp[e(t)?1TI?t0e(t)dt?TDde(t)/dt]离散化 t?kT(k?0,1,2,?)kke(t)?e(kT)de(t)dt?e(kT)?e[(k?1)T]T?e(t)dt??j?0e(jT)T?T?e(jT)j?0u(k)?Kp{e(k)?TTIk?e(j)?j?0kj?0TDT[e(k)?e(k?1)]}?Kpe(k)?KI?e(j)?KD[e(k)?e(k?1)]
这里关注点是微分部分。涉及到2个值,本次的误差e(kT) ,上次的误差e[(k-1)T],2者的差值除以采样时间就是变化率了。Td就是微分系数。和积分一样这次用Kd = kp*Td/T ,同样是为了减少程序的计算量,整定时直接修改即可。
全局变量 errSUM 积分项
新增上次的偏差值变量errorLast 微分项使用
double error = mySetpoint - inputMeter; errSUM += error;
outputPWM = kp*error + ki * errSUM + kd *(error – errorLast); //arduino 的调节范围就是0 - 255 if(outputPWM > 255) outputPWM = 255; if(outputPWM < 0) outputPWM = 0;
实验结果(这次2个电机一起来吧):
效果令人满意,呵呵。
再进一步,到目前为止,我们实现的算法,叫做位置PID,也就是每次都使用整个系统的状态。我理解为:偏差使用的是所有的全量偏差。还有一种算法是增量式PID。摘录网上的话:“位置式PID算法每次输出与整个过去状态有关,计算式中要用到过去误差的累加值,因此,容易产生较大的累积计算误差。而增量式PID只需计算增量,计算误差或精度不足时对控制量的计算影响较小。” 公式:
上一次的输出为u(k-1),这次的输出为u(k) ,变化量为^u(k):
k?1u(k?1)?Kpe(k?1)?KI?e(j)?KD[e(k?1)?e(k?2)]j?0?u(k)?u(k)?u(k?1)?KP[e(k)?e(k?1)]?KIe(k)?KD[e(k)?2e(k?1)?e(k?2)]我们需要的pwm输出是全量,而不能是变化量,那么加上上次的u(k-1)即可。 u(k) = u(k-1) + ^u(k),也就是把u(k)项移到等号左边,把^u(k)移动到等号右边。好了,让我们来实现它,这次是最终代码,直接上代码片段。 #define PVAL (error - last1Error) #define IVAL ((error+last1Error)/2)
#define DVAL (error - 2*last1Error + last2Error) /*Compute all the working error variables*/ double input = *myInput;
double error = *mySetpoint - input; /*Compute PID Output*/
double output = *myOutput + kp * PVAL + ki * IVAL + kd * DVAL ; if(output > outMax) output = outMax; else if(output < outMin) output = outMin; *myOutput = output;
/*Remember some variables for next time*/ last2Error = last1Error; last1Error = error;
好了,享受成果的时候到了:
别忘了,我们的目的还没有达到,目前为止只是实现了调速,还是空载运行,还要测试负载运行的情况。走直线还有需要考虑的算法没有进行。而且,对于这个调速结果还有可以深入的地方。积分分离算法,微分现行算法,这些对于我们的电机调速有帮助吗?自动整定参数可以实现吗。继续上路吧。
相关推荐: