Chinaunix首页 | 论坛 | 博客
  • 博客访问: 646895
  • 博文数量: 194
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 884
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-21 16:48
文章分类

全部博文(194)

文章存档

2023年(1)

2022年(3)

2021年(16)

2020年(4)

2019年(5)

2018年(10)

2017年(72)

2016年(36)

2015年(47)

我的朋友

分类: 嵌入式

2021-09-24 14:51:26

转:https://www.cnblogs.com/foxclever/p/9127104.html

从PID控制的基本原理我们知道,微分信号的引入可改善系统的动态特性,但也存在一个问题,那就是容易引进高频干扰,在偏差扰动突变时尤其显出微分项的不足。为了解决这个问题人们引入低通滤波方式来解决这一问题。

1、不完全微分的基本思想

  微分项有引入高频干扰的风险,但若在控制算法中加入低通滤波器,则可使系统性能得到改善。方法之一就是在PID算法中加入一个一阶低通滤波器。这就是所谓的不完全微分,其结构图如下:

 

或者是另一种形式:

 

在这里我们考虑第一种结构形式。在这种情况下,微分与一阶惯性环节结合,其微分部分的计算公式可表示如下:

 

其中α的取值在0和1之间,有滤波常数和采样周期确定。据此我们将其增量化,则可以得到为不完全微分的增量计算公式:

 

或者表示为:

 

这两种表示方式是等价的,第二种表示法与我们的完全微分PID算法增量型式表示更接近,好理解。而且与位置型的表示法也更为一致,所以我们选择第二种表示法。

2、算法实现

经过前面的分析及公式推导,我们想要实现不完全微分其实已经相当容易了。为了便于理解,我们保持比例和积分为基本的格式,只对微分部分采用不完全微分算法。

1)位置型PID算法实现

位置型PID实现过程与前面的一样,所不同的是需要增加前一个Ud值。首先定义PID对象的结构体:

点击(此处)折叠或打开

  1. /*定义结构体和公用体*/
  2. typedef struct
  3. {
  4.   float setpoint; //设定值
  5.   float proportiongain; //比例系数
  6.   float integralgain; //积分系数
  7.   float derivativegain; //微分系数
  8.   float lasterror; //前一拍偏差
  9.   float lastdev; //前一拍时的微分项值
  10.   float alpha; //不完全微分系数
  11.   float result; //输出值
  12.   float integral;//积分值
  13. }PID;



接下来实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)
{
  float thisError;
  float thisDev;

  thisError=vPID->setpoint-processValue;
  vPID->integral+=thisError;
  thisDev= vPID->derivativegain*(1- vPID-> alpha)*(thisError-vPID->lasterror)+ vPID-> alpha* vPID-> lastdev;


  vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+ thisDev;
  vPID->lasterror=thisError;
  vPID->lastdev = thisDev;
}


现了一个最简单不完全微分的位置型PID控制器,当然没有考虑任何干扰条件,仅仅只是对数学公式的计算机语言化。

2)增量型PID算法实现

  增量型不完全微分PID控制器的实现就是以前面的增量型公式为基础。首先定义PID对象的结构体:

点击(此处)折叠或打开

  1. /*定义结构体和公用体*/
  2. typedef struct
  3. {
  4.   float setpoint; //设定值
  5.   float proportiongain; //比例系数
  6.   float integralgain; //积分系数
  7.   float derivativegain; //微分系数
  8.   float lasterror; //前一拍偏差
  9.   float preerror; //前两拍偏差
  10.   float lastdeltadev; //前一拍时的微分项增量
  11.   float alpha; //不完全微分系数
  12.   float deadband; //死区
  13.   float result; //输出值
  14. }PID;


接下来实现PID控制器:

点击(此处)折叠或打开

  1. void PIDRegulation(PID *vPID, float processValue)
  2. {
  3.   float thisError;
  4.   float increment;
  5.   float deltaDev;
  6.   float pError,dError,iError;

  7.   thisError=vPID->setpoint-processValue; //得到偏差值
  8.   pError=thisError-vPID->lasterror;
  9.   iError=thisError;
  10.   dError=thisError-2*(vPID->lasterror)+vPID->preerror;

  11.   deltaDev= vPID->derivativegain*(1- vPID-> alpha)*dError+ vPID-> alpha* vPID-> lastdeltadev;

  12.   increment=vPID->proportiongain*pError+vPID->integralgain*iError+ deltaDev; //增量计算

  13.   vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
  14.   vPID->lasterror=thisError;
  15.   vPID-> lastdeltadev = deltaDev;

  16.   vPID->result+=increment;

  17. }


这就实现了一个最简单的增量型不完全微分PID控制器,也没有考虑任何的干扰条件,仅仅只是对数学公式的计算机语言化。

3、总结

  不完全微分方式在微分环节采用了低通滤波有效地提高了微分项的特性。其中α的取值是一个0~1之间的数。两个极限值,在0时其实就是没有滤波的普通微分环节;而取1时,则没有微分作用。所以α的取值对不完全微分的效果是至关重要的,一般要根据被控对象的特性来确定。

阅读(1052) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~