在普通的PID控制算法中,由于积分系数Ki是常数,所以在整个控制过程中,积分增量是不变的。然而,系统对于积分项的要求是,系统偏差大时,积分作用应该减弱甚至是全无,而在偏差小时,则应该加强。积分系数取大了会产生超调,甚至积分饱和,取小了又不能短时间内消除静差。因此,如何根据系统的偏差大小改变积分速度,对提高系统的品质是有必要的。变积分PID算法正好可以满足这一要求。

1、变积分的基本思想

  变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小相对应:偏差越大,积分越慢; 偏差越小,积分越快。设定系数为f(err(k)),它是err(k)的函数。当|err(k)|增大时,f减小,反之增大。变积分的PID积分项表达式为:

  其中f(err(k))与|err(k)|的函数关系可根据具体情况设定,可以是线性的也可以是非线性的,通常比较简单的设置如下:

  由以上公式可知,f(err(k))的值在[0,1]区间变化,当偏差值|err(k)|大于分离区间A+B时,不对当前偏差err(k)进行累加;当偏差值|err(k)|小于B时,加入当前偏差err(k)进行累加;介于B和A+B的区间时,按一定函数关系随err(k)变化。于是变积分PID算法可以表示为:

  上述的f(err(k))函数只是我们列举的一种,事实上可以采取任何可行的方式,甚至是非线性函数,只要更符合控制对象的特性。

  对于用增量型PID算法的变积分表示如下:

  看到这个公式,很多人可能会发觉与前面的积分分离算法的公式很象。特别是在增量型算法中,它们的形式确实是一样的,但表达的意思确是有一定区别,那么我们来看看有什么不同呢?在后面我们再作总结。

2、算法实现

  变积分实际上是通过对偏差的判断,让积分以不同的速度累计。这一系数介于0-1之间,可以通过多种方式实现,在这里我们按线性方式实现。变积分的控制流程图如下:

  首先实现一个处理f(e(k))的函数,有前面的函数关系表达式,实现为响应的编码就很简单了:

 /* 变积分系数处理函数,实现一个输出0和1之间的分段线性函数            */
/* 当偏差的绝对值小于最小值时,输出为1;当偏差的绝对值大于最大值时,输出为0 */
/* 当偏差的绝对值介于最大值和最小值之间时,输出在0和1之间现行变化 */
/* float error,当前输入的偏差值 */
/* float absmax,偏差绝对值的最大值 */
/* float absmin,偏差绝对值的最小值 */
static float VariableIntegralCoefficient(float error,float absmax,float absmin)
{ float factor=0.0; if(abs(error)<=absmin)
{ factor=1.0; }
else if(abs(error)>absmax)
{ factor=0.0; }
else { factor=(absmax-abs(error))/(absmax-absmin); } return factor; }

1)位置型PID算法实现

  变积分基于位置型PID的实现就是更具偏差绝对值的大小获取变积分的系数。然后再实现PID算法,同样首先定义PID对象的结构体:

 /*定义结构体和公用体*/

 typedef struct

 {

   float setpoint;       //设定值

   float proportiongain;     //比例系数

   float integralgain;      //积分系数

   float derivativegain;    //微分系数

   float lasterror;     //前一拍偏差

   float result; //输出值

   float integral;//积分值

 float errorabsmax;  //偏差绝对值最大值

 float errorabsmin;  //偏差绝对值最小值

 }PID;

  接下来实现PID控制器:

 void PIDRegulation(PID *vPID, float processValue)
{ float thisError; float factor; thisError=vPID->setpoint-processValue; factor= VariableIntegralCoefficient(thisError, vPID->errorabsmax, vPID->errorabsmin); vPID->integral+= factor*thisError; vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror); vPID->lasterror=thisError; }

2)增量型PID算法实现

  同样变积分基于增量型PID的实现也是一样的。首先定义PID对象的结构体:

 /*定义结构体和公用体*/
