1.根据我控制算法类文章中关于PID的理论的一些描述,同时也根据网络上一些其他的PID文章,以及自己最近一个项目的实践后,总结了几套基于C语言的PID算法,由于网络中很少有人进行分享完整的PID算法实现,我这里分享下。

(1)头文件,定义pid的结构体,类的概念,包含pid的属性和方法

  1. #ifndef __PID_H_
  2. #define __PID_H_
  3.  
  4. #include <stdint.h>
  5.  
  6. typedef struct _pid
  7. {
  8. int16_t set_value; // 给定值,rin(k)
  9. int16_t actual_value; // 实际值,反馈值,rout(k)
  10. int16_t err; // 偏差值,rin(k) - rout(k)
  11. int16_t err_last; // 上一次偏差值,rin(k - 1) - rout(k - 1)
  12. int16_t err_last_last; // 上一次上一次的偏差值,rin(k - 2) - rout(k - 2)
  13. float kp; // 比例系数
  14. float ki; // 积分系数
  15. float kd; // 微分系数
  16. float uk; // pid公式运算结果值
  17. float incremental_value; // 增量值
  18. float integral_value; // 积分值
  19. float umax; // uk的上限值,抗积分饱和用
  20. float umin; // uk的下限值,抗积分饱和用
  21. int16_t err_up_value; // 偏差上限值,积分分离用
  22. int16_t ki_k; // 积分的再次乘机系数,积分分离用
  23.  
  24. float out_value; //
  25.  
  26. float(*position_type)(struct _pid *ppid); // 位置型PID算法,无积分分离、无抗积分饱和
  27. float(*incremental_type)(struct _pid *ppid); // 增量型PID算法
  28. float(*integral_separation_type)(struct _pid *ppid); // 积分分离PID算法
  29. float(*int_sep_anti_sat_type)(struct _pid *ppid); // 积分分离 + 抗积分饱和PID算法
  30. }_pid_t;
  31.  
  32. _pid_t *pid_create(void);
  33.  
  34. extern _pid_t *pg_pid;
  35.  
  36. #endif

