PID算法的C语言实现
1.根据我控制算法类文章中关于PID的理论的一些描述,同时也根据网络上一些其他的PID文章,以及自己最近一个项目的实践后,总结了几套基于C语言的PID算法,由于网络中很少有人进行分享完整的PID算法实现,我这里分享下。
(1)头文件,定义pid的结构体,类的概念,包含pid的属性和方法
- #ifndef __PID_H_
- #define __PID_H_
- #include <stdint.h>
- typedef struct _pid
- {
- int16_t set_value; // 给定值,rin(k)
- int16_t actual_value; // 实际值,反馈值,rout(k)
- int16_t err; // 偏差值,rin(k) - rout(k)
- int16_t err_last; // 上一次偏差值,rin(k - 1) - rout(k - 1)
- int16_t err_last_last; // 上一次上一次的偏差值,rin(k - 2) - rout(k - 2)
- float kp; // 比例系数
- float ki; // 积分系数
- float kd; // 微分系数
- float uk; // pid公式运算结果值
- float incremental_value; // 增量值
- float integral_value; // 积分值
- float umax; // uk的上限值,抗积分饱和用
- float umin; // uk的下限值,抗积分饱和用
- int16_t err_up_value; // 偏差上限值,积分分离用
- int16_t ki_k; // 积分的再次乘机系数,积分分离用
- float out_value; //
- float(*position_type)(struct _pid *ppid); // 位置型PID算法,无积分分离、无抗积分饱和
- float(*incremental_type)(struct _pid *ppid); // 增量型PID算法
- float(*integral_separation_type)(struct _pid *ppid); // 积分分离PID算法
- float(*int_sep_anti_sat_type)(struct _pid *ppid); // 积分分离 + 抗积分饱和PID算法
- }_pid_t;
- _pid_t *pid_create(void);
- extern _pid_t *pg_pid;
- #endif
(2).c文件,包含头文件中4个PID算法的实现,包含位置型PID算法、增量型PID算法、积分分离PID算法、积分分离+抗饱和PID算法
- #include <stdlib.h>
- #include <string.h>
- #include "pid.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "portmacro.h"
- #include "semphr.h"
- #include "Debug.h"
- /*************************************
- *
- * Funciton Name : pid_position_type
- * Function :位置型PID算法,无积分分离、无抗积分饱和
- * @note : 积分分离:能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
- * : 抗积分饱和:能解决执行器到达极限值时,但uk还在增大,使得系统进入饱和,进入饱和区的时间越长,当系统出现反向偏差,解决这个反向偏差的时间就会越长,此时系统会像失控一样。
- * :进入抗积分饱和,当uk超过上限时,积分向只累加负偏差,当uk超过下限时,积分项只累加正偏差。
- *
- × @param :pid
- *
- *
- * @return : uk
- *************************************/
- static float pid_position_type_f(struct _pid *ppid)
- {
- ppid->err = ppid->set_value - ppid->actual_value; // 偏差
- ppid->integral_value += ppid->err; // 积分累加
- ppid->uk = ppid->kp * ppid->err + ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
- ppid->err_last = ppid->err;
- return (ppid->uk);
- }
- /*************************************
- *
- * Funciton Name : pid_incremental_type_f
- * Function :增量型PID算法
- * @note : 相较于位置型,因为与3个偏差相关,增强了系统稳定性
- *
- × @param :pid
- *
- *
- * @return : uk + 增量值
- *************************************/
- static float pid_incremental_type_f(struct _pid *ppid)
- {
- ppid->err = ppid->set_value - ppid->actual_value; // 偏差
- //ppid->integral_value += ppid->err; // 积分累加
- 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);
- ppid->uk += ppid->incremental_value;
- ppid->err_last_last = ppid->err_last;
- ppid->err_last = ppid->err;
- return (ppid->uk);
- }
- /*************************************
- *
- * Funciton Name : pid_integral_separation_type_f
- * Function :积分分离PID算法
- * @note : 能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
- *
- × @param :pid
- *
- *
- * @return : uk
- *************************************/
- static float pid_integral_separation_type_f(struct _pid *ppid)
- {
- ppid->err = ppid->set_value - ppid->actual_value; // 偏差
- // 误差过大去除积分效果
- if ( abs(ppid->err) > ppid->err_up_value )
- {
- ppid->ki_k = 0;
- }
- else
- {
- ppid->ki_k = 1;
- ppid->integral_value += ppid->err; // 积分累加
- }
- ppid->uk = ppid->kp * ppid->err + ppid->ki_k * ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
- ppid->err_last = ppid->err;
- return (ppid->uk);
- }
- /*************************************
- *
- * Funciton Name : pid_int_sep_anti_sat_type_f
- * Function :积分分离 + 抗积分饱和PID算法
- * @note : 能解决初期系统偏差值大,累加到积分项中,引起系统超调、振荡问题。积分是为了消除静态误差的,应在误差在小范围时引入积分
- * : 抗积分饱和:能解决执行器到达极限值时,但uk还在增大,使得系统进入饱和,进入饱和区的时间越长,当系统出现反向偏差,解决这个反向偏差的时间就会越长,此时系统会像失控一样。
- * :进入抗积分饱和,当uk超过上限时,积分向只累加负偏差,当uk超过下限时,积分项只累加正偏差。
- *
- × @param :pid
- *
- *
- * @return : uk
- *************************************/
- static float pid_int_sep_anti_sat_type_f(struct _pid *ppid)
- {
- ppid->err = ppid->set_value - ppid->actual_value; // 偏差
- Debug("ppid->err = %d\r\n", ppid->err);
- if ( ppid->out_value > ppid->umax ) // 抗积分饱和
- {
- // 误差过大去除积分效果
- if ( abs(ppid->err) > ppid->err_up_value ) // 积分分离
- {
- ppid->ki_k = 0;
- }
- else
- {
- ppid->ki_k = 1;
- if ( ppid->err < 0 )
- {
- ppid->integral_value += ppid->err; // 积分累加
- }
- }
- }
- else if ( ppid->out_value < ppid->umin ) // 抗积分饱和
- {
- // 误差过大去除积分效果
- if ( abs(ppid->err) > ppid->err_up_value ) // 积分分离
- {
- ppid->ki_k = 0;
- }
- else
- {
- ppid->ki_k = 1;
- if ( ppid->err > 0 )
- {
- ppid->integral_value += ppid->err; // 积分累加
- }
- }
- }
- else
- {
- // 误差过大去除积分效果
- if ( abs(ppid->err) > ppid->err_up_value )
- {
- ppid->ki_k = 0;
- }
- else
- {
- ppid->ki_k = 1;
- ppid->integral_value += ppid->err; // 积分累加
- }
- }
- ppid->uk = ppid->kp * ppid->err + ppid->ki_k * ppid->ki * ppid->integral_value + ppid->kd * (ppid->err - ppid->err_last);
- ppid->err_last = ppid->err;
- // if ( ppid->uk >= 0.07 && ppid->uk <= 1 )
- // {
- // ppid->uk = 1;
- // }
- //
- // if ( ppid->uk <= -0.07 && ppid->uk >= -1 )
- // {
- // ppid->uk = -1;
- // }
- return (ppid->uk);
- }
- /*************************************
- *
- * Funciton Name : pid_init
- * Function : pid实例构造
- *
- *
- *************************************/
- static void pid_init(_pid_t *ppid)
- {
- ppid->kp = 0.2;
- ppid->ki = 0.05;
- ppid->kd = 0;
- ppid->umax = 4000;
- ppid->umin = 0;
- ppid->position_type = pid_position_type_f;
- ppid->incremental_type = pid_incremental_type_f;
- ppid->integral_separation_type = pid_integral_separation_type_f;
- ppid->int_sep_anti_sat_type = pid_int_sep_anti_sat_type_f;
- }
- /*************************************
- *
- * Funciton Name : pid_create
- * Function : pid实例创建
- * @author :
- *
- * @return : 返回pid实例
- *
- *************************************/
- _pid_t *pid_create(void)
- {
- _pid_t *ppid = (_pid_t *)pvPortMalloc(sizeof(_pid_t));
- memset(ppid, 0, sizeof(_pid_t));
- pid_init(ppid);
- return ppid;
- }
(3)PID的实现算法有了,但还是要根据实际情况进行调试选取最适合的PID算法以及修改可能存在的不恰当的位置。
PID算法的C语言实现的更多相关文章
- PID算法(c 语言)(转)
PID算法(c 语言)(来自老外) #include <stdio.h> #include<math.h> //定义PID 的结构体 struct _pid { int pv; ...
- PID算法(c 语言)(来自老外)
#include <stdio.h> #include<math.h> //定义PID 的结构体 struct _pid { int pv; // integer that c ...
- PID控制算法的C语言实现三 位置型PID的C语言实现
上一节中已经抽象出了位置性PID和增量型PID的数学表达式,这一节,重点讲解C语言代码的实现过程,算法的C语言实现过程具有一般性,通过PID算法的C语言实现,可以以此类推,设计其它算法的C语言实现. ...
- PID控制算法的C语言实现
参考: PID控制器开发笔 浅谈位置式PID 专家PID控制在快速系统中的仿真及应用(这篇了论文介绍的积分分离PID.专家PID(脚本实现和simulink实现)很详细) PID控制算法的C语言实现一 ...
- 【转】位置式、增量式PID算法C语言实现
位置式.增量式PID算法C语言实现 芯片:STM32F107VC 编译器:KEIL4 作者:SY 日期:2017-9-21 15:29:19 概述 PID 算法是一种工控领域常见的控制算法,用于闭环反 ...
- PID算法(C语言)
/************ PID算法(C语言) ************/ #include <stdio.h> #include<math.h> struct _pid { ...
- PID控制算法的C语言实现十一 模糊算法简介
在PID控制算法的C语言实现九中,文章已经对模糊PID的实质做了一个简要说明.本来打算等到完成毕业设计,工作稳定了再着力完成剩下的部分.鉴于网友的要求和信任,抽出时间来,对模糊PID做一个较为详细的论 ...
- PID控制算法的C语言实现二 PID算法的离散化
上一节中,我论述了PID算法的基本形式,并对其控制过程的实现有了一个简要的说明,通过上一节的总结,基本已经可以明白PID控制的过程.这一节中先继续上一节内容补充说明一下. 1.说明一下反馈控制的原理, ...
- PID控制算法的C语言实现一 PID算法原理
本系列是转载............. 全部的程序有一个共同点:就是我没认真去调pid的参数 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设 ...
随机推荐
- JVM系列【6】GC与调优2.md
JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 了解HotSpot常用命令行参数 JVM的命令行参数参考: https:/ ...
- nginx集群:nginx配置负载均衡集群(nginx1.18.0)
一,nginx的负载均衡集群的特点: 1,nginx集群和lvs的不同? lvs集群:工作在第4层(传输层) nginx集群:工作在第7层(应用层) lvs集群:性能更强 nginx集群:功能更强:可 ...
- ansible的copy模块应用(ansible 2.9.5)
一,copy模块的作用: 复制文件到受控的远程主机 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest 对应的源码可以访问 ...
- 解决selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid 'expiry'
解决selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid 'expiry' ...
- vue实现循环滚动列表vue-seamless-scroll
1.安装 vue-seamless-scroll 实例文档链接 cnpm install vue-seamless-scroll --save 2.文件中引入,组件配置 import vueSea ...
- update不能直接使用select的返回结果
update不能直接使用select的返回结果,这是会报错的,这是SQL的语法规定的,若想在update中与select结合使用,sql需要这样写: 1.其中field1,field2为表中的字段名 ...
- naicat如何查看表关系
1.navict版本为:navict premium https://www.php.cn/tool/navicat/427617.html 参考上面链接 2. 这个版本的 目前就这些,后续进行补充
- ThreadLocal与Thread与Runable之间的关系
ThreadLocal继承Object,相当于没继承任何特殊的. ThreadLocal没有实现任何接口. ThreadLocal并不是一个Thread,而是Thread的局部变量
- list.add方法参数详解
- 浅谈1——用Eclipse调试JAVA程序
本篇博客主要介绍如何用Eclipse调试简单的JAVA程序. 1.如下图,一个简单的JAVA程序 2.设置断点. 方法:选中需设置断点的行代码,按快捷键Ctrl+Shift+B,设置断点: 断点设置 ...