typedef struct
{ float setpoint; //设定值 float proportiongain; //比例系数 float integralgain; //积分系数 float derivativegain; //微分系数 float lasterror; //前一拍偏差 float preerror; //前两拍偏差 float deadband; //死区 float result; //输出值 float errorabsmax; //偏差绝对值最大值 float errorabsmin; //偏差绝对值最小值 }PID;

  接下来实现PID控制器:

 void PIDRegulation(PID *vPID, float processValue)
{ float thisError; float increment; float pError,dError,iError; float factor; thisError=vPID->setpoint-processValue; //得到偏差值 factor= VariableIntegralCoefficient(thisError, vPID->errorabsmax, vPID->errorabsmin); pError=thisError-vPID->lasterror; iError= factor*thisError; dError=thisError-*(vPID->lasterror)+vPID->preerror; increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError; //增量计算 vPID->preerror=vPID->lasterror; //存放偏差用于下次运算 vPID->lasterror=thisError; vPID->result+=increment; }

3、总结

  变积分实际上有一定的专家经验在里面,因为限值的选取以及采用什么样的函数计算系数,有很大的灵活性。

我们在前面做了积分分离的算法,这次又说了变积分的算法。他们有相通的地方,也有不同的地方,下面对他们进行一些说明。

首先这两种算法的设计思想是有区别的。积分分离的思想是偏差较大时,取消积分;而偏差较小时引入积分。变积分的实现是想是设法改变积分项的累加速度,偏差大时减弱积分;而偏差小时强化积分。有些所谓改进型的积分分离算法实际已经脱离了积分分离的基本思想,而是动态改变积分系数。就这一点而言,特别是在增量型算法中,已经属于变积分的思想了。

  其次,对于积分分离来说,该操作是针对整个积分项操作,这一点在位置型PID算法中,表现的尤为明显。而对于变积分来说,是针对当前偏差的积分累计,就是说只影响当前这次的积分部分。再者,具体的实现方式也存在区别,特别是在位置型PID方式下尤为明显。

  我们在这里讨论它们的区别原因,佷显然就是我们没办法同时采用这两种优化方式,只能分别实现,在后面我们将实现基于积分项的优化。

欢迎关注:

PID控制器开发笔记之五:变积分PID控制器的实现的更多相关文章

  1. PID控制器开发笔记(转)

    源: PID控制器开发笔记

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

    前面的文章中,我们已经讲述了PID控制器的实现,包括位置型PID控制器和增量型PID控制器.但这个实现只是最基本的实现,并没有考虑任何的干扰情况.在本节及后续的一些章节,我们就来讨论一下经典PID控制 ...

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

    从微积分的基本原理看,积分的实现是在无限细分的情况下进行的矩形加和计算.但是在离散状态下,时间间隔已经足够大,矩形积分在某些时候显得精度要低了一些,于是梯形积分被提出来以提升积分精度. 1.梯形积分基 ...

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

    积分作用的引入是为了消除系统的静差,提高控制精度.但是如果一个系统总是存在统一个方向的偏差,就可能无限累加而进而饱和,极大影响系统性能.抗积分饱和就是用以解决这一问题的方法之一.这一节我们就来实现抗积 ...

  5. PID控制器开发笔记之八:带死区的PID控制器的实现

    在计算机控制系统中,由于系统特性和计算精度等问题,致使系统偏差总是存在,系统总是频繁动作不能稳定.为了解决这种情况,我们可以引入带死区的PID算法. 1.带死区PID的基本思想 带死区的PID控制算法 ...

  6. PID控制器开发笔记之十三:单神经元PID控制器的实现

    神经网络是模拟人脑思维方式的数学模型.神经网络是智能控制的一个重要分支,人们针对控制过程提供了各种实现方式,在本节我们主要讨论一下采用单神经元实现PID控制器的方式. 1.单神经元的基本原理 单神经元 ...

  7. PID控制器开发笔记之十二:模糊PID控制器的实现

    在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题.模糊PID控制器是将模糊算法与PID控 ...

  8. PID控制器开发笔记之十一:专家PID控制器的实现

    前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法,基本已经覆盖了无模型和简单模型PID控制经典算法的大部.再接下来的我们将讨论智能PID控制,智能PID控制不同于常规意义下的智能控制,是 ...

  9. PID控制器开发笔记之十:步进式PID控制器的实现

    对于一般的PID控制系统来说,当设定值发生较大的突变时,很容易产生超调而使系统不稳定.为了解决这种阶跃变化造成的不利影响,人们发明了步进式PID控制算法. 1.步进式PID的基本思想 所谓步进式PID ...

随机推荐

  1. 四十一、Linux 线程——线程同步之条件变量

    41.1 概念 41.1.1 条件变量的介绍 互斥锁的缺点是它只有两种状态:锁定和非锁定 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足 条件变量内部是一个等待队列,放置等待 ...

  2. GCC编译器原理(二)------编译原理一:目标文件

    一.目标文件 在 UNIX® 和 Linux® 中,任何事物都是文件.UNIX 和 Linux 编程实际上是编写处理各种文件的代码.系统由许多类型的文件组成,但目标文件具有一种特殊的设计,提供了灵活和 ...

  3. luogu 1314 聪明的质检员

    二分答案的边界问题还是要注意 double挨着,int+1-1, 此题用到long long,所以初始化ans要足够大,前缀和优化 依然根据check答案大小左右mid,虽然有s,但是有了+1-1加持 ...

  4. MySQL自动编号与主键

    1.自动编号(AUTO_INCREMENT),必须与主键组合使用 默认情况下,起始值为1,增量也为1. 2.主键(PRIMARY KEY) 每张数据表只能存在一个主键 主键保证记录的唯一性 主键自动为 ...

  5. c# cbo控件

    c#  cbo控件 ,要获取选中的值 最好使用 ((强转的类型)selectitem).属性

  6. [C++]数值与字符串转换问题

    #include <stdio.h>//sprintf #include <stdlib.h>//atof,atol,strtod,strtol using namespace ...

  7. JQ中的 offsetTop 和 offset().top 的区别

    话不多说先上图: offset()的top是指元素与document的上边的距离,而不是浏览器当前窗体的上边缘,如图 document高度超过window,浏览器出现滚动条,滚动滚动条,提交按钮的of ...

  8. Windows 7 SP1无人值守自动应答文件制作

    使用U盘安装Windows系统时,很多人都会使用UltraISO工具来制作U盘启动盘,然后插入到电脑中加以安装.系统的安装过程中,需要一步一步手动选择或者输入配置,Windows是支持无人值守自动应答 ...

  9. java中的进程与线程及java对象的内存结构【转】

    原文地址:http://rainforc.iteye.com/blog/2039501   1.实现线程的三种方式:   使用内核线程实现     内核线程(Kernel Thread, KLT)就是 ...

  10. Learning Spread-out Local Feature Descriptors

    论文Learning Spread-out Local Feature Descriptors 为什么介绍此文:引入了一种正则化手段,结合其他网络的损失函数,尤其是最新cvpr 2018的hardne ...