图文详解PID调参&积分分离PID控制算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


PID 积分分离意义

1、积分本身是用于消除静态误差。但在短期内存在很大偏差的情况下,会造成积分累积,导致控制量超出执行机构可能允许的最大动作范围对应极限控制量,引起超调以及振荡。

2、积分分离的原理:当误差值比较大时,取消积分作用,以免由于积分作用使得系统稳定性降低,超调量增大;当被控量接近目标值时(即误差较小时),引入积分控制,以消除净差,提高控制精度。

3、简单来说,就是积分作用是用来消除静态误差,但是不能整个状态中都使用。误差较大时,如果还使用积分,就会使控制量很大,产生超调或者振荡。所以这里的分离的意思就是,在误差大的时候不用积分,在误差比较小的时候才用积分作用,用于消除静差。

简述PID原理及临界比例度法参数整定

https://blog.csdn.net/qq_42962378/article/details/104528569?ops_request_misc=&request_id=&biz_id=102&utm_term=PID%20%E4%B8%B4%E7%95%8C%E6%AF%94%E4%BE%8B%E5%BA%A6%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-104528569.142v99pc_search_result_base7&spm=1018.2226.3001.4187

温控PID参数调节实验过程

https://www.amobbs.com/thread-936512-1-1.html

PID的源代码在网上基本都是公开的,既然大家都希望看一看,我还是贴出来吧,估计看了也很失望,因为我的也是网上的代码一模一样的,既然数学模型已经建立,程序只是把这个模型用语言把他表达出来而已,其实很多人PID实验不成功,就是没有仔细去分析参数的调节过程,我是想通过上面的实验过程来给大家一个思路去如何调节这几个参数,而不是在网上到处搜索源程序,然后抱怨下载的PID源程序都不能满足自己的调节要求。
经过实验发现:位置式整定的参数不能直接用在增量式上面,会出现超调的时间居多,无法稳定在目标值上

对于温度控制系统参数的整定过程及方法,搜索了很多论坛,大家都只提到PID数学原型,很少看到有实验过程及Kp,Ki,Kd参数的整定过程及方法,这2天闲着没事,来做个温度控制实验,并将一些实验过程写上来,我也是正在摸索阶段,希望大家踊跃发言哟,各位有好的建议尽管提出来,然后我来实验,将实验数据整理上来,希望对于以后想做温度控制的朋友有所帮助

硬件:
1。用可控硅控制200W加热丝,对一铁块加热,用K型热电偶采集温度,采用MAX6675做温度转换,可以到0。25度的精度,并且外围很简单,很容易与CPU对接,采用SPI通信,读取当前的温度值
2。过零检测电路,将交流信号全波整流后得到的波形去控制NPN管,将信号整形后接到CPU外部中断脚,为系统提供基准时间,所以CPU中断的频率是100HZ

实验目标:
在100度到200度内可对任意设定的温度恒温,精度先做到+/-1度吧

基本的控制实现方法:
因为是对加热的铁块温度进行控制,属于滞后效应系统,所以采样周期先定为5秒(这里指的是PID计算的周期,注意我的温度采样是时时的),所以CPU外部中断次数为500次,对应的PID计算结果输出为0~500,就是说把这5秒钟划分为500等份,根据计算的结果来决定在这5秒钟内应该加热多少等份

软件:
采用PID控制方法,我先采用位置式输出方式,公式原型:u(t) = kp * e(t) + ki * [e(1) + e(2) + …+ e(t)] + kd * [e(t) - e(t-1)],这里先做基本的PID算法,达到控制目标后再来优化算法提高恒温精度,考虑到实验温度过高实验时间会过长,所以我先定目标控制温度为110度,等控制好了再看其他温度会达到多少精度,为了提高加热速度提前20度开始PID控温

下面是调节参数的过程及数据:
参照网上一些方法,先确定Kp,即令Ki,Kd=0,只用比例调节,得到一个稳定的越接近控制目标的震荡参数,然后根据这个Kp和震荡周期来计算Ti,Td,

