PID控制器为什么需要一个开关
在调试PID算法的过程中,有时需要手动的让系统输出某个值。怎么办?可以简单的办,不管你PID控制器计算出来的值的多少,我都强制的让系统输出特定的值。这么做其实也不违法,感觉就是有点渣,既然不爱了为什么还去招惹她。就像下面的图,你让PID控制器辛辛苦苦的计算,计算出来的结果你又不要,非得自己去设置个值,这种人挺那个啥的。
就像下面的的代码,让PID计算完之后,又强制让输出为0.
void loop()
{
Compute();
Output=0;
}
这样无论PID的怎么说,都可以覆盖他的值。但是,这在实践中是一个可怕的想法。PID会变得非常疑惑:“我一直在改变输出值,什么也没发生,出了什么事情?!让我改变一个更大的输出值。”结果,当你停止覆写输出并切换回PID时,输出值可能会立刻发生巨大的改变。
解决方案
解决此问题的方法是有一种方法可以打开和关闭PID。 这些状态的常用术语是“手动”(我将手动调节值)和“自动”(PID将自动调节输出)。 让我们看看如何通过代码完成此操作:
/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
double outMin, outMax;
bool inAuto = false;
#define MANUAL 0
#define AUTOMATIC 1
void Compute()
{
if(!inAuto) return;
unsigned long now = millis();
int timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double error = Setpoint - Input;
ITerm+= (ki * error);
if(ITerm> outMax) ITerm= outMax;
else if(ITerm< outMin) ITerm= outMin;
double dInput = (Input - lastInput);
/*Compute PID Output*/
Output = kp * error + ITerm- kd * dInput;
if(Output > outMax) Output = outMax;
else if(Output < outMin) Output = outMin;
/*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;
}
}
void SetOutputLimits(double Min, double Max)
{
if(Min > Max) return;
outMin = Min;
outMax = Max;
if(Output > outMax) Output = outMax;
else if(Output < outMin) Output = outMin;
if(ITerm> outMax) ITerm= outMax;
else if(ITerm< outMin) ITerm= outMin;
}
void SetMode(int Mode)
{
inAuto = (Mode == AUTOMATIC);
}
一个相当简单的解决方案。 如果未处于自动模式,请立即退出计算函数,而无需调整输出或任何内部变量。
的确,可以通过不从调用例程中调用Compute来达到类似的效果,但是这种解决方案可以保留PID的工作原理,这正是我们所需要的。 通过将内容保持在内部,我们可以跟踪所处的模式,更重要的是,它使我们知道何时更改模式。 这就引出了下一个问题……