注册 登录
查看: 6882|回复: 47

PID算法实现(c 语言)

  [复制链接]
发表于 2013-9-7 13:36:03 | 显示全部楼层 |阅读模式

  1. #include <stdio.h>
  2. #include<math.h>

  3. //定义PID 的结构体
  4. struct _pid
  5. {
  6.     int pv; //integer that contains the process value 过程量
  7.     int sp; //*integer that contains the set point   设定值
  8.     float integral; // 积分值 -- 偏差累计值
  9.     float pgain;
  10.     float igain;
  11.     float dgain;
  12.     int deadband;    //死区
  13.     int last_error;
  14. };

  15. struct _pid warm,*pid;
  16. int process_point, set_point,dead_band; float p_gain, i_gain, d_gain,integral_val,new_integ;;

  17. /*----------------------------------------------
  18. pid_init DESCRIPTION This function initializes the
  19. pointers  in  the  _pid  structure  to  the  process  variable
  20. and the setpoint. *pv and *sp are integer pointers.
  21. ---------------------------------------------- */

  22. void pid_init(struct _pid *warm, int process_point, int set_point)
  23. {
  24.     struct _pid *pid;
  25.     pid = warm;
  26.     pid->pv = process_point;
  27.     pid->sp = set_point;
  28. }

  29. /*----------------------------------------------
  30. pid_tune DESCRIPTION Sets the proportional gain
  31. (p_gain), integral gain (i_gain),
  32. derivitive  gain  (d_gain),  and  the  dead  band  (dead_band)
  33. of a pid control structure _pid.  

  34. 设定PID参数 ---- P,I,D,死区
  35. ---------------------------------------------- */

  36. void pid_tune(struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band)
  37. {
  38.     pid->pgain = p_gain;
  39.     pid->igain = i_gain;
  40.     pid->dgain = d_gain;
  41.     pid->deadband = dead_band;
  42.     pid->integral= integral_val;
  43.     pid->last_error=0;
  44. }

  45. /*----------------------------------------------
  46. pid_setinteg DESCRIPTION Set a new value for the
  47. integral term of the pid equation.
  48. This is useful for setting the initial output of the
  49. pid controller at start up.

  50. 设定输出初始值
  51. ---------------------------------------------- */

  52. void pid_setinteg(struct _pid *pid,float new_integ)
  53. {
  54.     pid->integral = new_integ;
  55.     pid->last_error = 0;
  56. }

  57. /*----------------------------------------------
  58. pid_bumpless DESCRIPTION Bumpless transfer
  59. algorithim.
  60. When suddenly changing setpoints, or when restarting
  61. the PID equation after an extended pause,
  62. the derivative of the equation can cause a bump in the controller output. This function will help smooth out
  63. that bump.
  64. The process value in *pv should be the updated just
  65. before this function is used.

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

  70. void pid_bumpless(struct _pid *pid)
  71. {
  72.     pid->last_error = (pid->sp)-(pid->pv);  //设定值与反馈值偏差
  73. }

  74. /*----------------------------------------------
  75. pid_calc  DESCRIPTION  Performs  PID  calculations  for  the
  76. _pid structure *a. This function uses the positional form of the pid
  77. equation, and incorporates an integral windup
  78. prevention algorithim.
  79. Rectangular  integration  is  used,  so  this  function  must
  80. be repeated on a consistent time basis for accurate
  81. control.
  82. RETURN VALUE The new output value for the pid loop.
  83. USAGE #include "control.h"
  84. 本函数使用位置式PID计算方式,并且采取了积分饱和限制运算
  85. PID计算
  86. ----------------------------------------------*/

  87. float pid_calc(struct _pid *pid)
  88. {
  89. int err;
  90. float pterm, dterm, result, ferror;

  91. // 计算偏差
  92. err = (pid->sp) - (pid->pv);
  93. // 判断是否大于死区
  94.     if (abs(err) > pid->deadband)
  95.     {
  96.         ferror = (float) err;   //do integer to float conversion only once 数据类型转换
  97.          
  98.         // 比例项
  99.         pterm = pid->pgain * ferror;
  100.          
  101.         if (pterm > 100 || pterm < -100)
  102.         {
  103.             pid->integral = 0.0;
  104.         }
  105.         else
  106.         {
  107.             // 积分项
  108.             pid->integral += pid->igain * ferror;
  109.             
  110.             // 输出为0--100%
  111.             // 如果计算结果大于100,则等于100
  112.             if (pid->integral > 100.0)
  113.             {
  114.                 pid->integral = 100.0;
  115.             }
  116.             // 如果计算结果小于0.0,则等于0
  117.             else if (pid->integral < 0.0)
  118.             {
  119.                 pid->integral = 0.0;
  120.             }
  121.          
  122.         }
  123.      
  124.         // 微分项
  125.         dterm  =  ((float)(err  -  pid->last_error))  *  pid->dgain;
  126.          
  127.         result = pterm + pid->integral + dterm;
  128.     }
  129.     else
  130.     {
  131.         result = pid->integral; // 在死区范围内,保持现有输出
  132.     }
  133.      
  134.     // 保存上次偏差
  135.     pid->last_error = err;
  136.      
  137.     // 输出PID值(0-100)
  138.     return (result);
  139. }
  140.   
  141. //----------------------------------------------
  142. void main(void)
  143. {
  144.     float display_value;
  145.     int count=0;
  146.     pid = &warm;
  147.      
  148.     // printf("Enter the values of Process point, Set point, P gain, I gain, D gain \n");
  149.     // scanf("%d%d%f%f%f", &process_point, &set_point,&p_gain, &i_gain, &d_gain);
  150.      
  151.     // 初始化参数
  152.     process_point = 30;
  153.     set_point = 40;
  154.     p_gain = (float)(5.2);
  155.     i_gain = (float)(0.77);
  156.     d_gain = (float)(0.18);
  157.     dead_band = 2;  
  158.     integral_val =(float)(0.01);
  159.      
  160.     printf("The  values  of  Process  point,  Set  point,  P  gain, I gain, D gain \n");
  161.     printf(" %6d %6d %4f %4f %4f\n", process_point,
  162.     set_point, p_gain, i_gain, d_gain);
  163.     printf("Enter the values of Process point\n");
  164.     while(count<=20)
  165.     {
  166.         scanf("%d",&process_point);
  167.          
  168.         // 设定PV,SP 值
  169.         pid_init(&warm, process_point, set_point);
  170.          
  171.         // 初始化PID 参数值
  172.         pid_tune(&warm, p_gain,i_gain,d_gain,dead_band);
  173.          
  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.          
  180.         // how to display output
  181.         display_value = pid_calc(&warm);
  182.          
  183.         printf("%f\n", display_value);
  184.         //printf("\n%f%f%f%f",warm.pv,warm.sp,warm.igain,wa
  185.         rm.dgain);
  186.          
  187.         count++;
  188.     }
  189. }