//PID计算
UINT16 PID_Cal(void)
{
        float xdata pterm,iterm,dterm;

        //把当前的温度和设定的目标温度定义好
        ppid->pv = SystemRealTemprature;
        ppid->sp = SystemSetTemprature;

        //根据实验得出:Kp=5.98 T=5 Td=27 Ti=112.5

        //PID数学模型
        //u(t) = kp * e(t) + ki * [e(1) + e(2) + ....+ e(t)] + kd * [e(t) - e(t-1)]
       
        ppid->errk = (float)(ppid->sp - ppid->pv);

        pterm = ppid->kp * ppid->errk;

        ppid->sum += ppid->errk;               
        iterm = ppid->ki * ppid->sum;
       
        dterm = ppid->kd * (ppid->errk - ppid->errk_1);

        ppid->Last_Out = pterm + iterm + dterm;

        ppid->errk_2 = ppid->errk_1;
        ppid->errk_1 = ppid->errk;

        if(ppid->Last_Out > SampleT)
                ppid->Last_Out = SampleT;
        else if(ppid->Last_Out < 0)
                ppid->Last_Out = 0;

        printf("%d   p=%d   i=%d   d=%d   ",SystemRealTemprature, (int)pterm, (int)iterm, (int)dterm);
        printf("H=%d\n", (UINT16)ppid->Last_Out);

        return        (UINT16)ppid->Last_Out;
}

我的硬件系统是51单片机通过光耦触发可控硅来实现给电热丝供电,并且检测交流电过零,控制导通周期,至于上面看到的数据解析图片,是单片机通过串口将时时温度数据传递给PC,然后保存起来用EXCEL软件分析,温度走势,看PID的控温效果,等一下我将实验图片上传。下面是控制解析图,不知道表达清楚不?

在这里插入图片描述

简述PID原理及临界比例度法参数整定

原文链接:https://blog.csdn.net/qq_42962378/article/details/104528569

PID参数整定(临界比例度法)
步骤(1) 将积分时间常数Ti =∞ ,微分时间常数Td = 0,在闭合的调节系统中将比例度取适当值;
步骤(2)将比例度从大到小地逐渐调节,观察震荡过程。等观察到等幅震荡时,记下临界比例度的值δK和临界震荡周期的值Tk。(控制量出现等幅震荡,控制作用为一种临界状态)
在这里插入图片描述
位置式计算:
位置式控制当前系统的实际位置与目标位置的偏差,故此积分调节中的积分项为误差的积累。
在这里插入图片描述

在这里插入图片描述
由于上表多为经验公式,故此仍需要进行微调。

有的系统不允许临界振荡,临界振荡的幅度可能较大,也可能变为振幅越来越大的发散振荡可选择以下方法:
http://bbs.gkong.com/archive.aspx?id=339040

