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

1、问题所在

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

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

2、解决方案

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

3、代码

  1. /*working variables*/
  2. unsigned long lastTime;
  3. double InputOutputSetpoint;
  4. double ITermlastInput;
  5. double kpkikd;
  6. int SampleTime = ; //1 sec
  7. double outMinoutMax;
  8. bool inAuto = false;
  9.  
  10. #define MANUAL 0
  11. #define AUTOMATIC 1
  12.  
  13. void Compute()
  14. {
  15. if(!inAuto) return;
  16. unsigned long now = millis();
  17. int timeChange = (now - lastTime);
  18. if(timeChange>=SampleTime)
  19. {
  20. /*Compute all the working error variables*/
  21. double error = Setpoint - Input;
  22. ITerm+= (ki * error);
  23. if(ITerm> outMax) ITerm= outMax;
  24. else if(ITerm< outMin) ITerm= outMin;
  25. double dInput = (Input - lastInput);
  26.  
  27. /*Compute PID Output*/
  28. Output = kp * error + ITerm- kd * dInput;
  29. if(Output> outMax) Output = outMax;
  30. else if(Output < outMin) Output = outMin;
  31.  
  32. /*Remember some variables for next time*/
  33. lastInput = Input;
  34. lastTime = now;
  35. }
  36. }
  37.  
  38. void SetTunings(double Kpdouble Kidouble Kd)
  39. {
  40. double SampleTimeInSec = ((double)SampleTime)/;
  41. kp = Kp;
  42. ki = Ki * SampleTimeInSec;
  43. kd = Kd / SampleTimeInSec;
  44. }
  45.  
  46. void SetSampleTime(int NewSampleTime)
  47. {
  48. if (NewSampleTime > )
  49. {
  50. double ratio = (double)NewSampleTime
  51. / (double)SampleTime;
  52. ki *= ratio;
  53. kd /= ratio;
  54. SampleTime = (unsigned long)NewSampleTime;
  55. }
  56. }
  57.  
  58. void SetOutputLimits(double Mindouble Max)
  59. {
  60. if(Min > Max) return;
  61. outMin = Min;
  62. outMax = Max;
  63.  
  64. if(Output > outMax) Output = outMax;
  65. else if(Output < outMin) Output = outMin;
  66.  
  67. if(ITerm> outMax) ITerm= outMax;
  68. else if(ITerm< outMin) ITerm= outMin;
  69. }
  70.  
  71. void SetMode(int Mode)
  72. {
  73. bool newAuto = (Mode == AUTOMATIC);
  74. if(newAuto && !inAuto)
  75. { /*we just went from manual to auto*/
  76. Initialize();
  77. }
  78. inAuto = newAuto;
  79. }
  80.  
  81. void Initialize()
  82. {
  83. lastInput = Input;
  84. ITerm = Output;
  85. if(ITerm> outMax) ITerm= outMax;
  86. else if(ITerm< outMin) ITerm= outMin;
  87. }

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

4、最终结果

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

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

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

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

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

 欢迎关注:

改进初学者的PID-初始化的更多相关文章

  1. 改进初学者的PID-介绍

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  2. 改进初学者的PID-正反作用

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  3. 改进初学者的PID-修改整定参数

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  4. 改进初学者的PID-采样时间

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  5. 改进初学者的PID-测量的比例编码

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  6. 改进初学者的PID-积分饱和

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  7. 改进初学者的PID-测量的比例介绍

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  8. 改进初学者的PID-手自动切换

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

  9. 改进初学者的PID-微分冲击

    最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...

随机推荐

  1. Tarjan算法分解强连通分量(附详细参考文章)

    Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...

  2. list去重,String[]去重,String[]去空,StringBuffer去重,并且以','隔开,list拆分

    1.// 删除ArrayList中重复元素 public static void removeDuplicate(List list) { HashSet h = new HashSet(list); ...

  3. 性能:Transform层面

    数据处理的并行度 1.BlockRDD的分区数 (1)通过Receiver接受数据的特点决定 (2)也可以自己通过repartition设置 2.ShuffleRDD的分区数 (1)默认的分区数为sp ...

  4. 线程池的使用(ThreadPoolExecutor详解)

    为什么要使用线程池? 线程是一个操作系统概念.操作系统负责这个线程的创建.挂起.运行.阻塞和终结操作.而操作系统创建线程.切换线程状态.终结线程都要进行CPU调度——这是一个耗费时间和系统资源的事情. ...

  5. flask + websocket实现简单的单聊和群聊

    单聊 from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHand ...

  6. c#语言学习笔记(1)

    环境:VS Express 2013 for Desktop 也可以vs社区版,不过学习的话,Express本版做一些小的上位机工具应该是够用了学习的网站:https://www.runoob.com ...

  7. lambda()函数

    lambda lambda原型为:lambda 参数:操作(参数) lambda函数也叫匿名函数,即没有具体名称的函数,它允许快速定义单行函数,可以用在任何需要函数的地方.这区别于def定义的函数. ...

  8. C#中ref和out的原理

    去年在CSDN上写的,现在把它搬过来. 一.引发问题 用了那么久的 ref 和 out ,你真的了解它们是如何使得实参与形参的值保持同步的吗? 二.研究前提 要研究这个问题,前提是要了解 C# 中方法 ...

  9. Java 用Jackson进行json和object之间的转换(并解决json中存在新增多余字段的问题)

    1.添加jackson库 如果是maven工程,需要在pom.xml中添加jackson的依赖: <dependency>      <groupId>com.fasterxm ...

  10. Redis存储Sortedset

    与set相比Sortedset多了一个数字与set中的各个元素相关联. 存储结构: 1.添加元素: 添加元素的时候元素一定不能相同,如果已存在该元素,表示插入失败返回0,成功返回1,但是不同元素的数字 ...