PID算法理论,运用,代码编写详解

本文详细解读了PID控制器的工作原理,包括比例(P)、积分(I)和微分(D)运算,并通过电热水器实例说明其作用。同时介绍了位置式与增量式PID的区别,以及C语言中的实现代码。

什么是PID

我相信能来看这篇文章的应该都知道什么是PID,PID就是一种控制算法,利用比例运算(P),积分运算(I)和微分运算(D)一起控制某一事件,当然也可以只运用其中一个也可以两两结合。

运用举例:

比如我们家里都会有的那个电热水器,有点热水器会有那个保温功能,假如我们设定的温度保持在60度。一开始热水器开始工作P发现此时水温距离目标温度还差的多就控制加热棒输出较大功率快速加热。随着温度越来越高,P会发现距离目标温度越来越近,输出功率也越来越小,但由于“惯性”实际温度会超过目标温度,此时P就会输出负功率,但实际中没有负功率,我们可以启动制冷,但又会由于惯性温度会低于目标温度,就这样实际温度在目标温度附近徘徊。
在这里插入图片描述
显然这虽然能达到目标,但是不是很理想。于是就引入了D。D会发现当快要到目标温度时温度会上升比较慢(此时温度与目标温度的差值和上次温度和目标温度的差值比较),就表示快要到达目标温度了D就会给出信号以减小功率的输出。但是可能会出现下面这种情况,温度维持在目标温度附近。
在这里插入图片描述
这种虽然温度不会大幅跳动了但是没有到达我们设定的目标温度,此时就引入了I。I的作用就是在一段时间内它发现温度一直没有到达目标温度,此时它就增大输出功率进行加热。
以上就是PID算法在实际的一个应用,那他的一个底层数学逻辑是怎么样的勒?

底层数学逻辑的实现

接下来我们就讨论一下他的一个底层数学逻辑是怎么实现的。我们先来看看他的一个公式:
在这里插入图片描述
可以看出P就是简单的比例运算,I就是积分运算,D就是微分运算;
P:比例运算很简单我就不做阐述了;
I:积分运算,积分两点之间的积分,为两点连线,和两点对x轴的垂线,以及两垂足之间的线段所组成的梯形的面积。
在这里插入图片描述因为我们要编写这个代码,所以就得对其离散化理解。
在这里插入图片描述
D:微分运算,微分就是导线某点的切线斜率。
在这里插入图片描述以上就是PID运算的一个数学理解。我们可以上面的总结一下得到如下的公式:
在这里插入图片描述

其实上面讲解的这个PID也叫位置式PID,还有一种PID是 增量式PID。而增量式PID就是两次位置式PID相减。将两次位置式PID相减得到

在这里插入图片描述

区别
1、增量式只与最近三次的误差有关,运算速度快且无累积误差,而位置式需要对误差进行积分,容易产生累积误差且运算速度慢。
2、增量式的结果是输出量的变化量,即便出现误差影响不会太大,而位置式的结果是输出量,一旦出现错误影响会很大。

C语言实现

我们先用VisualStudio C语言编辑器编写代码验证,代码如下:

#include "stdio.h"
#include "windows.h"


typedef  unsigned char uint8_t;
typedef  unsigned int uint32_t;

//限幅输出预处理命令
#define Astrict_Out(input,min,max)	{
     
       		\
	if(input < min)					\
		input = min;				\
	else if(input >max)				\
		input =max;					\
}

enum PID_MODE
{
   
   
	PID_position = 0,   //位置式PID
	PID_increment      //增量式PID
};

typedef struct
{
   
   
	uint8_t mode; //PID运行模式
	float Kp;
	float Ki;
	float Kd;

	float max_Out;  //PID最大输出
	float min_Out;  //PID最大输出
	//float max_I_Out;  //PID最大积分输出

	float set_num;  //PID目标值
	float new_num;  //PID当前值

	float All_Out;  //三项叠加输出
	float P_Out;  //比例输出
	float I_Out;  //积分输出
	float D_Out;  //微分输出

	//微分项最近三个值,0最新,1上一次,2上上次
	float D_buf[3];  

	//误差项最近三个值 
	float Err_buf[3];
}PID_struct;

/*
PID初始化函数
参数:PID_struct *pid:PID结构体;
uint8_t mode:选择PID运算模式 0:位置式PID;  1:增量式PID
const float PID[3]:PID系数,Kp,Ki,Kd;
float max_out:PID最大输出值
float min_out:PID最小输出值
*/
void PID_Init(PID_struct *pid,uint8_t mode,const float PID[3],float max_out, float min_out)
{
   
   
	if (pid == NULL || PID == NULL)
		return;
	pid->mode = mode;
	pid->Kp = PID[0];
	pid->Ki = PID[1];
	pid->Kp = PID[2];
	pid->max_Out = max_out;
	pid->min_Out = min_out;
	pid->D_buf[0] = pid->D_buf[1] = pid->D_buf[2] = 0.0f;
	pid->Err_buf[0] = pid->Err_buf[1] = pid->Err_buf[2] = pid->P_Out 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值