qjj1020:在PID调试中比较常用的一种方法是临界比例度法:
1.被控系统稳定后,把控制器的积分时间放到最大,微分时间放到零(相当于切除了积分和微分作用,只使用比例作用)。
2.通过外界干扰或使控制器设定值作一阶跃变化,观察由此而引起的测量值振荡。
3.从大到小的,逐步把控制器的比例度减小,看测量值振荡的变化是发散的还是衰减的?如是衰减的则应把比例度继续减小;如是发散的则应把比例度放大。
4.连续重复2、3步,直至测量值按恒定幅度和周期发生振荡,即持续4–5次等幅振荡为止。此时的比例度示值就是临界比例度PB。然后根据临界振荡公式进行PID计算。
我想问的是,所谓的等幅振荡是不是在随意设置的设定值的上下(大于或小于设定值)做恒定幅度和两相邻的波峰或波谷周期不变的振荡?而仅仅只在设定值以下做的等幅振荡不是所需要的振荡,简单的说就是这个等幅振荡就是在设定值上下所做的等幅振荡。
下面是我的回帖:一个“纯粹”的线性系统是很难出现稳定的等幅震荡的。实际的系统由于有各种非线性,例如PID控制器的饱和非线性(对输出的限幅作用),不难观察到等幅震荡。这种震荡一般是在设定值上下的等幅振荡。
很多书上都有临界比例度法,用来确定PID的初始参数。有的系统不允许临界振荡,临界振荡的幅度可能较大,也可能变为振幅越来越大的发散振荡,因此这个方法对某些系统有一定的危险性。
可以用下面的方法来调试闭环:首先选用PI控制器,初始参数尽量取得保守些(比例系数尽量小、积分时间尽量大),以防止初次运行时出现大的超调量或系统不稳定。然后根据阶跃响应的特征调节控制器参数。
如果阶跃响应的超调量太大,应减小控制器的比例系数、增大积分时间。
如果阶跃响应没有超调量,但是被控量上升过于缓慢,过渡过程时间太长,应按相反的方向调整参数。
如果消除误差的速度较慢,可以适当减小积分时间。[/URL]反复调节比例系数和积分时间,如果超调量仍然较大,可以加入微分部分,逐渐增大微分时间。

在闭环的控制系统中,激励为阶跃信号,将调节器置于纯比例作用下,从小到大逐渐改变调节器比例度的大小,直到出现等幅振荡的过渡过程。此时的比例度称为临界比例度δ_r(δ=1/K_p )。相邻两个波峰间的距离称为临界振荡周期T_r,比例增益K_Pr。
在这里插入图片描述
在这里插入图片描述

临界比例度法整定PID参数

一个调节系统,在阶跃干扰作用下,出现既不发散也不衰减的等幅震荡过程,此过程成为等幅振荡过程,如下图所示。此时PID调节器的比例度为临界比例度δk,被调参数的工作周期为为临界周期Tk。
在这里插入图片描述
临界比例度法整定PID参数步骤
临界比例度法整定PID参数具体操作如下:
① 被控系统稳定后,把PID调节器的积分时间放到最大,微分时间放到零(相当于切除了积分和微分作用,只使用比例作用)。
② 通过外界干扰或使PID调节器设定值作一阶跃变化,观察由此而引起的测量值振荡。
③ 从大到小逐步把PID调节器的比例度减小,看测量值振荡的变化是发散的还是衰减的,如是衰减的则应把比例度继续减小;如是发散的则应把比例度放大。
④ 连续重复②和③步骤,直至测量值按恒定幅度和周期发生振荡,即持续4-5次等幅振荡为止。此时的比例度示值就是临界比例度δk。
⑤ 从振荡波形图来看,来回振荡1次的时间就是临界周期Tk,即从振荡波的第一个波的顶点到第二个波的顶点的时间。如果有条件用记录仪,就比较好观察了,即可看振荡波幅值,还可看测量值输出曲线的峰-峰距离,把该测量值除以记录纸的走纸速度,就可计算出临界周期Tk;如果是DCS控制或使用无纸记录仪,在趋势记录曲线中可直接得出Tk。

临界比例度法PID参数整定经验公式
临界比例度法PID参数整定经验公式
⑥计算所得的调节器参数输入调节器后再次运行调节系统,观察过程变化情况。多数情况下系统均能稳定运行状态,如果还未达到理想控制状态,进需要对参数微调即可。
在这里插入图片描述

图文详解PID调参

原文链接:https://blog.csdn.net/qq_45396672/article/details/118057838

我们在使用PID的时候,单独只使用一个参数是没有意义的至少使用两个参数,并且P(比例项)是必须要有的,虽然PID有三个参数,但大多数情况下PID三个参数并不是都使用上的,一般会其中两个来组合使用,比如PI组合用于追求稳定的系统,PD组合用于追求快速响应的系统,当然PID用于即追求稳定又追求快速响应的系统,但是实际上PID参数越多越难调,而且许多情况下两个参数的效果已经足够了,所以我一般根据情况使用前两个,下面对这几个系统都做一个分析

