初学者PID进阶——在线调整参数

 

原文地址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner%e2%80%99s-pid-tuning-changes/

问题The Problem

在系统运行时调参是一个优秀PID算法必须具备的。


初学者PID进阶——在线调整参数_第1张图片
 

最初的PID当你在系统运行时调整时显得有点懒惰。让我们看看这是什么原因。这里是最初的PID调整前后的状态:


初学者PID进阶——在线调整参数_第2张图片
 

因此我们立即认为这个问题出在积分项(或者I项)。唯一的参数变化引起急剧变化。为什会这样?这不得不解释初步的积分:



 

这个公式正常工作知道Ki改变。突然的,你新的Ki被乘以错误之和的累积。这不是我们想要的!我们只想把事情向前推进。

解决方案The Solution

我知道几种方法来解决这个问题。在最后的库里面我用的方法是从新调整误差和errSum。双倍Ki?errSum减半。这样避免了I项的跳动,并且工作良好。这个看起来有点粗糙,我想出一些更好的办法。

解决方案需要一些基础代数



 

和让Ki外部积分相反,我们把它放进去。看上去我们没做什么,但是我们将看到实际情况是有很大不同的。

现在误差乘以Ki。我们保存乘积的和。当Ki变化是,这里不会有抖动,因为旧的Ki已经保存了。我们得到一个平滑的过渡而不用一个附加的数学操作。这让我成为一个极客,但我认为这很性感。

The Code

/*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;
   }
}
 

The Result


初学者PID进阶——在线调整参数_第3张图片
那么这是如何解决问题的呢。在ki改变之前,重新调整了整个误差和;每个误差值我们都已经看到。这段代码中,前面的误差保持不变,只有新的Ki会影响变化,这正是我们想要的。

 

你可能感兴趣的:(自动控制,模型,电子,机器人)