PID控制算法: 6、Initialization(初始化)

文章讨论了在PID控制器中,当从手动模式切换到自动模式时可能出现的输出波动问题。解决方案是通过在切换时正确初始化关键变量ITerm和lastInput,以确保比例、积分和导数项的平稳过渡,防止输出跳跃。初始化ITerm为Output,lastInput为Input,从而避免积分积累和导数尖峰,实现无干扰的模式切换。
摘要由CSDN通过智能技术生成

在上一章中,实现了打开和关闭PID的功能。 当关闭了PID之后,再重新打开会发生生么。

PID会跳回到它发送的最后一个输出值,然后从那里开始调整。 这会导致出现反馈值波动。

解决方案

这个很容易解决,因为我们知道什么时候开始的手动/自动切换,所以我们只需要初始化一些东西就可以实现平稳的转换。这意味着对存储的两个工作变量(ITerm和lastInput)进行处理,以防止输出跳跃。

/*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)
{
    bool newAuto = (Mode == AUTOMATIC);
    if(newAuto && !inAuto)
    {  /*we just went from manual to auto*/
        Initialize();
    }
    inAuto = newAuto;
}

void Initialize()
{
   lastInput = Input;
   ITerm = Output;
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}

修改SetMode(…)函数,用来检测从手动到自动的过渡,并添加了初始化功能。设置ITerm=Output来处理积分项,设置lastInput=Input来防止导数尖峰。比例项不依赖于过去的任何信息,因此不需要任何初始化。

从上图中我们可以看到,正确的初始化会导致从手动到自动的无障碍转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值