本帖被以下淘专辑推荐:

回复

使用道具 举报

发表于 2013-10-17 22:40:33 | 显示全部楼层
不错,怎么没人顶啊?
回复 支持 2 反对 0

使用道具 举报

发表于 2013-11-21 21:54:01 | 显示全部楼层
顶起来,很有用的东西。
回复 支持 反对

使用道具 举报

发表于 2014-4-28 21:53:19 | 显示全部楼层
这么好 顶一顶
回复 支持 反对

使用道具 举报

发表于 2014-7-11 03:53:38 | 显示全部楼层
帅呆了,赞一个
回复 支持 反对

使用道具 举报

发表于 2014-7-11 08:07:20 | 显示全部楼层
走过路过,不能错过
回复 支持 反对

使用道具 举报

发表于 2014-11-22 20:07:19 | 显示全部楼层
今天再看,受教了。
回复 支持 反对

使用道具 举报

发表于 2014-11-22 20:36:39 | 显示全部楼层
赞一个!
回复 支持 反对

使用道具 举报

发表于 2014-12-16 10:24:26 | 显示全部楼层
make1   好贴要顶!!
回复 支持 反对

使用道具 举报

发表于 2014-12-30 23:22:40 | 显示全部楼层
我有点不理解的是,i是积分,d是微分,但是在我们程序里的运用需要用到积分微分的运算吗。
回复 支持 反对

使用道具 举报

发表于 2014-12-31 08:20:21 | 显示全部楼层
顶起来                              
回复 支持 反对

使用道具 举报

发表于 2015-1-7 15:09:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2015-1-7 17:22:18 | 显示全部楼层
虽然不懂,不过蛮高大上的感觉

回复 支持 反对

使用道具 举报

发表于 2015-1-23 19:30:13 | 显示全部楼层
学习学习
回复 支持 反对

使用道具 举报

发表于 2015-1-23 21:13:46 | 显示全部楼层
怒赞
回复 支持 反对

使用道具 举报

发表于 2015-1-27 14:57:57 | 显示全部楼层
顶一下!
回复 支持 反对

