PID算法实现(c 语言)(来自老外)

2019-12-09 20:01发布

论坛里讲PID原理的挺多,但是讲算法的实现却比较少,或是比较难懂,今天网上找到一个老外写的PID C语言实现,P ,I ,D 各环节独立实现,还是比较好理解的。
  1. PID算法(c 语言)(来自老外)
  2. (2010-02-17 00:18:24)
  3. 转载
  4. #include <stdio.h>
  5. #include<math.h>
  6. //定义PID 的结构体
  7. struct _pid
  8. {
  9. int pv; //integer that contains the process value 过
  10. 程量
  11. int sp; //*integer that contains the set point   设
  12. 定值
  13. float integral; // 积分值 -- 偏差累计值
  14. float pgain;
  15. float igain;
  16. float dgain;
  17. int deadband;    //死区
  18. int last_error;
  19. };

  20. struct _pid warm,*pid;
  21. int process_point, set_point,dead_band; float p_gain, i_gain, d_gain,
  22. integral_val,new_integ;;

  23. //------------------------
  24. ----------------------
  25. pid_init DESCRIPTION This function initializes the
  26. pointers  in  the  _pid  structure  to  the  process  variable
  27. and the setpoint. *pv and *sp are integer pointers.
  28. //------------------------
  29. ----------------------

  30. void pid_init(struct _pid *warm, int process_point,
  31. int set_point)
  32. {
  33. struct _pid *pid;
  34. pid = warm;
  35. pid->pv = process_point;
  36. pid->sp = set_point;
  37. }

  38. //------------------------
  39. ----------------------pid_tune DESCRIPTION Sets the proportional gain
  40. (p_gain), integral gain (i_gain),
  41. derivitive  gain  (d_gain),  and  the  dead  band  (dead_band)
  42. of a pid control structure _pid.  

  43. 设定PID参数 ---- P,I,D,死区
  44. //------------------------
  45. ----------------------

  46. void pid_tune(struct _pid *pid, float p_gain, float
  47. i_gain, float d_gain, int dead_band)
  48. {
  49. pid->pgain = p_gain;
  50. pid->igain = i_gain;
  51. pid->dgain = d_gain;
  52. pid->deadband = dead_band;
  53. pid->integral= integral_val;
  54. pid->last_error=0;
  55. }

  56. //------------------------
  57. ---------------------- pid_setinteg DESCRIPTION Set a new value for the
  58. integral term of the pid equation.
  59. This is useful for setting the initial output of the
  60. pid controller at start up.

  61. 设定输出初始值
  62. //------------------------
  63. ----------------------

  64. void pid_setinteg(struct _pid *pid,float new_integ)
  65. {
  66. pid->integral = new_integ;
  67. pid->last_error = 0;
  68. }

  69. //------------------------
  70. ----------------------
  71. pid_bumpless DESCRIPTION Bumpless transfer
  72. algorithim.
  73. When suddenly changing setpoints, or when restarting
  74. the PID equation after an extended pause,
  75. the derivative of the equation can cause a bump in the controller output. This function will help smooth out
  76. that bump.
  77. The process value in *pv should be the updated just
  78. before this function is used.

  79. pid_bumpless 实现无扰切换
  80. 当突然改变设定值时,或重新启动后,将引起扰动输出。这
  81. 个函数将能实现平顺扰动, 在调用该函数之前需要先更新 PV值
  82. //------------------------
  83. ----------------------

  84. void pid_bumpless(struct _pid *pid)
  85. {
  86. pid->last_error = (pid->sp)-(pid->pv);  //设定值与反馈值偏差
  87. }

  88. //------------------------
  89. ----------------------
  90. pid_calc  DESCRIPTION  Performs  PID  calculations  for  the
  91. _pid structure *a. This function uses the positional form of the pid
  92. equation, and incorporates an integral windup
  93. prevention algorithim.
  94. Rectangular  integration  is  used,  so  this  function  must
  95. be repeated on a consistent time basis for accurate
  96. control.
  97. RETURN VALUE The new output value for the pid loop.
  98. USAGE #include "control.h"
  99. 本函数使用位置式PID计算方式,并且采取了积分饱和限制运算
  100. PID计算
  101. //------------------------
  102. ----------------------

  103. float pid_calc(struct _pid *pid)

  104. int err;
  105. float pterm, dterm, result, ferror;

  106. // 计算偏差
  107. err = (pid->sp) - (pid->pv);
  108. // 判断是否大于死区
  109. if (abs(err) > pid->deadband)
  110. {
  111. ferror = (float) err;   //do integer to float
  112. conversion only once 数据类型转换

  113. // 比例项
  114. pterm = pid->pgain * ferror;

  115. if (pterm > 100 || pterm < -100)
  116. {
  117. pid->integral = 0.0;
  118. }
  119. else
  120. {
  121. // 积分项
  122. pid->integral += pid->igain * ferror;

  123. // 输出为0--100%
  124. // 如果计算结果大于100,则等于100
  125. if (pid->integral > 100.0)
  126. { pid->integral = 100.0;
  127. }
  128. // 如果计算结果小于0.0,则等于0
  129. else if (pid->integral < 0.0)
  130. pid->integral = 0.0;

  131. }

  132. // 微分项
  133. dterm  =  ((float)(err  -  pid->last_error))  *  pid->dgain;

  134. result = pterm + pid->integral + dterm;
  135. }
  136. else
  137. result = pid->integral; // 在死区范围内,保持现有输出

  138. // 保存上次偏差
  139. pid->last_error = err;

  140. // 输出PID值(0-100)
  141. return (result); }
  142.   
  143. //------------------------
  144. ----------------------
  145. void main(void)
  146. {
  147. float display_value;
  148. int count=0;
  149. pid = &warm;

  150. // printf("Enter the values of Process point, Set
  151. point, P gain, I gain, D gain ");
  152. // scanf("%d%d%f%f%f", &process_point, &set_point,
  153. &p_gain, &i_gain, &d_gain);

  154. // 初始化参数
  155. process_point = 30;
  156. set_point = 40;
  157. p_gain = (float)(5.2);
  158. i_gain = (float)(0.77);
  159. d_gain = (float)(0.18);
  160. dead_band = 2;  
  161. integral_val =(float)(0.01);

  162. printf("The  values  of  Process  point,  Set  point,  P  gain,
  163. I gain, D gain ");
  164. printf(" %6d %6d %4f %4f %4f ", process_point,
  165. set_point, p_gain, i_gain, d_gain);
  166. printf("Enter the values of Process point ");
  167. while(count<=20)
  168. {
  169. scanf("%d",&process_point);

  170. // 设定PV,SP 值
  171. pid_init(&warm, process_point, set_point);

  172. // 初始化PID 参数值
  173. pid_tune(&warm, p_gain,i_gain,d_gain,dead_band);

  174. // 初始化PID 输出值
  175. pid_setinteg(&warm,0.0);
  176. //pid_setinteg(&warm,30.0);
  177. //Get input value for process point
  178. pid_bumpless(&warm);

  179. // how to display output
  180. display_value = pid_calc(&warm);

  181. printf("%f ", display_value);
  182. //printf(" %f%f%f%f",warm.pv,warm.sp,warm.igain,wa
  183. rm.dgain);

  184. count++;
  185. }
  186. }
复制代码PDF文档:

C语言PID算法.pdf (57.85 KB, 下载次数: 3882) 2013-7-15 22:12 上传 点击文件名下载附件
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
99条回答
summarize
1楼-- · 2019-12-09 20:22
本帖最后由 summarize 于 2013-9-28 23:53 编辑

老外的是位置式PID,我在网上找了增量式PID公式.如下:

△u=Kp*(e0-e1) + Ki*e0 + Kd*(e0 - 2*e1 + e2);
u += △u

e0为本次偏差; e1是上次偏差; e2是上上次偏差。u为本次输出。
actshuishan
2楼-- · 2019-12-09 22:20
标记学习!
zj_871112
3楼-- · 2019-12-10 01:12
好资料啊~收藏了
名海2012
4楼-- · 2019-12-10 04:10
 精彩回答 2  元偷偷看……
zydwh
5楼-- · 2019-12-10 07:18
好资料!
powermeter
6楼-- · 2019-12-10 13:03
mrk 不错的资料。

一周热门 更多>