改進式PID控制
如果是在低速模式下,标準的PID基本可以滿足控制要求,但随着速度的提升,PID算法要進一步修改和完善才能達到控制要求。是以需要對PID算式進行适當的改進,進而提高控制品質。
積分項的改進
積分項的作用:消除穩态誤差,提高控制系統的精度。
積分項存在的問題:偏差較大時,積分的滞後作用會影響系統的響應速度,引起較大的超調及加長過渡過程,尤其對時間常數較大,有時間滞後的被控對象,更加劇了振蕩過程。
1. 積分分離法:
改進方案:當偏差大于某個規定的門限值時,取消積分作用,進而使積分不至于過大。隻有當e(k)較小時,才引入積分作用,以消除靜差。這樣控制量不易進入飽和區;即使進入了飽和區,也能較快的退出,是以能使系統的輸出特性得到改善。
2. 抗積分飽和法:
改進方案:當控制量進入飽和區後,隻執行削弱積分項的累加,而不進行增大積分項的累加。即計算u(k)時,先判斷u(k-1)是否超過限制範圍,若已超過umax,則隻累計負偏差;若小于umin,則隻累計正偏差,這種方法也可以避免控制量長期停留在飽和區。
算法案例如下:
/*
積分分離的pid控制算法c語言實作
系統所用時間是原來時間的一半
系統的快速性得到了提高
*/
#include<stdio.h>
#include<stdlib.h>
struct _pid{
float SetSpeed; //定義設定值 //24V 1100-1900
float ActualSpeed; //定義實際值
float err; //定義偏內插補點
float err_last; //定義上一個偏內插補點
float Kp,Ki,Kd; //定義比例、積分、微分系數
float voltage; //定義電壓值(控制執行器的變量)
float integral; //定義積分值
}pid;
//項目中擷取到的參數
void PID_init(){
printf("PID_init begin \n");
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2; //自己設定
pid.Ki=0.04; //自己設定
pid.Kd=0.2; //自己設定
printf("PID_init end \n");
}
float PID_realize(float speed){
pid.SetSpeed=speed; //設定值
pid.err=pid.SetSpeed-pid.ActualSpeed; //設定值-實際值
int index;
if(abs(pid.err)>200)
{
index=0;
}else{
index=1;
pid.integral+=pid.err;
}
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.
err-pid.err_last); //算法具體實作過程
pid.err_last=pid.err; //上一個偏內插補點
pid.ActualSpeed=pid.voltage*1.0; //算出實際值
return pid.ActualSpeed; //傳回
}
int main(){
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}
/*
抗擊分飽和的pid控制算法
*/
#include<stdio.h>
#include<stdlib.h>
struct _pid{
float SetSpeed; //定義設定值
float ActualSpeed; //定義實際值
float err; //定義偏內插補點
float err_last; //定義上一個偏內插補點
float Kp,Ki,Kd; //定義比例、積分、微分系數
float voltage; //定義電壓值(控制執行器的變量)
float integral; //定義積分值
float umax;
float umin;
}pid;
void PID_init(){
printf("PID_init begin \n");
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.1; //注意,和上幾次相比,這裡加大了積分環節的值
pid.Kd=0.2;
pid.umax=400;
pid.umin=-200;
printf("PID_init end \n");
}
float PID_realize(float speed){
int index;
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
if(pid.ActualSpeed>pid.umax) //灰色底色表示抗積分飽和的實作
{
if(abs(pid.err)>200) //藍色标注為積分分離過程
{
index=0;
}else{
index=1;
if(pid.err<0)
{
pid.integral+=pid.err;
}
}
}else if(pid.ActualSpeed<pid.umin){
if(abs(pid.err)>200) //積分分離過程
{
index=0;
}else{
index=1;
if(pid.err>0)
{
pid.integral+=pid.err;
}
}
}else{
if(abs(pid.err)>200) //積分分離過程
{
index=0;
}else{
index=1;
pid.integral+=pid.err;
}
}
// pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral/2+pid.Kd*(pid.err-pid.err_last);//梯形積分
pid.err_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;
return pid.ActualSpeed;
}
int main(){
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
return 0;
}