1、什么是增量式PID? 先看一下增量式PID的离散公式如下: :比例系数 :积分系数 :微分系数 :偏差
对于所谓的位置式,增量式的算法,这两者只是在算法的实现上的存在差异,本质的控制上对于系统控制的影响还是相同,单纯从输入和输出的角度来比较,具体如下表所示; ![]()
这里简单的说明一下; - 位置式:位置式算法较为简单,直接输入当前的偏差 ,即可得到输出;
- 增量式:增量式算法需要保存历史偏差,,即在第次控制周期时,需要使用第和第次控制所输入的偏差,最终计算得到 ,此时,这还不是我们所需要的PID输出量;所以需要进行累加;
不难发现第一次控制周期时,即时; 由以上公式我们可以推导出下式: 所以可以看出,最终PID的输出量,满足以下公式: 可见增量式算法,就是所计算出的PID增量的历史累加和: ![]() 2、举个例子2.1 位置式PID下面从一个简单的例子中去理解一下增量式PID,这里依然举一个不是很恰当的例子;如果是位置式PID算法的话: - 隆哥对一个直流电机进行调速,设定了转速为 1000;
- 这时由于反馈回来的速度和设定的速度偏差为 ;
- 经过位置式PID计算得到;
- 作为Process的输入值(可以是PWM的占空比),最终Process输出相应的PWM驱动直流电机;
- 反馈装置检测到电机转速,然后重复以上步骤;
整体框图如下所示: ![]() 2.2 增量式PID对于增量式PID来说; - 隆哥对一个直流电机进行调速,设定了转速为 1000;
- 这时由于反馈回来的速度和设定的速度偏差为 ,系统中保存上一次的偏差和上上次的偏差,这三个输入量经过增量PID计算得到;
- 系统中还保存了上一次的PID输出的,所以加上增量,就是本次控制周期的PID输出——;
- 作为Process的输入值(可以是PWM的占空比),最终Process输出相应的PWM驱动直流电机;
- 反馈装置检测到电机转速,然后重复以上步骤;
整体框图如下所示: ![]()
所以这里不难发现,所谓增量式PID,它的特点有: - 需要输入历史的偏差值;
- 计算得到的是PID输出增量,因此每一次需要累加历史增量最为当前的PID输出;
下面简单介绍一下如何实现增量式PID算法; 3、伪算法previous02_error:=0//上上次偏差previous01_error:=0//上一次偏差integral:=0//积分和pid_out:=0//pid增量累加和//循环//采样周期为dtloop://setpoint设定值//measured_value反馈值error:=setpoint−measured_value//计算得到偏差proportion:=error-previous01_error//计算得到比例输出integral:=error×dt//计算得到积分累加和derivative:=(error−2*previous01_error+previous02_error)/dt//计算得到微分pid_delta:=Kp×error+Ki×integral+Kd×derivative//计算得到PID增量pid_out:=pid_out+pid_delta//计算得到PID输出//保存当前的偏差和上一次偏差作为下一次采样所需要的历史偏差previous02_error:=previous01_errorprevious01_error:=error//保存当前偏差为下一次采样时所需要的历史偏差wait(dt)//等待下一次采用gotoloop4、C语言实现这里直接使用了TI公司的PID算法,做了积分抗饱和;具体可以参考controlSUITElibsapp_libsmotor_controlmath_blocksv4.2pid_grando.h 具体代码如下所示: pid_grando.h /*=================================================================================Filename:PID_GRANDO.H===================================================================================*/#ifndef__PID_H__#define__PID_H__typedefstruct{_iqRef;//Input:referenceset-point_iqFbk;//Input:feedback_iqOut;//Output:controlleroutput_iqc1;//Internal:derivativefiltercoefficient1_iqc2;//Internal:derivativefiltercoefficient2}PID_TERMINALS;//note:c1&c2placedheretokeepstructuresizeunder8wordstypedefstruct{_iqKr;//Parameter:referenceset-pointweighting_iqKp;//Parameter:proportionalloopgain_iqKi;//Parameter:integralgain_iqKd;//Parameter:derivativegain_iqKm;//Parameter:derivativeweighting_iqUmax;//Parameter:uppersaturationlimit_iqUmin;//Parameter:lowersaturationlimit}PID_PARAMETERS;typedefstruct{_iqup;//Data:proportionalterm_iqui;//Data:integralterm_iqud;//Data:derivativeterm_iqv1;//Data:pre-saturatedcontrolleroutput_iqi1;//Data:integratorstorage:ui(k-1)_iqd1;//Data:differentiatorstorage:ud(k-1)_iqd2;//Data:differentiatorstorage:d2(k-1)_iqw1;//Data:saturationrecord:[u(k-1)-v(k-1)]}PID_DATA;typedefstruct{PID_TERMINALSterm;PID_PARAMETERSparam;PID_DATAdata;}PID_CONTROLLER;/*-----------------------------------------------------------------------------DefaultinitalisationvaluesforthePIDobjects-----------------------------------------------------------------------------*/#definePID_TERM_DEFAULTS{0,0,0,0,0}#definePID_PARAM_DEFAULTS{ _IQ(1.0),_IQ(1.0),_IQ(0.0),_IQ(0.0),_IQ(1.0),_IQ(1.0),_IQ(-1.0)}#definePID_DATA_DEFAULTS{ _IQ(0.0),_IQ(0.0),_IQ(0.0),_IQ(0.0),_IQ(0.0),_IQ(0.0),_IQ(0.0),_IQ(1.0)}/*------------------------------------------------------------------------------PIDMacroDefinition------------------------------------------------------------------------------*/#definePID_MACRO(v) /*proportionalterm*/ v.data.up=_IQmpy(v.param.Kr,v.term.Ref)-v.term.Fbk; /*integralterm*/ v.data.ui=_IQmpy(v.param.Ki,_IQmpy(v.data.w1, (v.term.Ref-v.term.Fbk)))+v.data.i1; v.data.i1=v.data.ui; /*derivativeterm*/ v.data.d2=_IQmpy(v.param.Kd,_IQmpy(v.term.c1,(_IQmpy(v.term.Ref,v.param.Km)-v.term.Fbk)))-v.data.d2; v.data.ud=v.data.d2+v.data.d1; v.data.d1=_IQmpy(v.data.ud,v.term.c2); /*controloutput*/ v.data.v1=_IQmpy(v.param.Kp,(v.data.up+v.data.ui+v.data.ud));v.term.Out=_IQsat(v.data.v1,v.param.Umax,v.param.Umin);v.data.w1=(v.term.Out==v.data.v1)?_IQ(1.0):_IQ(0.0);#endif//__PID_H__example /*InstancethePIDmodule*/PIDpid1={PID_TERM_DEFAULTS,PID_PARAM_DEFAULTS,PID_DATA_DEFAULTS};main(){pid1.param.Kp=_IQ(0.5);pid1.param.Ki=_IQ(0.005);pid1.param.Kd=_IQ(0);pid1.param.Kr=_IQ(1.0);pid1.param.Km=_IQ(1.0);pid1.param.Umax=_IQ(1.0);pid1.param.Umin=_IQ(-1.0);}voidinterruptperiodic_interrupt_isr(){pid1.Ref=input1_1;//Pass_iqinputstopid1pid1.Fbk=input1_2;//Pass_iqinputstopid1PID_MACRO(pid1);//Callcomputemacroforpid1output1=pid1.Out;//Accesstheoutputofpid1}5、总结简单总结了位置式PID算法和增量式PID算法的差异,参考了TI公司的增量式PID算法实现,对于不同的控制对象可以根据系统要求选择合适的PID算法。
|