欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

初学者PID进阶

程序员文章站 2022-05-26 10:25:13
...

 

存在的问题

本次调整的目的是消除称为“Derivative Kick”的现象。


初学者PID进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
 

上图反应了这个问题。既然 error=Setpoint-Input, 任何 Setpoint 的变化将导致error瞬时发生变化。 这种变化的导数是无穷大(实际上,既然dt不是0,只是计算为一个非常大的数字)。这个数字被送入pid方程,输出一个非期望的峰值。幸运的是有一个简单的方法来摆脱这个。

解决方案


初学者PID进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
 
导数误差等于负导数的输入,除非当Setpoint 改变。这不是一个完美的解决方案,相对于添加(Kd *误差导数),我们减去(Kd *输入的导数)。这被称为使用“导数测量”。
 

The Code

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double errSum, 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;
      errSum += error;
      double dInput = (Input - lastInput);
 
      /*技术PID输出,Compute PID Output*/
      Output = kp * error + ki * errSum - 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进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
 

这里就是修改后的结果,注意,输入看起来仍然相同。所以我们得到同样的性能,但每次Setpoint 的变化不会输出巨大的峰值。

这或许是也或许不是一个大问题。这取决于你的程序对于输出峰值的敏感度。

 

  • 初学者PID进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
  • 大小: 14.2 KB
  • 初学者PID进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
  • 大小: 4.2 KB
  • 初学者PID进阶
            
    
    博客分类: 模型、电子、机器人自动控制 PID 
  • 大小: 12.2 KB
相关标签: PID