最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner's-pid-initialization/

1、问题所在

  在前一节中,我们实现了关闭和打开 PID 的功能。我们将其关闭,但现在让我们来看看当我们重新打开它时会发生什么:

  呵!PID跳回到它发送的最后一个输出值,然后从那里开始调整。这将导致我们不希望出现的输入颠簸。

2、解决方案

  这个很容易解决。因为我们现在知道什么时候打开 (从手动到自动),我们只需为一个平稳的过渡做一些初始化。这意味着对2个工作变量的存储 (积分项和最后的输入项) 进行处理,以防止输出跳转。

3、代码

 /*working variables*/
unsigned long lastTime;
double Input,Output,Setpoint;
double ITerm,lastInput;
double kp,ki,kd;
int SampleTime = ; //1 sec
double outMin,outMax;
bool inAuto = false; #define MANUAL 0
#define AUTOMATIC 1 void Compute()
{
if(!inAuto) return;
unsigned long now = millis();
int timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double error = Setpoint - Input;
ITerm+= (ki * error);
if(ITerm> outMax) ITerm= outMax;
else if(ITerm< outMin) ITerm= outMin;
double dInput = (Input - lastInput); /*Compute PID Output*/
Output = kp * error + ITerm- kd * dInput;
if(Output> outMax) Output = outMax;
else if(Output < outMin) Output = outMin; /*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;
}
} void SetOutputLimits(double Min,double Max)
{
if(Min > Max) return;
outMin = Min;
outMax = Max; if(Output > outMax) Output = outMax;
else if(Output < outMin) Output = outMin; if(ITerm> outMax) ITerm= outMax;
else if(ITerm< outMin) ITerm= outMin;
} void SetMode(int Mode)
{
bool newAuto = (Mode == AUTOMATIC);
if(newAuto && !inAuto)
{ /*we just went from manual to auto*/
Initialize();
}
inAuto = newAuto;
} void Initialize()
{
lastInput = Input;
ITerm = Output;
if(ITerm> outMax) ITerm= outMax;
else if(ITerm< outMin) ITerm= outMin;
}

  我们修改了 SetMode (...) 以检测从手动到自动的转换,并添加了初始化功能。它通过设置“积分项=输出”来处理积分项,“最后输入=输入”以防止微分激增。比例项不依赖于过去的任何信息,因此不需要任何初始化。

4、最终结果

  我们从上面的图表中看到,正确的初始化会导致从手动到自动的无扰动切换,这正是我们所追求的。

5、更新:为什么不 ITerm=0

  我最近收到了很多问题,问为什么我没有把 ITerm=0 设置为初始化。作为答案,我请您考虑以下方案:PID是手动的,用户已将输出设置为50。一段时间后,该过程稳定到75.2 的输入。用户将设置点75.2 打开 PID。会发生什么事?

  我认为,切换到自动后,输出值应该保持在50。由于 P 和 D 项将为零,因此发生这种情况的唯一方法是将 ITerm项初始化为“输出”值。

  如果您处于需要输出初始化为零的情况,则无需更改上面的代码。在将 PID 从“手动”转换为“自动”之前,只需在调用例程中设置Output=0。

 欢迎关注:

最新文章

  1. mysql语句查询练习
  2. PHP多维数组根据其中一个字段的值排序
  3. ZipArchive之C++编译和调用
  4. 可视化工具solo show
  5. ps前端切图常用快捷键
  6. oracle错误码
  7. AutoInvoice in Oracle Apps R12
  8. SQL Server 索引的自动维护 &lt;第十三篇&gt;
  9. Android 简介:Android SDK 和开发框架简介
  10. webots自学笔记(一)软件界面和简单模型仿真
  11. 模块(一)——re模块
  12. Node.js安装和简介
  13. [MongoDB] MongoDB管理:使用killOp干掉Long Running Operation
  14. 详解java中的byte类型
  15. 再战android-语音识别2(修改配置)
  16. LOJ #143. 质数判定
  17. ios常用的字符串NSString自动释放理解
  18. Hibernate常见优化策略
  19. asp.net中&lt;input type=button&gt;无法调用后台函数
  20. sql注入一点小心得

热门文章

  1. Welcome to GnuPG 2.2
  2. D. Zero Quantity Maximization ( Codeforces Round #544 (Div. 3) )
  3. 如何使用git,进行项目的管理
  4. 深度学习Keras框架笔记之AutoEncoder类
  5. Laravel —— 多模块开发
  6. python - django 使用ajax将图片上传到服务器并渲染到前端
  7. junit4的初级用法
  8. mariadb启动不了
  9. GoCN每日新闻(2019-10-16)
  10. 深搜的剪枝技巧(三)——Sticks(可行性剪枝、上下界剪枝、最优性剪枝)