1.PI系统调节

调节PI系统的第一步就是先调节P,由小到大依次调节,P的值可以很明显的在输出曲线体现出来,比如我先给P=0.05,系统反应如下,当P过小时,曲线呈现缓慢上升,且最终值会明显低于目标值
在这里插入图片描述
当我们加大P到0.15时,我们可以看到实际曲线很快的接近目标值,但因为只有单纯P控制,所以有较大的过冲(过冲就是实际值达到目标值时刹不住车,冲出去了),但在他稳定的时候,实际曲线基本接近目标曲线
在这里插入图片描述
如果P再增大到0.25,可以看到,实际曲线需要震荡很久才会达到稳定目标线,但在稳定后基本和目标线保持一致
在这里插入图片描述
如果P过大,整个系统就会不受控,实际曲线不会收敛到目标曲线位置,出现等幅震荡,比如P=0.45时
在这里插入图片描述
在调节PI系统时,P的选取一般有两种情况

P偏小一点,稳定时,实际值在目标值之下,一直存在误差,这时再从0开始,一直加大I,消除稳定时的误差,这种情况下的最终稳定曲线会一直保持在目标曲线之下,达到比较稳定的调节效果,不会有过冲

(无过冲,稳定!)

P大一点,在第一次到达目标值的时候有一定的过冲,但之后就会稳定,其与第一种相比反应速度更快!

(有过冲,但他快!)

下面展示第一种PI控制方式,选取P=0.5(偏小)时,再用I消除稳定时的稳态误差,达到稳定的效果:

I积分的值这里我展示了三个,分别为较小,刚好,和较大时的实际曲线,用来做对比!

P=0.5,I=0.00005,I选取较小,可以看到相对于单纯的P=0.5,稳定误差有一定消除,但消除程度不够!
在这里插入图片描述
在加大I到0.0001,刚刚好的时候,实际曲线和目标曲线基本重合!!!
在这里插入图片描述
当I过大取0.002时,因为累计误差占比过大,就会出现抖动现象,难以收敛
在这里插入图片描述
上面就是第一种PI调节情况,虽然PI系统平衡过程很稳定,但到达目标位置的反应速度较慢,有的时候为了提高反馈速度,适当的提高P,允许有一定的过冲,比如我取P=0.07,对应的I取0.0001时,波形如下,该系统允许一定的过冲,但可以更快的到达目标点后再趋于稳定,这就是第二种PI系统的调节方式,
在这里插入图片描述
以上基本就是PI系统的调节过程了,下面我讲一下PD系统的调节过程

2.PD系统调节

由一开始的概念我们可以知道,与 I 的不同点在于,I是计算累计误差,而D则是计算未来趋势,因此PD系统的反应速度更快,相对于PI系统会更快的到达目标位置附近,其调节方式首先还是调节P,这里我们根据PI中P的调节结果,调节P到比大的位置,出现一定的过冲,这里取P=0.15,不加D的时候图形如下:

在这里插入图片描述
从图像可以看出:P=0.15在开始时过冲严重,所以加上一个D来减小过冲幅度,D的选取和I的选取一样,从0慢慢增加,观看效果确定合适的点,下面一张图的D=1.5是我试出来比较合适的点,我们可以看到加上合适的D之后,实际曲线到达目标位置的时间更短,过冲幅度也降低了一些,但是这里效果不是很明显,主要原因是我这里使用的是小车轮子来做的速度PID,而PD的应用场合主要是大惯性系统中,这里的应用场景不适合,但也能看出一定效果
在这里插入图片描述
如果D调节的过大之后,反倒会放大系统趋势的影响,使系统出现震荡,难以稳定,如下D=5
在这里插入图片描述

3.PID系统调节