(2).c文件,包含头文件中4个PID算法的实现,包含位置型PID算法、增量型PID算法、积分分离PID算法、积分分离+抗饱和PID算法

  1. #include <stdlib.h>
  2. #include <string.h>
  3.  
  4. #include "pid.h"
  5.  
  6. #include "FreeRTOS.h"
  7. #include "task.h"
  8. #include "queue.h"
  9. #include "portmacro.h"
  10. #include "semphr.h"
  11.  
  12. #include "Debug.h"
  13.  
  14. /*************************************
  15. *
  16. * Funciton Name : pid_position_type
  17. * Function :位置型PID算法,无积分分离、无抗积分饱和
  18. * @note : 积分分离:能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
  19. * : 抗积分饱和:能解决执行器到达极限值时,但uk还在增大,使得系统进入饱和,进入饱和区的时间越长,当系统出现反向偏差,解决这个反向偏差的时间就会越长,此时系统会像失控一样。
  20. * :进入抗积分饱和,当uk超过上限时,积分向只累加负偏差,当uk超过下限时,积分项只累加正偏差。
  21. *
  22. × @param :pid
  23. *
  24. *
  25. * @return : uk
  26. *************************************/
  27. static float pid_position_type_f(struct _pid *ppid)
  28. {
  29. ppid->err = ppid->set_value - ppid->actual_value; // 偏差
  30.  
  31. ppid->integral_value += ppid->err; // 积分累加
  32.  
  33. ppid->uk = ppid->kp * ppid->err + ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
  34.  
  35. ppid->err_last = ppid->err;
  36.  
  37. return (ppid->uk);
  38. }
  39.  
  40. /*************************************
  41. *
  42. * Funciton Name : pid_incremental_type_f
  43. * Function :增量型PID算法
  44. * @note : 相较于位置型,因为与3个偏差相关,增强了系统稳定性
  45. *
  46. × @param :pid
  47. *
  48. *
  49. * @return : uk + 增量值
  50. *************************************/
  51. static float pid_incremental_type_f(struct _pid *ppid)
  52. {
  53. ppid->err = ppid->set_value - ppid->actual_value; // 偏差
  54.  
  55. //ppid->integral_value += ppid->err; // 积分累加
  56.  
  57. ppid->incremental_value = ppid->kp * ( ppid->err - ppid->err_last) + ppid->ki * ppid->err + ppid->kd * (ppid->err - 2 * ppid->err_last + ppid->err_last_last);
  58.  
  59. ppid->uk += ppid->incremental_value;
  60.  
  61. ppid->err_last_last = ppid->err_last;
  62. ppid->err_last = ppid->err;
  63.  
  64. return (ppid->uk);
  65. }
  66.  
  67. /*************************************
  68. *
  69. * Funciton Name : pid_integral_separation_type_f
  70. * Function :积分分离PID算法
  71. * @note : 能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
  72. *
  73. × @param :pid
  74. *
  75. *
  76. * @return : uk
  77. *************************************/
  78. static float pid_integral_separation_type_f(struct _pid *ppid)
  79. {
  80. ppid->err = ppid->set_value - ppid->actual_value; // 偏差
  81.  
  82. // 误差过大去除积分效果
  83. if ( abs(ppid->err) > ppid->err_up_value )
  84. {
  85. ppid->ki_k = 0;
  86. }
  87. else
  88. {
  89. ppid->ki_k = 1;
  90. ppid->integral_value += ppid->err; // 积分累加
  91. }
  92.  
  93. ppid->uk = ppid->kp * ppid->err + ppid->ki_k * ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
  94.  
  95. ppid->err_last = ppid->err;
  96.  
  97. return (ppid->uk);
  98. }
  99.  
  100. /*************************************
  101. *
  102. * Funciton Name : pid_int_sep_anti_sat_type_f
  103. * Function :积分分离 + 抗积分饱和PID算法
  104. * @note : 能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
  105. * : 抗积分饱和:能解决执行器到达极限值时,但uk还在增大,使得系统进入饱和,进入饱和区的时间越长,当系统出现反向偏差,解决这个反向偏差的时间就会越长,此时系统会像失控一样。
  106. * :进入抗积分饱和,当uk超过上限时,积分向只累加负偏差,当uk超过下限时,积分项只累加正偏差。
  107. *
  108. × @param :pid
  109. *
  110. *
  111. * @return : uk
  112. *************************************/
  113. static float pid_int_sep_anti_sat_type_f(struct _pid *ppid)
  114. {
  115. ppid->err = ppid->set_value - ppid->actual_value; // 偏差
  116.  
  117. Debug("ppid->err = %d\r\n", ppid->err);
  118.  
  119. if ( ppid->out_value > ppid->umax ) // 抗积分饱和
  120. {
  121. // 误差过大去除积分效果
  122. if ( abs(ppid->err) > ppid->err_up_value ) // 积分分离
  123. {
  124. ppid->ki_k = 0;
  125. }
  126. else
  127. {
  128. ppid->ki_k = 1;
  129.  
  130. if ( ppid->err < 0 )
  131. {
  132. ppid->integral_value += ppid->err; // 积分累加
  133. }
  134.  
  135. }
  136. }
  137. else if ( ppid->out_value < ppid->umin ) // 抗积分饱和
  138. {
  139. // 误差过大去除积分效果
  140. if ( abs(ppid->err) > ppid->err_up_value ) // 积分分离
  141. {
  142. ppid->ki_k = 0;
  143. }
  144. else
  145. {
  146. ppid->ki_k = 1;
  147.  
  148. if ( ppid->err > 0 )
  149. {
  150. ppid->integral_value += ppid->err; // 积分累加
  151. }
  152.  
  153. }
  154. }
  155. else
  156. {
  157. // 误差过大去除积分效果
  158. if ( abs(ppid->err) > ppid->err_up_value )
  159. {
  160. ppid->ki_k = 0;
  161. }
  162. else
  163. {
  164. ppid->ki_k = 1;
  165. ppid->integral_value += ppid->err; // 积分累加
  166. }
  167. }
  168.  
  169. ppid->uk = ppid->kp * ppid->err + ppid->ki_k * ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
  170.  
  171. ppid->err_last = ppid->err;
  172.  
  173. // if ( ppid->uk >= 0.07 && ppid->uk <= 1 )
  174. // {
  175. // ppid->uk = 1;
  176. // }
  177. //
  178. // if ( ppid->uk <= -0.07 && ppid->uk >= -1 )
  179. // {
  180. // ppid->uk = -1;
  181. // }
  182.  
  183. return (ppid->uk);
  184. }
  185.  
  186. /*************************************
  187. *
  188. * Funciton Name : pid_init
  189. * Function : pid实例构造
  190. *
  191. *
  192. *************************************/
  193. static void pid_init(_pid_t *ppid)
  194. {
  195. ppid->kp = 0.2;
  196. ppid->ki = 0.05;
  197. ppid->kd = 0;
  198.  
  199. ppid->umax = 4000;
  200. ppid->umin = 0;
  201.  
  202. ppid->position_type = pid_position_type_f;
  203. ppid->incremental_type = pid_incremental_type_f;
  204. ppid->integral_separation_type = pid_integral_separation_type_f;
  205. ppid->int_sep_anti_sat_type = pid_int_sep_anti_sat_type_f;
  206. }
  207.  
  208. /*************************************
  209. *
  210. * Funciton Name : pid_create
  211. * Function : pid实例创建
  212. * @author :
  213. *
  214. * @return : 返回pid实例
  215. *
  216. *************************************/
  217. _pid_t *pid_create(void)
  218. {
  219. _pid_t *ppid = (_pid_t *)pvPortMalloc(sizeof(_pid_t));
  220.  
  221. memset(ppid, 0, sizeof(_pid_t));
  222.  
  223. pid_init(ppid);
  224.  
  225. return ppid;
  226. }

