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

前面的文章中,我们已经讲述了PID控制器的实现,包括位置型PID控制器和增量型PID控制器。但这个实现只是最基本的实现,并没有考虑任何的干扰情况。在本节及后续的一些章节,我们就来讨论一下经典PID控制器的优化与改进。这一节我们首先来讨论针对积分项的积分分离优化算法。

1、基本思想

我们已经讲述了PID控制引入积分主要是为了消除静差,提高控制精度。但在过程的启动、结束或大幅度增减设定值时,短时间内系统输出有很大偏差,会造成PID运算的积分累积,引起超调或者振荡。为了解决这一干扰,人们引入了积分分离的思想。其思路是偏差值较大时,取消积分作用,以免于超调量增大;而偏差值较小时,引入积分作用,以便消除静差,提高控制精度。

具体的实现步骤是:根据实际情况,设定一个阈值;当偏差大于阈值时,消除积分仅用PD控制;当偏差小于等于阈值时,引入积分采用PID控制。则控制算法可表示为:

其中β称为积分开关系数,其取值范围为:

由上述表述及公式我们可以知道,积分分离算法的效果其实与ε值的选取有莫大关系,所以ε值的选取实际上是实现的难点,ε值过大则达不到积分分离的效果,而ε值过小则难以进入积分区,ε值的选取存在很大的主观因素。

对于经典的增量式PID算法,似乎没有办法由以上的公式推导而来,因为β随着err(k)的变化在不是修改着控制器的表达式。其实我们可以换一种角度考虑,每次系统调节未定后,偏差应该为零,然后只有当设定值改变时,系统才会响应而开始调节。设定值的改变实际上是一个阶跃变化,此时的控制输出记为U0,开始调节时,其调节增量其实与之前的一切没有关系。所以我们就可以以变化时刻开始为起点,而得到带积分分离的增量算法,以保证在启动、停止和快速变化时防止超调。公式如下:

其中β的取值与位置型PID算法一致。可能有人会担心偏差来回变化,造成积分作用的频繁分离和引入,进而使上述的增量表达式无法实现。其实我们分析一下就能发现,在开始时,由于设定值变化引起的偏差大而分离了积分作用,在接近设定值时,偏差变小就引入了积分,一边消除静差,而后处于稳态,直到下一次变化。

2、算法实现

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

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

 1 static uint16_t BetaGeneration(float error,float epsilon)
 2
 3 {
 4
 5   uint16_t beta=0;
 6
 7   if(abs(error)<= epsilon)
 8
 9 {
10
11   beta=1;
12
13 }
14
15 return beta;
16
17 }

1)位置型PID算法实现

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

 1 /*定义结构体和公用体*/
 2
 3 typedef struct
 4
 5 {
 6
 7   float setpoint;       //设定值
 8
 9   float proportiongain;     //比例系数
10
11   float integralgain;      //积分系数
12
13   float derivativegain;    //微分系数
14
15   float lasterror;     //前一拍偏差
16
17   float result; //输出值
18
19   float integral;//积分值
20
21   float epsilon; //偏差检测阈值
22
23 }PID;

接下来实现PID控制器:

 1 void PIDRegulation(PID *vPID, float processValue)
 2
 3 {
 4
 5   float thisError;
 6
 7   thisError=vPID->setpoint-processValue;
 8
 9   vPID->integral+=thisError;
10
11   uint16_t beta= BetaGeneration(error, vPID->epsilon);
12
13   if(beta>0)
14
15 {
16
17   vPID->result=vPID->proportiongain*thisError+vPID->derivativegain*(thisError-vPID->lasterror);
18
19 }
20
21 else
22
23 {
24
25 vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror);
26
27 }
28
29
30
31   vPID->lasterror=thisError;
32
33 }

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

2)增量型PID算法实现

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

 1 /*定义结构体和公用体*/
 2
 3 typedef struct
 4
 5 {
 6
 7   float setpoint;       //设定值
 8
 9   float proportiongain;     //比例系数
10
11   float integralgain;      //积分系数
12
13   float derivativegain;    //微分系数
14
15   float lasterror;     //前一拍偏差
16
17   float preerror;     //前两拍偏差
18
19   float deadband;     //死区
20
21   float result; //输出值
22
23   float epsilon; //偏差检测阈值
24
25 }PID;

接下来实现PID控制器:

 1 void PIDRegulation(PID *vPID, float processValue)
 2
 3 {
 4
 5   float thisError;
 6
 7   float increment;
 8
 9   float pError,dError,iError;
10
11
12
13   thisError=vPID->setpoint-processValue; //得到偏差值
14
15   pError=thisError-vPID->lasterror;
16
17   iError=thisError;
18
19   dError=thisError-2*(vPID->lasterror)+vPID->preerror;
20
21   uint16_t beta= BetaGeneration(error, vPID->epsilon);
22
23   if(beta>0)
24
25 {
26
27 increment=vPID->proportiongain*pError+vPID->derivativegain*dError;   //增量计算
28
29 }
30
31 else
32
33 {
34
35 increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError;   //增量计算
36
37 }
38
39   vPID->preerror=vPID->lasterror;  //存放偏差用于下次运算
40
41   vPID->lasterror=thisError;
42
43   vPID->result+=increment;
44
45 }

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

3、总结

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

欢迎关注:

原文地址:https://www.cnblogs.com/foxclever/p/8969944.html

时间: 2024-10-14 16:49:16