在讲了PI和PD系统的调节方式后,下面分享一下PID系统的调节方式,首先我们先按照PI系统进行调节,先调P在调I,让系统有一定的过冲后达到稳定,如下图:
在这里插入图片描述
在出现了上面的 PI 波形之后,下面就开始调节D,慢慢增加D,将过冲补偿掉,直到系统稳定,最终效果如下图,PID系统就基本调节完成了
在这里插入图片描述
这篇文章的PID讲解内容就到这里了,下一篇文章将会详细分享我常使用的PID调用代码,帮助大家PID进一步入门
第二篇已更新,文章链接:从0编写一份PID控制代码

Chapter1 积分分离PID控制算法

原文链接:https://blog.csdn.net/songyulong8888/article/details/117389191

注:本文内容摘自《先进PID控制MATLAB仿真(第4版)》刘金琨 编著,研读此书受益匪浅,感谢作者!
积分分离PID控制:
在普通的PID控制中引入积分环节的目的,主要为了消除静差,提高控制精度。但在过程启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,致使控制量超过执行机构可能允许的最大动作范围对应的极限控制量,引起系统较大的超调,甚至引起系统较大的震荡。

积分分离控制基本思路:
当被控制量与设定值偏差较大时,取消积分作用,以避免由于积分作用使系统稳定性降低,超调量增大;当被控量接近给定值时,引入积分控制,以便消除静差,提高控制精度。其具体实现步骤如下:
(1)根据实际情况,认为设定阀值ϵ > 0 ;
(2)当∣ e r r o r ( k ) ∣ > ϵ 时,采用PD控制,可以避免产生过大的超调,又使系统有较快的响应;
(3)当∣ e r r o r ( k ) ∣ ≤ ϵ 时,采用PID控制,以保证系统的控制精度;

在这里插入图片描述
积分分离式PID控制算法程序流程图:
在这里插入图片描述

Chapter2 PID 算法原理(位置型 PID、增量型 PID 、积分分离、抗积分饱和的 PID 控制算法 C 语言实现)

原文链接:https://blog.csdn.net/cubejava/article/details/125646033

位置型 PID 的 C 语言实现

上一节中已经抽象出了位置性 PID 和增量型 PID 的数学表达式,这一节,重
点讲解 C 语言代码的实现过程,算法的 C 语言实现过程具有一般性,通过 PID
算法的 C 语言实现,可以以此类推,设计其它算法的 C 语言实现。

第一步:定义 PID 变量结构体,代码如下:

struct _pid{
float SetSpeed; //定义设定值
float ActualSpeed; //定义实际值
float err; //定义偏差值
float err_last; //定义上一个偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
float voltage; //定义电压值(控制执行器的变量)
float integral; //定义积分值
}pid;

控制算法中所需要用到的参数在一个结构体中统一定义,方便后面的使用。
第二部:初始化变量,代码如下:

void PID_init(){
printf("PID_init begin \n");
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
printf("PID_init end \n");
}

统一初始化变量,尤其是 Kp,Ki,Kd 三个参数,调试过程当中,对于要求的控制
效果,可以通过调节这三个量直接进行调节。
第三步:编写控制算法,代码如下:

float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
pid.integral+=pid.err;
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pi
d.err_last);
pid.err_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;
return pid.ActualSpeed;
}

注意:这里用了最基本的算法实现形式,没有考虑死区问题,没有设定上下限,
只是对公式的一种直接的实现,后面的介绍当中还会逐渐的对此改进。
到此为止,PID 的基本实现部分就初步完成了。下面是测试代码:

int main(){
printf("System begin \n");
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}

下面是经过 1000 次的调节后输出的 1000 个数据(具体的参数整定过程就不说明
了,网上这种说明非常多):
在这里插入图片描述
在这里插入图片描述

增量型 PID 的 C 语言实现

上一节中介绍了最简单的位置型 PID 的实现手段,这一节主要讲解增量式 PID
的实现方法。实现过程仍然是分为定义变量、初始化变量、实现
控制算法函数、算法测试四个部分,这里直接给出代码了。

