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语言实现的更多相关文章

  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. spring boot:使用多个redis数据源(spring boot 2.3.1)

    一,什么情况下需要使用多个redis数据源? 为了缓存数据,通常我们会在线上使用多个redis的cluster, 每个cluster中缓存不同的数据,以方便管理. 例如:我们缓存了杂志文章/商品信息/ ...

  2. nginx 快速安装

    必要条件 1能访问外网 2防火墙放开80 3有软件安装权限 依次执行以下命令 一.设置CentOS7的yum源及EPEL yum源 wget -O /etc/yum.repos.d/epel.repo ...

  3. poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10742   Accepted: 3885 ...

  4. Ⅱ Finite Markov Decision Processes

    Dictum:  Is the true wisdom fortitude ambition. -- Napoleon 马尔可夫决策过程(Markov Decision Processes, MDPs ...

  5. Qlik Sense插件及QRS接口补充

    date: 2019-10-18 09:10:00 updated: 2019-10-18 15:18:00 Qlik Sense插件及QRS接口补充 1.插件 1.1 获取数据方式 理论上 Engi ...

  6. 阅读源码,通过LinkedList回顾基础

    目录 前言 类签名 泛型 Serializable和Cloneable Deque List和AbstractList RandomAccess接口(没实现) 变量 构造函数 常用方法 List体系下 ...

  7. C# 2 新增语法特性

    C# 2.0 ,.NET Framework 2.0,.NET Framework 3.0,Visual Studio 2005 C#2主要添加了泛型.匿名方法,分部类型(类.结构.接口),可空类型, ...

  8. R语言factor类型转numeric

    R 语言中为了进行数据分析,比如回归分析,这时候对于数据表格中的factor类型的数据会带来弊端,比如对因子的每一个数据都进行一次回归,这样就显得很复杂,且违背了我们的初衷,需要把factor转换为n ...

  9. Python - 生成 requirement.txt 文件

    前言 Python项目中,一般都会有一个 requirements.txt 文件 这个文件主要是用于记录当前项目下的所有依赖包及其精确的版本号,以方便在一个新环境下更快的进行部署 如何生成 requi ...

  10. 什么是4G模块 4G模块的工作原理及特点

    什么是4G模块 4G模块,也被叫做4G通信模块或4G DTU模块,他是物联网行业具有4G通信功能的一种产品,通过4G模块,我们可以实现工业设备数据通过无线4G网络传输到远端控制中心,并从控制中心通过4 ...