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算法的设 ...
随机推荐
- rabbitmq--通配符模式Topics
topic模式也称为主题模式,其实他相对于routing模式最大的好处就是他多了一种匹配模式的路由,怎么理解匹配呢,其实就相当于我们之前正则的.*这种,不过他的匹配机制可能不是这种(其实除了匹配规则外 ...
- go内建方法 append copy delete
package mainimport "fmt"func main() { testAppend() testCopy() testDelete()}func testAppend ...
- linux(centos8):lnmp环境编译安装zabbix5.0
一,zabbix的用途: zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案 zabbix能监视各种网络参数,保证服务器系统的安全运营: 并提供灵活的通知机制以 ...
- <!DOCTYPE>,<address>,<applet>的用法
希望以下内容能让大家有所收获 HTML <!DOCTYPE> 标签 实例 <!DOCTYPE html> <html> <head> <title ...
- volatile与重排序
使用关键字volatile可以禁止代码的重排序: 在Java程序运行时,JIT(即使编译器)可以动态地改变程序代码运行地顺序:例如,有如下代码: A代码-重耗时 B代码-轻耗时 C代码-重耗时 D代码 ...
- static_cast与c风格的强制类型转换比较
转载:https://blog.csdn.net/whatday/article/details/50417503 class A { int a; }; class B { int b; }; cl ...
- plsql查询中文乱码
1.查看数据库字符集 select userenv('language') from dual 查看数据库字符集 2.在环境变量中添加并设置变量 变量名:NLS_LANG: 变量值:第一步查询的数据库 ...
- mybatis-plus自动填充
1,给字段添加注解 @TableField(value = "create_time", fill = FieldFill.INSERT) 2,添加填充处理器,需要实现接口Meta ...
- SWPUCTF_2019_p1KkHeap
SWPUCTF_2019_p1KkHeap 环境:ubuntu18 考点:UAF,沙箱逃逸 ubuntu18现在不能构造double free了!!! 所以我用patchelf来做 IDA逆一下 可以 ...
- Java进阶面试
消息中间件: 1.你们公司生产环境用的是什么消息中间件? https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484149&am ...