对传统PID控制算的优化改善

针对传统PID控制算法的优化

一,原理图

根据原理图,MCU通过输出0~100%占空比的PWM来控制温度;通过ADC0808来采集温度

二,PID控制代码

void PIDCalu(PID_para *pid )

{

pid->Yn = 0.3906*GetADC();

pid->En = pid->Rn - pid->Yn;

pid->SumOfEn += Pid.En;

pid->Un =     pid->Kp*pid->En +

pid->Ki*Pid.SumOfEn +

pid->Kd*(pid->En - pid->En_1);

pid->En_1 = pid->En;

}

三,分析

PID控制代码并不是难点。难点是Kp,Ki,Kd三个参数的最优配置。这三个参数可能随便配一个差不多的数,温度也能最终稳定下来;但需要的时间、超调量、精准度这些指标,却并不一定是所有情况中最好的。

当Kp,Ki,Kd为5,0.005,20时,期望温度50℃,控制效果为

通过此图可以得知:

a,系统的输出控制,前期主要由比例项决定;后期主要由微分项和积分项决定;

b,比例项的大小决定了前期升温的速度;微分项和积分项决定了后期稳定的精度。

根据这两个结论,我们设计一个公式,让Kp,Ki,Kd参数在控制过程中实时改变。当距离期望温度很大时,便采用较大的Kp,较小的积分项和Kd;而距离期望温度较小时,用较小的Kp,较大的积分项和Kd。

注意,改积分项并不是改改Ki就行了。积分是一种累加运算,你即便在后期改了Ki,那前期的累计值依然在积分项中,影响着后期的控制。所以实际上改积分项应该改不同阶段的积分权值,即:

积分项 =

注意Ki和k(t)并不是一回事。Ki是一个常量,影响了积分项在PID中的整体权重。而k(t)是一个函数,它实时性的为每一个样本e(t0),e(t1),e(t2)...分配了不同的权重。

我们下面采用单一变量法进行实验。

1,验证变参数Kp的效果。

A组:Ki,Kd,Kp为5,0.005,20不变

B组:Ki,Kd不变;令Kp = En/5 + 5;当En从50到0时,Kp相应的从15变化到5。

根据以上实验得知,在其他性能相似的情况下,B组达到稳定状态的速度要比A组好。

2,验证变参数Kd的效果

A组:Kp,Ki,kd为5,0.003,50,期望温度为50度

B组:Kp,Ki不变,Kd = 10/En,当En从10到0.2时,Kd也从1到50;

显然,B优于A。

3,验证变参数Ki的效果

A组:Kp,Ki,kd为5,0.05,50,期望温度为50度

B组:在Kp,Ki,Kd不变的情况下;引入一个“积分强弱”控制因子Kit = 1-En/Rn;原来的积分项公式修改为:

显然,即便在系统肯定会产生超调的情况下,B组的超调也比A组小。

四,改进之后的PID控制代码,加了一个KpKiKdCalu函数,用于实时调整Kp,Ki,Kd.

void KpKiKdCalu(PID_para *pid)

{

//变参数Kp

pid->Kp =  Abs(pid->En)/5 + 5;

//变参数Kd

if(Abs(pid->En) < 0.2)

{

pid->Kd = 50;

}

else

{

pid->Kd = 10/ Abs(pid->En)  ;

}

//变参数Kit

if(pid->Rn!=0)

{

pid->Kit =  1 -  Abs(pid->En /  pid->Rn)  ;

}

}

void PIDCalu(PID_para *pid )

{

pid->Yn = 0.3906*GetADC();

pid->En = pid->Rn - pid->Yn;

pid->SumOfEn +=  pid->Kit*pid->En;

pid->Un =     pid->Kp*pid->En +

pid->Ki*Pid.SumOfEn +

pid->Kd*(pid->En - pid->En_1);

pid->En_1 = pid->En;

}

Kp,Ki,Kd初始值:5,0.01,50

期望温度50℃,控制效果:

(0)

相关推荐