(3)PID的实现算法有了,但还是要根据实际情况进行调试选取最适合的PID算法以及修改可能存在的不恰当的位置。

PID算法的C语言实现的更多相关文章

  1. PID算法(c 语言)(转)

    PID算法(c 语言)(来自老外) #include <stdio.h> #include<math.h> //定义PID 的结构体 struct _pid { int pv; ...

  2. PID算法(c 语言)(来自老外)

    #include <stdio.h> #include<math.h> //定义PID 的结构体 struct _pid { int pv; // integer that c ...

  3. PID控制算法的C语言实现三 位置型PID的C语言实现

    上一节中已经抽象出了位置性PID和增量型PID的数学表达式,这一节,重点讲解C语言代码的实现过程,算法的C语言实现过程具有一般性,通过PID算法的C语言实现,可以以此类推,设计其它算法的C语言实现. ...

  4. PID控制算法的C语言实现

    参考: PID控制器开发笔 浅谈位置式PID 专家PID控制在快速系统中的仿真及应用(这篇了论文介绍的积分分离PID.专家PID(脚本实现和simulink实现)很详细) PID控制算法的C语言实现一 ...

  5. 【转】位置式、增量式PID算法C语言实现

    位置式.增量式PID算法C语言实现 芯片:STM32F107VC 编译器:KEIL4 作者:SY 日期:2017-9-21 15:29:19 概述 PID 算法是一种工控领域常见的控制算法,用于闭环反 ...

  6. PID算法(C语言)

    /************ PID算法(C语言) ************/ #include <stdio.h> #include<math.h> struct _pid { ...

  7. PID控制算法的C语言实现十一  模糊算法简介

    在PID控制算法的C语言实现九中,文章已经对模糊PID的实质做了一个简要说明.本来打算等到完成毕业设计,工作稳定了再着力完成剩下的部分.鉴于网友的要求和信任,抽出时间来,对模糊PID做一个较为详细的论 ...

  8. PID控制算法的C语言实现二 PID算法的离散化

    上一节中,我论述了PID算法的基本形式,并对其控制过程的实现有了一个简要的说明,通过上一节的总结,基本已经可以明白PID控制的过程.这一节中先继续上一节内容补充说明一下. 1.说明一下反馈控制的原理, ...

  9. PID控制算法的C语言实现一 PID算法原理

    本系列是转载............. 全部的程序有一个共同点:就是我没认真去调pid的参数 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设 ...

随机推荐

  1. JVM系列【6】GC与调优2.md

    JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 了解HotSpot常用命令行参数 JVM的命令行参数参考: https:/ ...

  2. nginx集群:nginx配置负载均衡集群(nginx1.18.0)

    一,nginx的负载均衡集群的特点: 1,nginx集群和lvs的不同? lvs集群:工作在第4层(传输层) nginx集群:工作在第7层(应用层) lvs集群:性能更强 nginx集群:功能更强:可 ...

  3. ansible的copy模块应用(ansible 2.9.5)

    一,copy模块的作用: 复制文件到受控的远程主机 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest 对应的源码可以访问 ...

  4. 解决selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid 'expiry'

    解决selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid 'expiry'   ...

  5. vue实现循环滚动列表vue-seamless-scroll

    1.安装 vue-seamless-scroll   实例文档链接 cnpm install vue-seamless-scroll --save 2.文件中引入,组件配置 import vueSea ...

  6. update不能直接使用select的返回结果

    update不能直接使用select的返回结果,这是会报错的,这是SQL的语法规定的,若想在update中与select结合使用,sql需要这样写: 1.其中field1,field2为表中的字段名 ...

  7. naicat如何查看表关系

    1.navict版本为:navict premium https://www.php.cn/tool/navicat/427617.html 参考上面链接 2. 这个版本的 目前就这些,后续进行补充

  8. ThreadLocal与Thread与Runable之间的关系

    ThreadLocal继承Object,相当于没继承任何特殊的. ThreadLocal没有实现任何接口. ThreadLocal并不是一个Thread,而是Thread的局部变量

  9. list.add方法参数详解

  10. 浅谈1——用Eclipse调试JAVA程序

    本篇博客主要介绍如何用Eclipse调试简单的JAVA程序. 1.如下图,一个简单的JAVA程序  2.设置断点. 方法:选中需设置断点的行代码,按快捷键Ctrl+Shift+B,设置断点: 断点设置 ...