改进初学者的PID-修改整定参数
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-tuning-changes/
1、问题
对于任何可靠的PID算法,拥有在系统运行时更改整定参数的能力都是必须的。

如果你试图在系统运行时改变整定参数,在初学PID的人看来会显得有点疯狂。让我们看看这是为什么?以下是初学者的 PID 在上述参数更改前后的状态:

因此,我们可以立即将这种差异归咎于积分项(或“I项”)。只有当参数发生变化时,它才会发生剧烈的变化。为什么会这样?这与初学积分的人对积分的理解有关:

这种解释在 Ki 被改变之前都是可以正常工作的。然后,你突然把这个新的 Ki 乘以你积累的整个误差总和。这不是我们想要的!我们只想影响事情后续的发展。
2、解决方案
有几种方法可以处理这个问题。我在上一个库中使用的方法是重新缩放偏差累计。Ki 翻了一倍?或者把偏差累计削减一半。这可以避免积分项撞击,并且也能工作的很好。不过,这有点笨拙,我想出了更优雅的东西。(我不可能是第一个想到这个问题,但我确实是一个人想到的。这算数!)
这个方案需要一个小的基本代数 (还是微积分?)

我们不是让 Ki 处在积分之外,而是把它带到里面。看起来我们视乎什么都没做,但我们会看到,在实践中,这带来了很大的变化。
现在,我们把误差乘以那个时候的Ki。然后我们存储它的和。当Ki发生变化时,没有任何变化,因为所有旧的Ki都已经“存在银行”了。我们得到一个平稳的转换,没有额外的数学运算。这可能会让我成为一个极客,但我觉得这很性感。
3、代码
/*working variables*/
unsigned long lastTime;
double Input,Output,Setpoint;
double ITerm,lastInput;
double kp,ki,kd;
int SampleTime = ; //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)/;
kp = Kp;
ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;
} void SetSampleTime(int NewSampleTime)
{
if (NewSampleTime > )
{
double ratio = (double)NewSampleTime
/ (double)SampleTime;
ki *= ratio;
kd /= ratio;
SampleTime = (unsigned long)NewSampleTime;
}
}
因此,我们用复合积分项变量替换了 [第4行]偏差求和变量。它计算 Ki * 偏差,而不仅仅是偏差 [第15行]。此外,由于 Ki 现在被隐藏在积分项中,因此它将从主 PID 计算 [第19行] 中删除。
4、结果


那么,这是如何解决问题的。在修改Ki之前,它重新计算了所有偏差的总和;我们看到的每一个偏差值。有了这段代码,之前的偏差将保持不变,而新的Ki只会影响事情的进展,这正是我们想要的。
译注:对于本篇讨论的修改整定参数对积分项的影响问题。采用位置式PID公式确实存在这一问题,作者的解决方式也很赞。因为这就是增量式PID积分项的默认处理方式。所以如果采用增量式PID就不会存在这个问题了。
欢迎关注:

改进初学者的PID-修改整定参数的更多相关文章
- 改进初学者的PID-介绍
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- 改进初学者的PID-测量的比例编码
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- 【技术】Arduino PID自整定库
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- 改进初学者的PID-测量的比例介绍
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- 改进初学者的PID-正反作用
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- 改进初学者的PID-采样时间
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- mac 修改系统配置参数 主机名 等
mac 修改系统配置参数,可以使用 命令 scutil 参考网址: https://developer.apple.com/library/mac/documentation/Darwin/Refer ...
- uboot启动阶段修改启动参数方法及分析
作者:围补 本来启动方式这节不是什么复杂的事儿,不过想简单的说清楚明白,还真是不知道怎么组织.毕竟文字跟有声语言表达有别.但愿简单的东西别让我讲的太复杂! Arm板系统文件一般有三个——bootloa ...
- 测试修改gcs_server_processes参数
RAC部署前提是要求各节点的主机硬件一致的,但实际如果碰上一些不规范的客户,经费有限或是扩容时已买不到同样的机器,那么采购的机器会有一些区别,比如RAC各节点的CPU核数有区别,那么默认的gcs_se ...
随机推荐
- bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希
题目 给定矩阵A, B和模数p,求最小的正整数x满足 A^x = B(mod p). 分析 与整数的离散对数类似,只不过普通乘法换乘了矩阵乘法. 由于矩阵的求逆麻烦,使用 $A^{km-t} = B( ...
- js大文件分块上传断点续传demo
文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...
- nowcoder73E 白兔的刁难 单位根反演+NTT
感觉很套路? #include <bits/stdc++.h> #define ll long long #define setIO(s) freopen(s".in" ...
- 【CSS3】 新增属性
一. box-shadow(阴影效果) 使用: box-shadow: 20px 10px 0 #000; -moz-box-shadow: 20px 10px 0 #000; -webkit-box ...
- luogu 3466 对顶堆
显然答案是将一段区间全部转化成了其中位数这样的话,需要维护一个数据结构支持查询当前所有数中位数对顶堆 用两个堆将 < 中位数的数放入大根堆将 > 中位数的数放入小根堆这样就会存在删除操作 ...
- loj #137 and #6021
最小瓶颈路 加强版 重构树 最小生成树在合并 (x, y) 时,新建节点 z,link(x, z), link(y, z), 新建节点的权值为 w_{x,y}, 这样的 话任意两点的 answer 为 ...
- Unity 3d 实现物体跟随摄像机视野运动
https://blog.csdn.net/qq_31411825/article/details/61623857 Unity 3d 实现物体跟随摄像机视野运动Created by miccall ...
- 《挑战30天C++入门极限》新手入门:关于C++中的内联函数(inline)
新手入门:关于C++中的内联函数(inline) 在c++中,为了解决一些频繁调用的小函数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数. 可能说到这里,很 ...
- 贪心算法训练(四)——(HDU1050)Moving Tables
题目描述 在一个狭窄的走廊里将桌子从一个房间移动到另一个房间,走廊的宽度只能允许一个桌子通过.给出 t,表示有 t 组测试数据,再给出 n,表示要移动 n 个桌子.n 下面有 n 行,每行两个数字,表 ...
- linux rand application
code: #include <stdio.h> #include <stdlib.h> #include <time.h> #define random_1(a, ...