#include<stdio.h>
#include<stdlib.h>
struct _pid{
float SetSpeed; //定义设定值
float ActualSpeed; //定义实际值
float err; //定义偏差值
float err_next; //定义上一个偏差值
float err_last; //定义最上前的偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
}pid;
void PID_init(){
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.err_next=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
float
incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(p
id.err-2*pid.err_next+pid.err_last);
pid.ActualSpeed+=incrementSpeed;
pid.err_last=pid.err_next;
pid.err_next=pid.err;
return pid.ActualSpeed;
}
int main(){
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}

在这里插入图片描述

积分分离的 PID 控制算法 C 语言实现

通过前面基本上已经弄清楚了 PID 控制算法的最常规的表达方法。在普通 PID 控制中,引入积分环节的目的,主要是为了消除静差,提高控制精度。但是在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成 PID 运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应极限控制量,从而引起较大的超调,甚至是震荡,这是绝对不允许的。为了克服这一问题,引入了积分分离的概念,其基本思路是 当被控量与设定值偏差较大时,取消积分作用; 当被控量接近给定值时,引入积分控制,以消除静差,提高精度。其具体实现代码如下:

pid.Kp=0.2;
pid.Ki=0.04;
pid.Kd=0.2; //初始化过程
if(abs(pid.err)>200)
{
index=0;
}else{
index=1;
pid.integral+=pid.err;
}
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.
err-pid.err_last); //算法具体实现过程

同样采集 1000 个量,会发现,系统到 199 所有的时间是原来时间的 1/2,系统的快速性得到了提高。
在这里插入图片描述
在这里插入图片描述

抗积分饱和的 PID 控制算法 C 语言实现

所谓的积分饱和现象是指如果系统存在一个方向的偏差,PID 控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置,若控制器输出 U(k)继续增大,执行器开度不可能再增大,此时计算机输出控制量超出了正常运行范围而进入饱和区。一旦系统出现反向偏差,u(k)逐渐从饱和区退出。进入饱和区越深则退出饱和区时间越长。在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应的改变,这时系统就像失控一样,造成控制性能恶化,这种现象称为积分饱和现象或积分失控现象。

防止积分饱和的方法之一就是抗积分饱和法,该方法的思路是在计算 u(k)时,首先判断上一时刻的控制量 u(k-1)是否已经超出了极限范围: 如果u(k-1)>umax,则只累加负偏差; 如果 u(k-1)<umin,则只累加正偏差。从而避免控制量长时间停留在饱和区。直接贴出代码,不懂的看看前面几节的介绍。

struct _pid{
float SetSpeed; //定义设定值
float ActualSpeed; //定义实际值
float err; //定义偏差值
float err_last; //定义上一个偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
float voltage; //定义电压值(控制执行器的变量)
float integral; //定义积分值
float umax;
float umin;
}pid;
void PID_init(){
printf("PID_init begin \n");
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.1; //注意,和上几次相比,这里加大了积分环节的值
pid.Kd=0.2;
pid.umax=400;
pid.umin=-200;
printf("PID_init end \n");
}
float PID_realize(float speed){
int index;
PID 控制----C 语言讲解
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
if(pid.ActualSpeed>pid.umax) //灰色底色表示抗积分饱和的实现
{
if(abs(pid.err)>200) //蓝色标注为积分分离过程
{
index=0;
}else{
index=1;
if(pid.err<0)
{
pid.integral+=pid.err;
} }
}else if(pid.ActualSpeed<pid.umin){
if(abs(pid.err)>200) //积分分离过程
{
index=0;
}else{
index=1;
if(pid.err>0)
{
pid.integral+=pid.err;
} }
}else{
if(abs(pid.err)>200) //积分分离过程
{
index=0;
}else{
index=1;
pid.integral+=pid.err;
} }
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.
err-pid.err_last);
pid.err_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;
return pid.ActualSpeed;
}

最终的测试程序运算结果如下,可以明显的看出系统的稳定时间相对前几次来讲
缩短了不少。
在这里插入图片描述