PID控制器开发笔记之二:积分分离PID控制器的实现的相关文章

微信订阅号开发笔记(二)

微信开发的流程其实很简单 o(∩_∩)o 哈哈!在微信网站的编辑操作 额,就不说了.虽然有人问过.下面是我的微信开发过程,简单记录下. 成为开发者 材料:1.自己的服务器资源,百度的BAE,新浪的SAE都不错. 2.懂那么点编程语言. 3.注册微信公众号. 上面的都有了之后,就可以自己动手开发了.哇咔咔,好兴奋.有木有. 在登录进去之后,怎么成为开发者?不知道,自己看去. 开始coding吧. 1.验证 if (! empty ( $_GET ['echostr'] ) && ! empt

ANDROID开发笔记(二)

动机: 开发的一个背单词的软件. 不会实现划屏的特性. 方法: 第一步尝试: 在MainActivity中, 增加以下代码后, 如果在视图的空白处点击时, 文本框中的时间就会发生改变. @Override     public boolean onTouchEvent(MotionEvent event) {         // TODO Auto-generated method stub         final TextView textview = (TextView)findVie

PID控制器开发笔记之三:抗积分饱和PID控制器的实现

积分作用的引入是为了消除系统的静差,提高控制精度.但是如果一个系统总是存在统一个方向的偏差,就可能无限累加而进而饱和,极大影响系统性能.抗积分饱和就是用以解决这一问题的方法之一.这一节我们就来实现抗积分饱和的PID算法. 1.抗积分饱和的基本思想 所谓积分饱和就是指系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而扩大,从而导致控制器输出不断增大超出正常范围进入饱和区.当系统出现反响的偏差时,需要首先从饱和区退出,而不能对反向的偏差进行快速的响应. 为了解决积分饱和的问题,人们引

cocos2dx3.0 超级马里奥开发笔记(二)——正确规划游戏的逻辑

本来想出一个完整的开发笔记,因为个人原因,代码已经OK了,博客的话就不贴代码了,直接讲解一下整个游戏的设计,更确切的说是新手开发时应该注意的地方. 1.角色类正确的继承和扩展. 我们要封装一个角色类,第一印象就是封装一个继承自sprite的精灵,里面封装好玛丽的动作和角色属性等.继承自sprite是可行的,我们只要重写几个static create函数,然后把这个精灵贴到层上即可. 仔细考虑一下,如果角色要再添加一个特效跟随呢,角色吃到道具出现幻影分身呢?一系列的BT需求会发现继承自sprite

PID控制器开发笔记之四:梯形积分PID控制器的实现

从微积分的基本原理看,积分的实现是在无限细分的情况下进行的矩形加和计算.但是在离散状态下,时间间隔已经足够大,矩形积分在某些时候显得精度要低了一些,于是梯形积分被提出来以提升积分精度. 1.梯形积分基本思路 在PID控制其中,积分项的作用是消除余差,为了尽量减小余差,应提高积分项的运算精度.在积分项中,默认是按矩形方式来计算积分,将矩形积分改为梯形积分可以提高运算精度.其计算公式为: 于是如果在位置型PID算法中引入梯形积分则可以修改计算公式如下: 同样要在增量型PID算法中引入梯形积分则可以修

Modbus库开发笔记之二:Modbus消息帧的生成

前面我们已经对Modbus的基本事务作了说明,也据此设计了我们将要实现的主从站的操作流程.这其中与Modbus直接相关的就是Modbus消息帧的生成.Modbus消息帧也是实现Modbus通讯协议的根本. 1.Modbus消息帧分析 MODBUS协议在不同的物理链路上的消息帧有一些差异,但我们分析一下就会发现,在这些不同的消息帧中具有一下相同的部分,这对我们实现统一的数据操作非常重要,具体描述如下: (1).简单协议数据单元 MODBUS协议定义了一个与基础通信层无关的简单协议数据单元(PDU)

discuz二次开发笔记(二)------跳转函数运用

前几天在增加修改功能时,突然用到一个提示函数,有点不理解,看了他的由来后果断做下笔记,感觉这在以后的开发中肯定还是要用的上的.有些地方不是很理解,在以后慢慢纠正.查补. Htm页面中用的js跳转: $("#lyy_real").click(function(){ $.post("api/realnamechange.php", {uname:$("#uname").val(),uid:$("#uid").val(),realn

钉钉开发笔记(二)MySQL的配置

最近在编写web的过程中,经常需要与后台工作人员互动.由于比较麻烦.没有效率. 就果断的请教了,公司的后台大牛,学习下数据库的一些简单操作,现在就把利用MySQL连接服务器, 进行可视化操作的简单步骤,记录下来,希望对大家也会有所帮助.       经过以上几步之后就会经过配置得到一个操作数据库的入口了, 可以进行删除,添加,查询的一些简单操作了.

Neo4j图数据库管理系统开发笔记之二:嵌入式服务端系统界面一览

最近在neo4j java api和rmi的基础上,设计了一套neo4j管理工具,分为server端和client端,中间用rmi进行通信.基本功能包括图数据库基本信息维护管理(创建.编辑.删除.统计等),图数据库数据维护管理(创建节点和关系.编辑节点和关系属性信息.节点标签管理.索引管理.删除管理.路径深度遍历.两点之间路径寻址等),RMI服务管理等功能. 先把部分功能界面贴出来,希望能对别人有所帮助,如果有需要代码的话,给我留言.