在STM32上实现增量式PID算法

本文详细介绍了如何在STM32上实现增量式PID算法,包括算法原理、离散化过程、C语言实现及参数整定方法。重点讲述了比例、积分和微分三个环节的作用,并提供了增量式PID的C语言代码示例。同时,讨论了增量式PID相对于位置式PID的优点,如计算量小、抗干扰能力强等,并给出了PID控制器的基本特点和整定口诀。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 < (pid.T))  //最小计算周期未到
     {
            return ;
     }
    pid.Tdata = 0;
    
    pid.En=pid.set-pid.curr;  //本次误差
    dk1=pid.En-pid.En_1;   //本次偏差与上次偏差之差
    dk2=pid.En-2*pid.En_1+pid.En_2;
    
    t1=pid.Kp*dk1;                            //比例
    
    t2=(pid.Kp*pid.T)/pid.Ti;      //积分
    t2=t2*pid.En;
    
    t3=(pid.Kp*pid.Td)/pid.T;        //微分
    t3=t3*dk2;
    
    switch(pid.choose_model)
     {
         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<0)
    {
     pid.currpwm=0;
    }
    
    printf("实际输出使用的OUT:\t%d\r\n",(int)pid.currpwm) ;
    pid.En_2=pid.En_1;
    pid.En_1=pid.En;
    
    
    Turn_Angle(pid.currpwm);                //输出PWM
    
    
 
}

上面我们贴出来位置式PID算法和增量式PID算法的核心部分了,但是上面的理论上可以直接移植,添加一些还没有定义的变量就好了,下面是具体的演示工程。

2.9 PID算法整定

(一)首先在使用PID算法之前先进行基础的设置

  1. PWM正脉冲控制输出开

  2. 传感器曲线随着PWM占空比越大而越大

  3. 传感器在环境下情况下最低数据 ,和最高数据。 设定值不能超过这两个范围

(二)凑试法的基本方法是:对参数实行先比例,后积分,再微分的整定步踩具体步骤如下:

1)首先先只整定比例部分。将比例系数Kp由小变大,观察系统响应的变化情况,直到得到反应快、超调小的响应曲线。如果系统没有静差或静差小到允许的范围内,那么只需要比例控制器即可满足要求。

2)整定积分时间常数。在比例控制下系统的静差不满足设计要求时,则需要采用积分环节来消除静差。整定时,首先置积分时间Ti为一较大值,并将经第一步整定很到的比例系数略为缩小(如缩小为原值的4/5),观察系统响应的情况,然后根据观察的情况来减小积分时间常数,同时比例系数也可能缩小,使系统消除静差的同时能够获得良好的动态性值在此过程中,在此过程可根据响应曲线的好坏反复改变比例系数与积分时间常数,以期得到满意的控制过程与整定参数。

3)整定微分时间常数。若使用比例积分控制器消除了静差,但动态过程经反复调胜仍不能满意(主要是响应速度达不到要求),则可加人微分环节,构成PID控制器。整定时先置.较小的微分时间常数,同时比例系数略微减小、 积分时间常数略微增大,观察系统师应的情况。然后加大微分时间常数,比例系数、积分时间常数相应调整,反复调整,直到得满意的控制过程和整定参数。

(三)总结试凑法

1. 比例系数有小到大,然后找出超调小的Kp
2. 积分时间常数Ti由大变小,适当调整Kp
3. 微分时间常数Td由小变大,适当调整Ti和Kp

(四)实验总结

  1. KP设定,最初使用1,假如控制之后实际值比设定值小不够,那就增大。反之就减少。

  2. TI设定,数据先很大。看效果

1). 如果TI加进去之后数据很久才变化到目标值就逐渐减小。如果TI减少到执行几次都是比设定值大的时候那就逐渐增大

2). 如果刚加进去变化很快,并且超调很高,就增大来调节

  1. 积分就看情况调节

(五)增量式PID控制与位置式PID控制比较,有如下优点:

1)由式增量式PID控制与位置式PID可见,增量式PID控制算式只需要现时刻以及前两个时刻的偏差采样值,计算量和存储量都小,且计算的是增量,当存在计算误差或精度不足时,对控制量计算的影响较小。而位置式PID控制算式每次计算均与整个过去的状态有关,需要过去所有的偏差采样值参与累积计算,容易产生较大的积累误差,存储量和计算量较大。

2)增量式PID控制容易实现无扰动切换。增量式PID控制算法是对前一一时刻控制量的增量式变化,对执行机构的冲击小。位置式PID控制算法则是对前一稳定运行点控制量的绝对大小的变化,变化大,对执行机构容易产生冲击。

3)增量式PID控制本质上具有更好的抗干扰能力。若某个时刻采样值受到干扰,对于位置式PID控制,这个干扰会一直影响系统的整个运行过程;而增量式PID控制算式只需要现时刻以及前两个时刻的偏差采样值,干扰最多影响3个采样时间,其他时间不受该干扰的影响。

4)位置式PID控制比增量式PID控制更容易产生积分饱和。

3. PID控制器的基本实现

完成了离散化后,我们就可以来实现它了。已经用离散化的数据公式表示出来后,再进型计算机编程已经不是问题了。接下来我们就使用C语言针对增量型公式来具体实现。

(2)增量型PID的简单实现

增量型PID的实现就是以前面的增量型公式为基础。这一节我们只是完成最简单的实现,也就是将前面的离散增量型PID公式的计算机语言化。

4. 基本特点

前面讲述并且实现了PID控制器,包括位置型PID控制器和增量型PID控制器。界限来我们对这两种类型的控制器的特点作一个简单的描述。

位置型PID控制器的基本特点:

位置型PID控制的输出与整个过去的状态有关,用到了偏差的累加值,容易产生累积偏差。
位置型PID适用于执行机构不带积分部件的对象。
位置型的输出直接对应对象的输出,对系统的影响比较大。
增量型PID控制器的基本特点:

增量型PID算法不需要做累加,控制量增量的确定仅与最近几次偏差值有关,计算偏差的影响较小。
增量型PID算法得出的是控制量的增量,对系统的影响相对较小。
采用增量型PID算法易于实现手动到自动的无扰动切换。

5. PID 整定口诀

                参数整定找最佳, 从小到大顺序查。
                先是比例后积分, 最后再把微分加。
                曲线振荡很频繁, 比例度盘要放大。
                曲线漂浮绕大弯, 比例度盘往小扳。
                曲线偏离回复慢, 积分时间往下降。
                曲线波动周期长, 积分时间再加长。
                曲线振荡频率快, 先把微分降下来。
                动差大来波动慢, 微分时间应加长。
                理想曲线两个波, 前高后低四比一。
                一看二调多分析, 调节质量不会低。

在这里插入图片描述

资料来源:
https://www.cnblogs.com/foxclever/p/8902029.html

https://seipher.blog.csdn.net/article/details/108361789?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-13.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-13.no_search_link

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值