设计pid控制器并设定参数,pid控制器参数设置
我们发表了一系列与PID控制器相关的文章,包括经典PID控制器和参数自适应PID控制器。虽然该系列PID控制器实现了主要功能,在实际使用中取得了良好的效果,但仍有许多细节可以改进,以提高性能和灵活性。在本文中,我们将讨论改进PID控制器参数设置的问题。
1.问题就提出来了。在上一篇文章中,我们推导了PID控制器的公式,并将其离散化以适合程序实现。具体的离散化公式如下:
编写程序时,我们将比例项的系数设为Kp,积分项的系数设为Ki,微分项的系数设为Kd,其中:
其中t是采样周期,Ti是积分时间,Td是微分时间。所以在设置参数时,我们需要先去掉比例系数Kp,然后根据采样周期和积分微分时间计算Ki和Kd。虽然公式变得简单,但是和我们传统的参数设置相比就没有那么直观了,所以有些用户希望用传统比例中的PB,积分时间Ti,微分时间Td来配置相应的参数。本文将对这一问题进行分析和解决。
2.针对上述问题的分析与设计,我们需要弄清楚Kp,Ki,Kd与PB,Ti,Td之间的关系。其实他们之间的关系并不复杂。首先,比例系数Kp是比例带的倒数,知道其中一个就可以得到另一个。ti和Ki的关系以及Td和Kd的关系前面已经给出了。
接下来我们要做的,其实就是让我们的PID控制器在不同的应用需求下呈现不同的参数设置,然后我们就可以设置不同的参数形式。
3.软件实现我们已经分析了需要实现什么。接下来,我们来考虑如何实现。在这方面,我们考虑我们的PID控制器的设计形式,它需要在三个方面进行修改。首先需要修改的地方是PID控制器对象的定义。我们定义一个宏来实现条件编译,以实现不同要求下的不同参数定义,所以我们定义PID控制器的对象类型如下:
/*定义PID对象类型*/
typedef结构经典
{
float * pPV//测量值指针
float * pSV//设置值指针
float * pMV//输出值指针
uint16 _ t * pMA//手动自动操作指针
\#if PID_PARAMETER_STYLE (0)
float * pKp//比例系数指针
float * pKi//整型系数指针
float * pKd//微分系数指针
\#else
float * pPb//比例带
float * pTi//积分时间,单位为秒
float * pTd//差分时间,以秒为单位
浮动ts;//采样周期,以秒为单位
\#endif
浮动设定值;//设置值
float lasterror//前一节拍偏差
浮点预误差;//前两拍的偏差
浮动死区;//死区
浮点结果;//PID控制器//的计算结果
浮点输出;//输出值为0-100%
浮动最大值;//输出值的上限
浮动最小值;//输出值的下限
浮点误差absmax;//最大偏差绝对值
float errorabsmin//绝对偏差的最小值
浮动;//不完全微分系数
浮点deltadiff//差分增量
浮点integralValue//累计积分金额
浮动伽马;//差分第一滤波器系数
float lastPv//最后一拍的过程测量值
float lastDeltaPv//前一个节拍的过程测量值的增量
ClassicPIDDRType direct//正面和负面影响
经典sm;//将值设置为平滑
ClassicPIDCSType cas//级联设置
} CLASSICPID我们定义了对象类型,可以得到我们需要的对象变量,但是这个对象变量需要初始化后才能使用。所以第二个需要修改的是PID控制器对象的初始化函数。我们使用条件编译,我们在不同的应用需求下初始化不同的对象参数。具体实现如下:
/* PID初始化应该在修改vPID对象的值之前完成*/
/* CLASSICPID vPID,一个常用的PID对象变量,实现数据交换和存储*/
/*浮点vMax、浮点vMin、过程变量的最大值和最小值(范围*/
void PID para initial ization(经典PID * vPID,//PID控制器对象
float *pPV,//测量值指针
float *pSV,//设定值指针
float *pMV,//输出值指针
\#if PID_PARAMETER_STYLE (0)
float *pKp,//比例系数指针
float *pKi,//积分系数指针
float *pKd,//微分系数指针
\#else
float * pPb//比例带
float * pTi//积分时间
float * pTd//微分时间
浮点ts,//采样周期,单位为秒
\#endif
uint16_t *pMA,//手自动操作指针
浮点vMax,//控制变量量程
浮点vMin,//控制变量的零点
ClassicPIDDRType direct,//正反作用
ClassicPIDSMType sm,//设定值平滑
ClassicPIDCSType cas //串级设定
)
{
if((vPID==NULL) (pPV==NULL) (pSV==NULL) (pMV==NULL) (pMA==NULL))
{
返回;
}
vPID-pPV=pPV;
vPID-pSV=pSV;
vPID-pMV=pMV;
vPID-pMA=pMA;
\#if PID_PARAMETER_STYLE (0)
if((pKp==NULL) (pKi==NULL) (pKd==NULL))
{
返回;
}
vPID-pKp=pKp;
vPID-pKi=pKi;
vPID-pKd=pKd;
如果(*vPID- pKp=0.00001)
{
* vPID-pKp=1.0;//比例系数
* vPID-pKi=0.01;//积分系数
* vPID-pKd=0.01;//微分系数
}
\#else
if((pPb==NULL) (pTi==NULL) (pTd==NULL))
{
返回;
}
vPID-pPb=pPb;
vPID-pTi=pTi;
vPID-pTd=pTd;
vPID-ts=ts;
如果(*vPID- pPb=0.00001)
{
* vPID-pPb=1.0;//比例带
* vPID-pTi=1.0;//积分时间,单位为秒
* vPID-pTd=0.0001;//微分时间,单位为秒
}
\#endif
vPID-maximum=vMax;//控制变量的量程
vPID-minimum=vMin;//控制变量的零点
* vPID-pSV=* pPV;//设定值
vPID-setpoint=* pPV;//设定值
* vPID-pMA=1;//初始化为自动模式
vPID-direct=direct;//设定PID对象的正反作用
vPID-cas=cas;//设定是否启用串级
vPID-sm=sm;//设定是否启用设定值平滑
if(vPID- cas==CASCADE)
{
vPID-sm=SMOOTH _ DISABLE;
}
vPID-lasterror=0.0;//前一拍偏差
vPID-preerror=0.0;//前两拍偏差
vPID-result=vMin;//PID控制器结果
vPID-output=0.0;//输出值,百分比
* vPID-pMV=vPID-output;//输出值,百分比
vPID-errorabsmax=(vMax-vMin)* 0.9;
vPID-errorabsmin=(vMax-vMin)* 0.1;
vPID-死区=(vMax-vMin)* 0.001;//死区
vPID-alpha=0.2;//不完全微分系数
vPID-delta diff=0.0;//微分增量
vPID-积分值=0.0;
}第三个需要修改的是PID控制器对象的实现。在前面我们已经描述铅、钛、总镉与Kp、Ki、Kd之间的数学关系。为了方便处理,我们通过条件编译在不同应用需求下将参数均转化为统一的Kp、Ki、Kd来进行计算。具体的实现方式如下:
/* 通用PID控制器,采用增量型算法,具有变积分,梯形积分和抗积分饱和功能*/
/* 微分项采用不完全微分,一阶滤波,阿尔法值越大滤波作用越强*/
/* CLASSICPID vPID,PID对象变量,实现数据交换与保存*/
/*浮动pv,过程测量值,对象响应的测量数据,用于控制反馈*/
无效PID调节器(经典PID *vPID)
{
浮动此错误
浮点结果;
浮动系数;
浮动增量;
浮点pError、dError、iError
浮动kp,ki,KD;
\#if PID_PARAMETER_STYLE (0)
kp=*vPID-
ki=*vPID-
kd=*vPID-
\#else
if((*vPID- pTi) vPID- ts)
{
*vPID- pTi=vPID-
}
KP=1/(* vPID-pPb);
ki=KP *(vPID-ts/(* vPID-pTi));
KD=KP *(vPID-pTd)/vPID-
\#endif
if(*vPID- pMA 1) //手动模式
{
识输出=*vPID-
//设置无扰动切换
vPID-结果=(vPID-最大值-vPID-最小值)*vPID-输出/100.0 vPID-最小值;
*vPID- pSV=*vPID-
vPID-设定点=*vPID-
}
else //自动模式
{
if(vPID- sm==SMOOTH_ENABLE) //设定值平滑变化
{
平滑设定点(vPID);
}
其他
{
if(vPID- cas==CASCADE) //串级处理
{
vPID-设定点=(vPID-最大值-vPID-最小值)*(*vPID- pSV)/100.0 vPID-最小值;
}
其他
{
vPID-设定点=*vPID-
}
}
这个误差=vPID-设定点-(* vPID-pPV);//得到偏差值
结果=vPID-结果;
if (fabs(thisError) vPID-死区)
{
pError=this error-vPID-lasterror;
I error=(thisError vPID-lasterror)/2.0;
dError=this error-2 *(vPID-lasterror)vPID-preerror;
//变积分系数获取
factor=VariableIntegralCoefficient(this error,vPID- errorabsmax,vPID-error absmin);
//计算不完全微分的微分项增量
vPID-delta diff=KD *(1-vPID-alpha)* dError vPID-alpha * vPID-delta diff;
increment=KP * pError ki * factor * I error vPID-delta diff;//增量计算
}
其他
{
if((fabs(vPID-设定点-vPID-最小值)vPID-死区)(fabs((*vPID- pPV)-vPID-最小值)vPID-死区))
{
结果=vPID-最小值;
}
增量=0.0;
}
//正反动作设置
if(vPID- direct==DIRECT)
{
结果=结果增量;
}
其他
{
结果=结果-增量;
}
/*对于输出限制,避免过冲和积分饱和*/
if(结果=vPID-最大值)
{
result=vPID-maximum;
}
if(结果=vPID-最小值)
{
结果=vPID-最小值;
}
vPID-preerror=vPID-lasterror;//为下一次操作存储偏差。
vPID-lasterror=this error;
vPID-result=结果;
vPID-output=(vPID-result-vPID-minimum)/(vPID-maximum-vPID-minimum)* 100.0;
* vPID-pMV=vPID-output;
}
}4.总结在本文中,我们只是修改了PID控制器的参数定义,以满足不同用户的需求,但控制器本身的功能并没有改变。这样原应用不会受到影响,新应用也可以根据需要定义参数,使用Kp,Ki,Kd或者PB,Ti,Td根据应用设计的需要进行选择。
这里需要说的是,无论我们如何定义参数,采样周期的选择都需要慎重考虑。即使采用相同的参数设置,当采样周期不同时,效果也可能相差很大,所以在设置参数前要根据系统的特点采用合适的采样周期。
欢迎关注:
想更方便及时的阅读相关文章,请关注我的微信微信官方账号【木南创智】
转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。