PID模块(含常用改进算法和例程)--C源码

大家经常会用到PID算法,虽然算法简单,但实际应用中往往要考虑很多细节,而且往往普通的PID算法不能很好的应对大家的需求,为了能在打代码的时候节省点时间,这里作者提供一个自己写好的PID模块,可以让各位在工程中应用。

下载地址:
百度云:链接:https://pan.baidu.com/s/1PI6EuMif5Y_67c4VWE1x7A 提取码:yhmi 
Github:连接:https://github.com/diceTZ/pid.git

PID模块除了普通PID还加入了常用的几个改进PID算法:
1、积分分离PID
2、抗积分饱和PID
3、变速积分PID – 由于需求不一样,这个需要用户自行修改
4、不完全微分PID
5、微分先行PID
注:该PID模块为位置型PID

以下为.h代码和例程代码
pid.h(由于篇幅过长pid.c在上述下载地址中存放)

//@作者   :tou_zi
//@编写时间 :2019年4月6日
//@修改时间 :2019年4月6日
//@文件名  :pid.h
//@描述   :pid模块库,可实现pid的计算
#ifndef _PID_H
#define _PID_H

#ifndef u8
#define u8 unsigned char
#endif

#define INTEGRAL_NORMAL    0   //普通积分
#define INTEGRAL_SEPARATION  1   //积分分离
#define INTEGRAL_SATURATION  2   //抗饱和积分
#define INTEGRAL_SPEED    3   //变速积分 

#define DIFFERENTIAL_COMPLETE 0   //完全微分
#define DIFFERENTIAL_PART   1   //不完全微分
#define DIFFERENTIAL_PREVIOUS 2   //微分先行

//PID标志
typedef struct PID_Position_Flag
{
	u8 run;
	u8 integral_way;
	u8 differential_way;
	u8 use_predict;
}PID_Position_Flag;

//PID数据接口
typedef struct PID_Position_DInterface
{
	float *target;
	float *present;	
	float *predict;
}PID_Position_DInterface;

//PID接口
typedef struct PID_Position_Interface
{
 	PID_Position_DInterface data;
}PID_Position_Interface;

//PID参数
typedef struct PID_Position_Parameter
{
	float kp;        //比例系数
	float ki;        //积分系数
	float kd;        //微分系数
	float kf;        //前馈系数
	float kd_lpf;      //不完全微分系数
	float kd_pre;      //微分先行系数
	float k_pre;      //预测系数
	
	float target_limit;    //目标值限幅
	float bias_limit;     //误差限幅
	float bias_dead_zone;   //小于这个值将不进行PID操作
	float bias_for_integral; //开始积分的误差 -- 用于积分分离
	float integral_limit;   //积分限幅    -- 用于抗积分饱和
	float out_limit;     //输出限幅
}PID_Position_Parameter;

//PID数据
typedef struct PID_Position_Data
{ 	
	float out;
}PID_Position_Data;

//PID过程变量
typedef struct PID_Position_Process
{
	float bias;
	float integral_bias;
	float differential_bias;
	float lpf_differential_bias;
	
	float feedforward;
	float predict;
	
	float last_target;
	float last_bias;
}PID_Position_Process;

//PID模块
typedef struct PID_Position_Module
{
	PID_Position_Flag    flag;
	PID_Position_Interface  interface;
	PID_Position_Parameter parameter;
	PID_Position_Data    data;
	PID_Position_Process   process;
}PID_Position_Module;

//PID API
void initPID_Position_Module(PID_Position_Module *pid);
void calculatePID_Position_Module(PID_Position_Module *pid, float cycle);

模块分为五个子模块:标志模块,接口模块,参数模块,数据模块以及过程变量模块
****标志模块:(控制模块运行和运行方法)
****接口模块:分为数据接口(变量指针)和方法接口 (函数指针)
********数据接口:target 目标值, present 当前值
****参数模块:设定PID的相关参数
****数据模块:用户感兴趣的数据的存放点
****过程变量模块:用户不敢兴趣的数据的存放点,但调试时可能会用得上

例程代码:

#include "stdlib.h"
#include "pid.h"

PID_Position_Module my_pid;

int main(void)
{
	float target = 0, present = 1;
	initPID_Position_Module(&my_pid); //初始化pid结构体
	//设置标志位
	my_pid.flag.run = 1; //运行PID
	my_pid.flag.differential_way = DIFFERENTIAL_COMPLETE; //设置微分方法--完全微分
	my_pid.flag.integral_way = INTEGRAL_SATURATION; //设置积分方法--抗积分饱和
	//设置接口
	my_pid.interface.data.target  = (float *)malloc(sizeof(float)); //设置目标值接口
	my_pid.interface.data.present = (float *)malloc(sizeof(float)); //设置当前值接口
	// my_pid.interface.data.target  = ⌖             //设置目标值接口
	// my_pid.interface.data.present = &present;            //设置当前值接口
	//设置参数
	my_pid.parameter.kp = 0;          //设置比例系数
	my_pid.parameter.ki = 0;          //设置积分系数
	my_pid.parameter.kd = 0;          //设置微分系数
	my_pid.parameter.kf = 0;          //设置前馈系数
	my_pid.parameter.integral_limit = 25.0f;  //积分限制
	my_pid.parameter.bias_dead_zone = 0;    //误差死区
	my_pid.parameter.target_limit = 50.0f;   //期望限幅
	my_pid.parameter.bias_limit = 50.0f;    //误差限幅
	my_pid.parameter.out_limit = 50.0f;     //输出限幅
	while(1)
	{
	 	calculatePID_Position_Module(&my_pid, 0.01f); //计算pid,0.01 = 0.01秒(计算周期)		
	}
}

“望小小的举动,能够改变世界”

发布了2 篇原创文章 · 获赞 2 · 访问量 261

猜你喜欢

转载自blog.csdn.net/weixin_39159599/article/details/104318660