改变控制参数积分项对输出结果的影响
可靠的控制系统应该有能力实时变更系统的参数
The Beginner’s PID acts a little crazy if you try to change the tunings while it’s running. Let’s see why. Here is the state of the beginner’s PID before and after the parameter change above:
如果你在系统稳定运行时尝试更改调节参数,可能会导致输出结果有较大的变化,如下所示:
这主要是因为积分项导致的,当参数改变时,积分项的变化是最大的,这是唯一发生剧烈变化的东西。因为系统稳定时,误差是非常小的,同理误差的微分也是非常小的,但是累计误差只会增加,所以变更PID的调节参数,积分项的影响是最大的。
从公式中可以看出,突然改变Ki的值,积分项的变化是最大的。
解决方案
要想消除积分系数改变对输出结果的影响,就得保证需改参数前后,积分项也就是累计误差和的大小变化不大,怎么搞?学过微积分的同学,应该都清楚下面的等式变换。
将积分系数放在积分的里面,积分项的结果还是不变的,在某个时刻改变的大小,受影响的只有这一项,整个误差的积分结果影响就不大了,这样积分项就不会有大的突变,完美解决问题。
在代码上的实现
/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
void Compute()
{
unsigned long now = millis();
int timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double error = Setpoint - Input;
ITerm += (ki * error);//将每次的误差都与积分系数相乘,再去累加
double dInput = (Input - lastInput);
/*Compute PID Output*/
Output = kp * error + ITerm - kd * dInput;
/*Remember some variables for next time*/
lastInput = Input;
lastTime = now;
}
}
void SetTunings(double Kp, double Ki, double Kd)
{
double SampleTimeInSec = ((double)SampleTime)/1000;
kp = Kp;
ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;
}
void SetSampleTime(int NewSampleTime)
{
if (NewSampleTime > 0)
{
double ratio = (double)NewSampleTime
/ (double)SampleTime;
ki *= ratio;
kd /= ratio;
SampleTime = (unsigned long)NewSampleTime;
}
}
So we replaced the errSum variable with a composite ITerm variable [Line 4]. It sums Ki*error, rather than just error [Line 15]. Also, because Ki is now buried in ITerm, it’s removed from the main PID calculation [Line 19].
用变量ITerm【第4行】替换了errSum变量。用它来表示Ki * error,而不仅仅是误差【第15行】。
输出结果的变化
使用此代码,先前的误差和仍然保持不变。