欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > Arduino PID库 (3):调参更改

Arduino PID库 (3):调参更改

2024/10/23 23:20:47 来源:https://blog.csdn.net/acktomas/article/details/140901627  浏览:    关键词:Arduino PID库 (3):调参更改

Arduino PID库 (3):调参更改

参考:手把手教你看懂并理解Arduino PID控制库——调参改变

pid内容索引

Arduino PID库 (2) – Derivative Kick

问题

在系统运行时更改调谐参数的能力对于任何PID算法都是必须的。
在 PID 控制实际的应用过程中,可能会存在需要突然改变 PID 调谐参数 Kp、Ki、Kd 的情形,那么如果突然改变调谐参数,会有什么影响呢?首先先看一张图:

img
如果在系统运行的过程中,对调谐参数进行较大的改变,那么 Output 会产生一个突变,有点略微像 “坑”。
初学者的PID在运行时尝试整定,表现得有点疯狂。让我们看看为什么。以下是上述参数更改前后初学者的PID状态:

undesirable: 不可取,不理想

img
上述现象描述了在系统进入稳态后,突然改变 PID 参数导致的变化,引起输出较大变化的起主要作用的因子为 I 参数,由于进入稳态 P 参数乘以 E 变化不大,D 参数同样不大,但是 I 参数相乘因子是关于时间的积分(可以想象如果一开始被控量与设定值相距较远,而积分表示的是带方向的面积和,所以必然存在一个方向会有较大面积,见下图),所以,会引起较大的变化。
在这里插入图片描述

因此,我们可以立即将这种振荡归咎于积分项(或“I 项”)。这是参数更改时唯一发生巨大变化的东西。为什么会这样?这与初学者对积分的解释有关:

在这里插入图片描述
第一个等式在 KI 是常数的时候没问题,不是常数的时候需要评估,尽管不完全成立,但如果在稳态时 E 非常小,那么,也是可以接受。这似乎和经典的 PID 等式不一样。换个角度,经典的 PID 控制 I 项,也仅仅是为了消除静态误差而确定的,如果在这个大前提下,换一种方式消除静态误差也是可以的,仅仅是牺牲了力度

在 Ki 更改之前,这种解释效果很好。然后,突然之间,您将这个新 Ki 乘以您累积的整个误差总和。那不是我们想要的!我们只想影响事情的发展!

解决方案

我知道有几种方法可以解决这个问题。我在上一个库中使用的方法是重新缩放 errSum。Ki加倍了?将errSum减半。这样可以防止 I 项发生碰撞,并且它有效。不过有点笨拙,我想出了更优雅的东西。(我不可能是第一个想到这一点的人,但我确实自己想到了。

解决方案需要一点基本的代数(或者是微积分?

img

我们不是让 Ki 生活在积分之外,而是把它带入内部。看起来我们什么都没做,但我们会看到在实践中这有很大的不同。

现在,我们取error并将其乘以当时的 Ki。然后我们存储 它 的总和。当 Ki 发生变化时,不会有颠簸,因为可以这么说,所有旧的 Ki 都已经“在银行里”。我们无需额外的数学运算即可顺利转移。

代码

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

因此,我们将 errSum 变量替换为复合 ITerm 变量 [第 4 行]。它对 Ki*error 求和,而不仅仅是error [第 15 行]。此外,由于 Ki 现在包含在 ITerm 中,因此它已从主 PID 计算 [第 19 行] 中删除。

结果

img
img
从图表中可以看出,尽管 PID 参数发生了较大的改变,但输出仍然变得连续。在上述过程中,牺牲了系统的响应的 “灵敏度” 增加了控制的稳定性,系统的灵敏度往往可以通过增加计算频率来改善,大幅提高采样频率可以起到较快的更新积分项的作用。
我们看到的每一个error值。使用此代码,以前的错误保持不变,新的 ki 只会影响将来的事情,这正是我们想要的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com