最近看到了Brett Beauregard发表的有关PID的系列文章,感受对于理解PID算法颇有帮助,因而将系列文章翻译过来!在自我提升的过程当中,也但愿对同道中人有所帮助。做者Brett Beauregard的原文网址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-tuning-changes/算法
1、问题spa
对于任何可靠的PID算法,拥有在系统运行时更改整定参数的能力都是必须的。翻译
若是你试图在系统运行时改变整定参数,在初学PID的人看来会显得有点疯狂。让咱们看看这是为何?如下是初学者的 PID 在上述参数更改先后的状态:3d
所以,咱们能够当即将这种差别归咎于积分项(或“I项”)。只有当参数发生变化时,它才会发生剧烈的变化。为何会这样?这与初学积分的人对积分的理解有关:code
这种解释在 Ki 被改变以前都是能够正常工做的。而后,你忽然把这个新的 Ki 乘以你积累的整个偏差总和。这不是咱们想要的!咱们只想影响事情后续的发展。blog
2、解决方案get
有几种方法能够处理这个问题。我在上一个库中使用的方法是从新缩放误差累计。Ki 翻了一倍?或者把误差累计削减一半。这能够避免积分项撞击,而且也能工做的很好。不过,这有点笨拙,我想出了更优雅的东西。(我不多是第一个想到这个问题,但我确实是一我的想到的。这算数!)数学
这个方案须要一个小的基本代数 (仍是微积分?)io
咱们不是让 Ki 处在积分以外,而是把它带到里面。看起来咱们视乎什么都没作,但咱们会看到,在实践中,这带来了很大的变化。ast
如今,咱们把偏差乘以那个时候的Ki。而后咱们存储它的和。当Ki发生变化时,没有任何变化,由于全部旧的Ki都已经“存在银行”了。咱们获得一个平稳的转换,没有额外的数学运算。这可能会让我成为一个极客,但我以为这很性感。
3、代码
1 /*working variables*/ 2 unsigned long lastTime; 3 double Input,Output,Setpoint; 4 double ITerm,lastInput; 5 double kp,ki,kd; 6 int SampleTime = 1000; //1 sec 7 void Compute() 8 { 9 unsigned long now = millis(); 10 int timeChange = (now - lastTime); 11 if(timeChange>=SampleTime) 12 { 13 /*Compute all the working error variables*/ 14 double error = Setpoint - Input; 15 ITerm += (ki * error); 16 double dInput = (Input - lastInput); 17 18 /*Compute PID Output*/ 19 Output = kp * error + ITerm - kd * dInput; 20 21 /*Remember some variables for next time*/ 22 lastInput = Input; 23 lastTime = now; 24 } 25 } 26 27 void SetTunings(double Kp,double Ki,double Kd) 28 { 29 double SampleTimeInSec = ((double)SampleTime)/1000; 30 kp = Kp; 31 ki = Ki * SampleTimeInSec; 32 kd = Kd / SampleTimeInSec; 33 } 34 35 void SetSampleTime(int NewSampleTime) 36 { 37 if (NewSampleTime > 0) 38 { 39 double ratio = (double)NewSampleTime 40 / (double)SampleTime; 41 ki *= ratio; 42 kd /= ratio; 43 SampleTime = (unsigned long)NewSampleTime; 44 } 45 }
所以,咱们用复合积分项变量替换了 [第4行]误差求和变量。它计算 Ki * 误差,而不只仅是误差 [第15行]。此外,因为 Ki 如今被隐藏在积分项中,所以它将从主 PID 计算 [第19行] 中删除。
4、结果
那么,这是如何解决问题的。在修改Ki以前,它从新计算了全部误差的总和;咱们看到的每个误差值。有了这段代码,以前的误差将保持不变,而新的Ki只会影响事情的进展,这正是咱们想要的。
译注:对于本篇讨论的修改整定参数对积分项的影响问题。采用位置式PID公式确实存在这一问题,做者的解决方式也很赞。由于这就是增量式PID积分项的默认处理方式。因此若是采用增量式PID就不会存在这个问题了。
欢迎关注: