前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进PID控制器以实现动态调整参数的目的。

1、提出问题

在我们一开始开发PID控制器时,我们主要是关注于其算法的实现而没有过多的关心其使用过程。但在我们的使用过程中发现有些不够灵活的地方。

在原有的PID控制器中,设定值是通过在外部给PID对象的参数赋值实现的,虽然说并不影响使用,但我们若想对PID控制器中的参数设定值进行某些处理就不是很方便了。而在原有的PID控制器中,输出值在外部是不可见的,只能通过PID对象查看且不可更改。这些使得对这些参数的操作显得不够灵活。

而且在原有的PID控制器中3个调节参数也不能在外部随时调整,这显然不符合很多应用的需要,因为PID参数的调整是很常见的工作。所以在这篇中我们来考虑实现这些参数的动态调整。

2、分析设计

为了使得PID控制器使用起来更为灵活,我们需要将PID对象作必要的改动。关于PID对象我们考虑将测量值、设定值、输出值作为对象的属性。但我们不是直接将这几个变量作为对象属性,因为这样达不到我们从外部灵活操作的目的,我们将几个指向浮点变量的指针作为对象的属性,而初始化后这几个指针将指向我们的测量值、设定值、输出值变量。

同样的三个PID参数我们想要在外部修改它,我们也将其在外部定义为变量,而在PID对象中定义为指向这三个变量的浮点数指针。在对对象进行初始化时,我们将变量地址赋值给这几个指针。据此我们定义PID对象类型为:

/*定义结构体和公用体*/
typedef struct CLASSIC
{float *pPV;                   //测量值指针float *pSV;                   //设定值指针float *pMV;                   //输出值指针float *pKp;                   //比例系数指针float *pKi;                   //积分系数指针float *pKd;                   //微分系数指针float setpoint;               //设定值float lasterror;              //前一拍偏差float preerror;               //前两拍偏差float deadband;               //死区float result;                 //PID控制器计算结果float output;                 //输出值0-100%float maximum;                //输出值上限float minimum;                //输出值下限float errorabsmax;            //偏差绝对值最大值float errorabsmin;            //偏差绝对值最小值float alpha;                  //不完全微分系数float deltadiff;              //微分增量float integralValue;          //积分累计量float gama;                   //微分先行滤波系数float lastPv;                 //上一拍的过程测量值float lastDeltaPv;            //上一拍的过程测量值增量
}CLASSICPID;

3、软件实现

我们计划将PID参数和过程变量改成指向浮点型变量的指针,那么代码上需要做哪些修改呢?需要修改的主要是两个函数:PID调节函数和PID对象初始化函数。

首先,我们来看一看PID对象的初始化函数。我们知道将这些变量修改为指向浮点变量法的指针后,我们就必须在初始化时指定具体的变量地址,否则指向的将是不可预知的位置。所以我们修改初始化函数如下:

/* PID初始化操作,需在对vPID对象的值进行修改前完成 */
void PIDParaInitialization(CLASSICPID *vPID,    //PID控制器对象float *pPV,          //测量值指针float *pSV,          //设定值指针float *pMV,          //输出值指针float *pKp,          //比例系数指针float *pKi,          //积分系数指针float *pKd,          //微分系数指针float vMax,          //控制变量量程float vMin,          //控制变量的零点)
{if((vPID==NULL)||(pPV==NULL)||(pSV==NULL)||(pMV==NULL)||(pKp==NULL)||(pKi==NULL)||(pKd==NULL)){return;}vPID->pPV=pPV;vPID->pSV=pSV;vPID->pMV=pMV;vPID->pKp=pKp;vPID->pKi=pKi;vPID->pKd=pKd;vPID->maximum=vMax;                /*输出值上限*/vPID->minimum=vMin;                /*输出值下限*/vPID->setpoint=*pPV;               /*设定值*/vPID->lasterror=0.0;              /*前一拍偏差*/vPID->preerror=0.0;               /*前两拍偏差*/vPID->result=vMin;                /*PID控制器结果*/vPID->output=0.0;                 /*输出值,百分比*/vPID->errorabsmax=(vMax-vMin)*0.8;vPID->errorabsmin=(vMax-vMin)*0.2;vPID->deadband=(vMax-vMin)*0.0005;               /*死区*/vPID->alpha=0.2;                  /*不完全微分系数*/vPID->deltadiff=0.0;                /*微分增量*/vPID->integralValue=0.0;vPID->mode=mode;
}

其次,我们还需要修改PID调节函数。在原来的PID调节器中过程值是作为函数的参数输入的,而且PID参数是作为变量存在于对象内部的,所以要针对这两个方面做相应的修改:

/* 通用PID控制器,采用增量型算法,具有变积分,梯形积分和抗积分饱和功能,微分项采用不完全微分,一阶滤波,alpha值越大滤波作用越强                    */
void PIDRegulator(CLASSICPID *vPID)
{float thisError;float result;float factor;float increment;float pError,dError,iError;vPID->setpoint=*vPID->pSV;thisError=vPID->setpoint-(*vPID->pPV); //得到偏差值result=vPID->result;if (fabs(thisError)>vPID->deadband){pError=thisError-vPID->lasterror;iError=(thisError+vPID->lasterror)/2.0;dError=thisError-2*(vPID->lasterror)+vPID->preerror;//变积分系数获取factor=VariableIntegralCoefficient(thisError,vPID->errorabsmax,vPID->errorabsmin);//计算微分项增量带不完全微分vPID->deltadiff=(*vPID->pKd)*(1-vPID->alpha)*dError+vPID->alpha*vPID->deltadiff;increment=(*vPID->pKp)*pError+(*vPID->pKi)*factor*iError+vPID->deltadiff;   //增量计算}else{if((fabs(vPID->setpoint-vPID->minimum)<vPID->deadband)&&(fabs((*vPID->pPV)-vPID->minimum)<vPID->deadband)){result=vPID->minimum;}increment=0.0;}result=result+increment;/*对输出限值,避免超调和积分饱和问题*/if(result>=vPID->maximum){result=vPID->maximum;}if(result<=vPID->minimum){result=vPID->minimum;} vPID->preerror=vPID->lasterror;  //存放偏差用于下次运算vPID->lasterror=thisError;vPID->result=result;vPID->output=(vPID->result-vPID->minimum)/(vPID->maximum-vPID->minimum)*100.0;*vPID->pMV=vPID->output;}
}

4、总结

我们将PID参数和过程变量都改为了对象所包含的指针,这样当我们从上位机或者其他进程修改变量的值时,也同步修改了PID对象中的值。测试的结果比原来的方式操作更为方便。

欢迎关注:

PID控制器改进笔记之一:改进PID控制器之参数动态调整相关推荐

  1. PID控制器开发笔记之一:PID算法原理及基本实现

           在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于 ...

  2. PID控制器开发笔记之七:微分先行PID控制器的实现

    前面已经实现了各种的PID算法,然而在某些给定值频繁且大幅变化的场合,微分项常常会引起系统的振荡.为了适应这种给定值频繁变化的场合,人们设计了微分先行算法. 1.微分先行算法的思想 微分先行PID控制 ...

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

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

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

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

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

    源: PID控制器开发笔记 转载于:https://www.cnblogs.com/LittleTiger/p/10499701.html

  6. PID控制器概述及python实现PID控制算法

    PID控制器简要分析 PID控制器概述 PID控制器的分类 位置式PID 增量式PID 代码实现 参数整定 PID控制器概述 PID控制器是自动控制领域一种常见的控制器,其简单易设计的结构和良好的鲁棒 ...

  7. PID控制器改进笔记之六:改进PID控制器之参数设定

      前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器.这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提 ...

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

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

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

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

最新文章

  1. 云端卫士架构师讲DDoS攻击的智能防御之道
  2. pandas基于列表内容对dataframe数据行进行筛选(isin函数)实战:Filter DataFrame rows on a list of values
  3. 敏捷开发一千零一问系列之七:怎样对待有看法的徒弟?
  4. java中什么时候不能用泛型_java中泛型的正确使用姿势
  5. Java Web 三大框架开发资料
  6. 微信公众号Java开发-笔记02【开发接入准备、开发接入】
  7. MySQL substring()函数
  8. 山东鲁能轨道智能巡检机器人_温湿度传感器在轨道巡检机器人中的应用
  9. 导师要让你学会的“显规则”
  10. Java程序员如何提升技能
  11. moodeaudio 源码_MoodeAudio 音频播放器上手配置
  12. 【Elasticsearch】Elasticsearch:Runtime fields 入门, Elastic 的 schema on read 实现 - 7.11 发布
  13. python爬虫微博图片,pyhton爬虫爬取微博某个用户所有微博配图
  14. 统计思维:程序员数学之概率统计(第2版)PDF
  15. 各自然带代表植被_十种常见自然带所对应的植被
  16. 应用程序错误电脑黑屏_werfault应用程序错误黑屏|Win7解决werfault.exe应用程序错误方法...
  17. python 计算list中平均值_python里的list求平均值
  18. [iOS]ARC下循环引用的问题
  19. 环境变量的作用及设置方法
  20. Tailwind CSS

热门文章

  1. 【TensorFlow】实现简单的鸢尾花分类器
  2. 赫夫曼树编码的算法及应用习题--数据结构
  3. 16 操作系统第四章 文件管理 文件的基本操作 文件共享 文件保护 文件系统的层次结构
  4. 转:Some interesting facts about SharePoint 2007 Search
  5. DevExpress破解和消除弹出框问题
  6. NuGet version
  7. 编译过程中的链接地址对最终编译镜像文件的影响
  8. QMap与QHash
  9. 【 Date 对象 参考手册】
  10. Python深入05 装饰器