PID入门提高翻译教程【二】-Arduino中文社区 - Powered by Discuz! Archiver

syl312 发表于 2013-12-31 12:51

PID入门提高翻译教程【二】

本帖最后由 syl312 于 2014-1-23 13:57 编辑

   微分过冲:   出现的问题:通过对微分项的弱化处理,目的是消除微分过冲的现象。
                                 上图说明了这个问题,因为偏差error=Setpoint-Input.任何在系统设定值得改变将立刻引起偏差的变化。所以系统设置值微小的变化将会导致出现一个极大的微分值。解决方法:
                              以上公式已经被证明,除了设置值改变的时候,偏差的微分等于输入导数的负值。这就有了一个很好的解决方法。我们用 -kd * dInput取代原来的微分。这就是微分的测量方法。程序实现:
unsigned long lastTime;
doubleInput, Output, Setpoint;
doubleerrSum, lastInput;
doublekp, ki, kd;
int SampleTime =1000; //1s
void Compute()
{
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      doubleerror = Setpoint - Input;
      errSum += error;
      doubledInput = (Input - lastInput);
      Output = kp * error + ki * errSum - kd * dInput;
      lastInput = Input;
      lastTime = now;
   }
}

void SetTunings(doubleKp,doubleKi,doubleKd)
{
doubleSampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki * SampleTimeInSec;
   kd = Kd / SampleTimeInSec;
}
void SetSampleTime(int NewSampleTime)
{
   if (NewSampleTime >0)
   {
      doubleratio= (double)NewSampleTime
                      / (double)SampleTime;
      ki *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}
      结果:                     这就是我们修正后带来的效果。注意输入依旧是一样的。我们得到了一样的性能,并且不会因为Setpoing的变化导致输出波形有很大的纹波。问题:对于一个正在运行的PID控制系统PID参数的改变会导致输出的变化。
                        
对于修正正在运行的控制系统的PID参数,会带来很大的变化。以下是PID参数修改前后的变化值:
                     
       通过这张可以看出,以上是因为积分突然变为原来的一半。当参数变化时,带来的变化是巨大的。为什么会是这样的呢?下面的积分公式可以解释:
                        
      这就解释了为什么KI没改变之前系统工作的一直很稳定。突然,你乘了一个新的KI值与之前的偏差累计总和。这样带来的变化不是我们所希望的,我们只想改变后能朝着我们希望的方向发展。   解决方法:解决的方法有很多,我在最新的Arduino PID库里使用的方法是重新调整errSum(偏差总和).KI变为原来的两倍时,把errSum变为原来的一半,虽然这个方法有点笨拙,下面有更加明智的方法。这个方法要求有基础的代数基础或者计算技巧。
                     


   把KI乘到里面,虽然看起来没什么变化,但是我们将会看到这个小变化带来了很大的不同。现在我们将error和Ki相乘。并且把乘积和保存起来,当Ki变化时,这时不会有很大的变化了,因为之前的KI的乘积和值已经存储起来了。
unsigned long lastTime;
doubleInput, Output, Setpoint;
doubleITerm, lastInput;
doublekp, ki, kd;
int SampleTime =1000; //1sec
void Compute()
{
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      doubleerror = Setpoint - Input;
      ITerm += (ki * error);
      doubledInput = (Input - lastInput);
      Output = kp * error + ITerm - kd * dInput;

      lastInput = Input;
      lastTime = now;
   }
}

void SetTunings(doubleKp,doubleKi,doubleKd)
{
doubleSampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki * SampleTimeInSec;
   kd = Kd / SampleTimeInSec;
}

void SetSampleTime(int NewSampleTime)
{
   if (NewSampleTime >0)
   {
      doubleratio= (double)NewSampleTime
                      / (double)SampleTime;
      ki *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}
我们用ITerm变量来替代errSum【第四行】。这样KI就包含在ITerm中,就从主要的PID计算式子中抽离出来。结果如下:                           
                        
当KI调整之前,控制器重新调整了全部的error的总和,每个偏差值都能看到。通过这个程序,先前的偏差值仍旧是原样的,新的KI值只是朝着我们希望的方向有作用。

coloz 发表于 2014-1-2 11:44

好东西!

syl312 发表于 2014-1-2 13:50

coloz 发表于 2014-1-2 11:44
好东西!

:L:L:L:L

syl312 发表于 2014-1-2 13:51

coloz 发表于 2014-1-2 11:44
好东西!

图片不能贴在文章里吗,只能放在附件?

coloz 发表于 2014-1-2 17:22

syl312 发表于 2014-1-2 13:51
图片不能贴在文章里吗,只能放在附件?

可以啊,点上传图片就行了啊

syl312 发表于 2014-1-2 19:01

coloz 发表于 2014-1-2 17:22
可以啊,点上传图片就行了啊

需要先上传图片再复制才可以显示在文章里,有几张显示不出来我就放在附件里了,搞定了

syl312 发表于 2014-1-2 19:39

图又挂了,我放在附件里了。

popopupa 发表于 2014-1-5 08:42

强烈支持,正好想用PID,多谢分享!

syl312 发表于 2014-1-5 09:46

popopupa 发表于 2014-1-5 08:42
强烈支持,正好想用PID,多谢分享!

剩下部分这个月应该会翻译好,可以去原地址看看,先学习:lol

646097010 发表于 2014-2-22 20:31

好帖子!收藏研究!!!!!!!
页: [1] 2 3
查看完整版本: PID入门提高翻译教程【二】