Chapter3 PID控制器开发笔记之二:积分分离PID控制器的实现

原文链接:https://blog.csdn.net/foxclever/article/details/80274790

2、算法实现

这一部分,我们根据前面对其基本思想的描述,来实现基于积分分离的PID算法实现,同样是包括位置型和增量型两种实现方式。首先我们来看一下算法的实现过程,具体的流程图如下:
在这里插入图片描述

有上图我们知道,与普通的PID算法的区别,只是判断偏差的大小,偏差大时,为PD算法,偏差小时为PID算法。于是我们需要一个偏差检测与积分项分离系数β的函数。

static uint16_t BetaGeneration(float error,float epsilon)
{
  uint16_t beta=0;
 
  if(abs(error)<= epsilon)
{
  beta=1;
}
 
return beta;
 
}

2.1、位置型PID算法实现

根据前面的分析我们可以很轻松的编写程序,只需要在编写程序时判断偏差以确定是否引入积分项就可以了。同样先定义PID对象的结构体:

/*定义结构体和公用体*/
typedef struct
{
  floatsetpoint;       //设定值
  floatproportiongain;     //比例系数
  floatintegralgain;      //积分系数
  floatderivativegain;    //微分系数
  floatlasterror;     //前一拍偏差
  floatresult; //输出值
  floatintegral;//积分值
  float epsilon; //偏差检测阈值
}PID;

接下来实现PID控制器:

void PIDRegulation(PID *vPID, float processValue)
{
  floatthisError;
 thisError=vPID->setpoint-processValue;
 vPID->integral+=thisError;
  uint16_tbeta= BetaGeneration(error,vPID->epsilon);
 
  if(beta>0)
{
 vPID->result=vPID->proportiongain*thisError+vPID->derivativegain*(thisError-vPID->lasterror);
}
else
{
vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror);
}
 
 vPID->lasterror=thisError;
 
}

与普通的PID算法的区别就是上述代码中增加了偏差判断,来决定积分项的分离与否。

2.2、增量型PID算法实现

对于增量型PID控制,我们也可以采取相同的处理。首先定义PID对象的结构体:

/*定义结构体和公用体*/
typedef struct
{
  floatsetpoint;       //设定值
  floatproportiongain;     //比例系数
  floatintegralgain;      //积分系数
  floatderivativegain;    //微分系数
  floatlasterror;     //前一拍偏差
  floatpreerror;     //前两拍偏差
  floatdeadband;     //死区
  floatresult; //输出值
  float epsilon; //偏差检测阈值
}PID;

接下来实现PID控制器:

void PIDRegulation(PID *vPID, float processValue)
{
  floatthisError;
  floatincrement;
  floatpError,dError,iError;
 
 thisError=vPID->setpoint-processValue; //得到偏差值
 pError=thisError-vPID->lasterror;
 iError=thisError;
 dError=thisError-2*(vPID->lasterror)+vPID->preerror;
  uint16_tbeta= BetaGeneration(error,vPID->epsilon);
 
  if(beta>0)
{
increment=vPID->proportiongain*pError+vPID->derivativegain*dError;   //增量计算
}
else
{
increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError;   //增量计算
}
 vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
 vPID->lasterror=thisError;
 vPID->result+=increment;
}

这就实现了增量型PID控制器积分分离算法,也没有考虑任何的干扰条件,仅仅只是对数学公式的计算机语言化。

3、总结

积分分离算法的思想非常简单。当然,对于β的取值,很多人提出了改进措施,例如分多段取值,设定多个阈值ε1、ε2、ε3、ε4等,不过这些阈值也需要根据实际的系统来设定。除了分段取值外,甚至也有采用函数关系来获取β值。当然,这样处理后就不再是简单的积分分离了,特别是在增量型算法中,实际上已经演变为一种变积分算法了。已经偏离了积分分离算法的设计思想,在后面我们会进一步说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值