在STM32上实现增量式PID算法

您所在的位置:网站首页 plc实现pid 在STM32上实现增量式PID算法

在STM32上实现增量式PID算法

#在STM32上实现增量式PID算法| 来源: 网络整理| 查看: 265

在STM32上实现增量式PID算法 1. PID算法基本原理2. PID算法的离散化2.1 从上面图中我们可以得到定义2.2 如果我们在一段时间内就从传感器读取一个值,那么我们就可以得到一个实际值的数据序列,,那么我们也会得到一个偏差值的序列2.3 比例控制(P),作用:对偏差起到及时反映的作用,一旦产生偏差,控制器立即做出反映.............2.4 积分控制(I),作用:消除静差............2.5 微分控制(D),作用:反映偏差信号的变化趋势.............2.6 那么我们从上面就能得出PID的控制算法2.7 数字PID的公式2.8 我们将上面的增量式PID公式通过C语言写出来2.9 PID算法整定 3. PID控制器的基本实现4. 基本特点5. PID 整定口诀

1. PID算法基本原理

PID算法是控制行业最经典、最简单、而又最能体现反馈控制思想的算法。对于一般的研发人员来说,设计和实现PID算法是完成自动控制系统的基本要求。这一算法虽然简单,但真正要实现好,却也需要下一定功夫。首先我们从PID算法最基本的原理开始分析和设计这一经典命题。

PID算法的执行流程是非常简单的,即利用反馈来检测偏差信号,并通过偏差信号来控制被控量。而控制器本身就是比例、积分、微分三个环节的加和。其功能框图如下: 在这里插入图片描述 根据上图我们考虑在某个特定的时刻t,此时输入量为rin(t),输出量为rout(t),于是偏差就可计算为err(t)=rin(t)-rout(t)。于是PID的基本控制规律就可以表示为如下公式: 在这里插入图片描述 其中Kp为比例带,TI为积分时间,TD为微分时间。PID控制的基本原理就是如此。

2. PID算法的离散化

上一节简单介绍了PID算法的基本原理,但要在计算机上实现就必须将其离散化,接下来我们就说一说PID算法的离散化问题。在实现离散化之前,我们需要对比例、积分、微分的特性做一个简单的说明。

比例就是用来对系统的偏差进行反应,所以只要存在偏差,比例就会起作用。积分主要是用来消除静差,所谓静差就是指系统稳定后输入输出之间依然存在的差值,而积分就是通过偏差的累计来抵消系统的静差。而微分则是对偏差的变化趋势做出反应,根据偏差的变化趋势实现超前调节,提高反应速度。

在实现离散前,我们假设系统采样周期为T。假设我们检查第K个采样周期,很显然系统进行第K次采样。此时的偏差可以表示为err(K)=rin(K)-rout(K),那么积分就可以表示为:err(K)+ err(K+1)+┈┈,而微分就可以表示为:(err(K)- err(K-1))/T。于是我们可以将第K次采样时,PID算法的离线形式表示为: 在这里插入图片描述 这就是所谓的位置型PID算法的离散描述公式。我们知道还有一个增量型PID算法,那么接下来我们推到一下增量型PID算法的公式。上面的公式描述了第k个采样周期的结果,那么前一时刻也就是k-1个采样周期就不难表示为: 在这里插入图片描述 那么我们再来说第K个采样周期的增量,很显然就是U(k)-U(k-1)。于是我们用第k个采样周期公式减去第k-1个采样周期的公式,就得到了增量型PID算法的表示公式: 在这里插入图片描述 当然,增量型PID必须记得一点,就是在记住U(k)=U(k-1)+∆U(k)。

2.1 从上面图中我们可以得到定义

原文链接:https://blog.csdn.net/zxm8513/article/details/108361789

定义变量

用户设定值: SV

当前值(实际值): PV

偏差: E = SV - PV

2.2 如果我们在一段时间内就从传感器读取一个值,那么我们就可以得到一个实际值的数据序列,,那么我们也会得到一个偏差值的序列

读取时间:  t(1) t(2)    ------  t(k-1) t(k) 读取到的值: X(1) X(2)    ------  X(k-1)  X(k)

偏差值: E(1) E(2)    ------  E(k-1)  E(k)

