天天看點

改進式PID控制以及C語言實作過程

改進式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;
}
           

繼續閱讀