使用道具 举报

发表于 2015-1-28 14:53:10 | 显示全部楼层
帮顶~~~~~~~~~~~
回复 支持 反对

使用道具 举报

发表于 2015-4-6 01:16:03 | 显示全部楼层
每次循环都初始化 微分量总是0 积分量也没累加起来 main函数的功能是什么
回复 支持 反对

使用道具 举报

发表于 2015-4-19 19:33:33 | 显示全部楼层
很棒
回复 支持 反对

使用道具 举报

发表于 2015-4-19 23:11:55 | 显示全部楼层
顶,拿来主义,
回复 支持 反对

使用道具 举报

发表于 2015-4-19 23:39:03 | 显示全部楼层
顶起来
回复 支持 反对

使用道具 举报

发表于 2015-5-15 19:34:44 | 显示全部楼层
顶起
回复 支持 反对

使用道具 举报

发表于 2015-10-2 01:48:12 | 显示全部楼层
很不错的东西,留着备用
回复 支持 反对

使用道具 举报

发表于 2015-10-27 22:41:51 | 显示全部楼层
赞,谢谢分享
回复 支持 反对

使用道具 举报

发表于 2015-11-6 16:14:26 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

发表于 2015-11-11 02:27:54 | 显示全部楼层
太好了
回复 支持 反对

使用道具 举报

发表于 2015-11-18 12:44:45 | 显示全部楼层
强烈支持
回复 支持 反对

使用道具 举报

发表于 2015-11-20 02:29:04 | 显示全部楼层
学习了,顶!!!
回复 支持 反对

使用道具 举报

发表于 2015-11-23 18:20:16 | 显示全部楼层

void pid_init(struct _pid *warm, int process_point, int set_point)

27.
{

28.
    struct _pid *pid;

29.
    pid = warm;

30.
    pid->pv = process_point;

31.
    pid->sp = set_point;

32.
}


    struct _pid *pid; 定义这个变量干什么,还有局部变量和全局变量都一样啦
回复 支持 反对

使用道具 举报

发表于 2015-11-29 21:19:20 | 显示全部楼层
顶一个
回复 支持 反对

使用道具 举报

发表于 2015-11-30 19:07:08 | 显示全部楼层
真棒!!!
回复 支持 反对

使用道具 举报

发表于 2015-12-3 15:05:56 | 显示全部楼层
6666
回复 支持 反对

使用道具 举报

发表于 2016-1-14 09:55:04 | 显示全部楼层
看一下资料
回复 支持 反对

使用道具 举报

发表于 2016-1-16 19:40:29 | 显示全部楼层
好帖好帖!
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

发表于 2016-1-21 10:17:37 | 显示全部楼层
标记下,谢谢楼主。。。
回复 支持 反对

使用道具 举报

发表于 2016-3-5 21:42:35 | 显示全部楼层
顶一个
回复 支持 反对

使用道具 举报

发表于 2016-3-26 14:59:20 | 显示全部楼层
666666666666666
回复 支持 反对

使用道具 举报

发表于 2016-4-6 12:51:49 | 显示全部楼层
66666
回复 支持 反对

使用道具 举报

发表于 2016-4-16 11:40:19 | 显示全部楼层
怎么感觉这么复杂,比自己写的难多了
回复 支持 反对

使用道具 举报

发表于 2016-5-7 21:20:36 | 显示全部楼层
顶。。顶。。学习学习
回复 支持 反对

使用道具 举报

发表于 2016-5-8 09:06:09 | 显示全部楼层
用结构体的好处是?
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

发表于 2016-5-18 17:55:23 | 显示全部楼层
谢谢楼主分享,顶一个
回复 支持 反对

使用道具 举报

发表于 2016-7-21 09:18:36 | 显示全部楼层
可以给解释一下吗?
回复 支持 反对

使用道具 举报

发表于 2016-8-11 21:51:28 | 显示全部楼层
小白报道
回复 支持 反对

使用道具 举报

发表于 2016-10-12 14:04:22 | 显示全部楼层
小白报道
回复 支持 反对

使用道具 举报

发表于 2016-10-12 20:49:01 | 显示全部楼层
好厉害
回复 支持 反对

使用道具 举报

发表于 2016-10-14 17:30:10 | 显示全部楼层
小白,不懂
回复 支持 反对

使用道具 举报

发表于 2016-10-16 19:39:05 | 显示全部楼层
这个和增量式PID有什么不同呢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回列表 返回顶部