那么我们从偏差值中可以知道:   E(X) > 0    说明未达标

E(X) = 0    说明正好达标

E(X) < 0 说明超标

2.3 比例控制(P),作用:对偏差起到及时反映的作用,一旦产生偏差,控制器立即做出反映…

定义: 比例系数:Kp    (根据系统进行调节) 比例输出:POUT  = Kp * E(k)

POUT = Kp * E(k) + OUT0

OUT0说明:OUT0是防止E(K) = 0 时候比例控制不作用,所以添加个OUT0进去,OUT0可以根据系统定义大小

Kp说明:如果我们得到一个偏差之后,将偏差进行放大或者缩小来让控制器进行控制

2.4 积分控制(I),作用:消除静差…

从上面我们得到偏差序列: 偏差值: E(1) E(2)    ------  E(k-1)  E(k)

定义,历史偏差值之和:S(k) = E(1) + E(2) + … + E(k-1) + E(K) 定义,积分输出:   IOUT = Kp * S(k) + OUT0

2.5 微分控制(D),作用:反映偏差信号的变化趋势…

从上面我们得到偏差序列:

偏差值: E(1) E(2)    ------  E(k-1)  E(k) 定义,偏差之差:D(k) = E(k) - E(k-1) 定义,微分输出:DOUT = Kp * D(k) + OUT0

2.6 那么我们从上面就能得出PID的控制算法

PIDOUT = POUT + IOUT + DOUT = (Kp * E(k) + OUT0) + (Kp * S(k) + OUT0) + (Kp * D(k) +OUT0)        = Kp * (E(k) + S(k) + D(k)) + OUT0

OUT0防止PIDOUT = 0 时候算法还有输出,防止失去控控制 比例(P):考虑当前 积分(I):考虑历史 微分(D):考虑未来

2.7 数字PID的公式

在这里插入图片描述

在这里插入图片描述 在这里插入图片描述

2.8 我们将上面的增量式PID公式通过C语言写出来 #ifndef _pid_ #define _pid_ #include "stm32f10x_conf.h" #define MODEL_P 1 #define MODEL_PI 2 #define MODEL_PID 3 typedef struct { u8 choose_model; //使用哪个模式调节 float curr; //当前值 float set; //设定值 float En; //当前时刻 float En_1; //前一时刻 float En_2; //前二时刻 float Kp; //比例系数 float T; //采样周期---控制周期,每隔T控制器输出一次PID运算结果 u16 Tdata; //判断PID周期到没到 float Ti; //积分时间常数 float Td; //微分时间常数 float Dout; //增量PID计算本次应该输出的增量值--本次计算的结果 float OUT0; //一个维持的输出,防止失控 short currpwm; //当前的pwm宽度 u16 pwmcycle; //pwm周期 }PID; extern u8 STATUS; extern PID pid; void PIDParament_Init(void); /*增量式PID初始化*/ void pid_calc(void); /*pid计算 并输出*/ #endif #include "pid.h" #include "PWM_Config.h" #include "USART_Config.h" //USART设置 PID pid; void PIDParament_Init() // { pid.choose_model = MODEL_PID; pid.T=330; //采样周期,定时器使用1ms,则最小执行PID的周期为330ms pid.set =280; //用户设定值 pid.Kp=0.5; //比例系数 pid.Ti=40; //微分系数常数 pid.Td=10; //积分时间常数 pid.OUT0=0; //一个维持的输出 pid.pwmcycle = 330; //PWM的周期 } void pid_calc() //pid?? { float dk1;float dk2; float t1,t2,t3; if(pid.Tdata case MODEL_P: pid.Dout= t1; printf("使用P运算\r\n") ; break; case MODEL_PI: pid.Dout= t1+t2; printf("使用PI运算\r\n") ; break; case MODEL_PID: pid.Dout= t1+t2+t3; printf("使用PID运算\r\n") ; break; } pid.currpwm+=pid.Dout; //本次应该输出的PWM printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ; /*判断算出的数是否符合控制要求*/ if(pid.currpwm>pid.pwmcycle) //算出的值取值,肯定是在0-pid.pwmcycle之间,不然的话PWM怎么输出 { pid.currpwm=pid.pwmcycle; } if(pid.currpwm


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3