PID控制算法初探

简介

当被控对象的结构和参数不能完全掌握,或得不到精确的数学模型时,控制理论的其它技术难以采用时,系统控制器的结构和参数必须依靠经验和现场调试来确定,这时应用PID控制技术最为方便。即当我们不完全了解一个系统和被控对象,或不能通过有效的测量手段来获得系统参数时,最适合用PID控制技术。PID控制,实际中也有PI和PD控制。PID控制器就是根据系统的误差,利用比例、积分、微分计算出控制量进行控制的。
个人理解:对应于一个黑盒系统,想要得到确定的输出,就需要对应的输入。而输入往往是不确定的,这时就需要PID来进行反馈控制。给定一个输入,可以得到输出,通过误差比例、积分、微分三项的反馈可以得到输入的增量值,一直迭代,最终达到理想输出。
PID控制算法初探_第1张图片
对于离散系统,积分转换为求和,微分转换为差分
在这里插入图片描述
比例控制(P):减少误差的核心,使输入向减小误差的方向改变
积分控制(I):由于存在阻尼,若仅用比例控制会导致稳态误差,所以引入积分项,增大反馈得到的增加量
微分控制(D):为了减缓变化趋势

软件模拟PID算法的模型

半生不熟的python写的

#定义个一个PID的类,用于保存属性,包括误差量
class PID(object):
    def __init__(self,kp,ki,kd):
        self.ek=0
        self.ek1=0
        self.ek2=0
        self.kp=kp
        self.ki=ki
        self.kd=kd
        self.esum=0

#定义计算PID的函数,返回量为所需要增加的值
def PID_Cal(setvalue,actualvalue,PID_Class):
    PID_Class.ek=setvalue-actualvalue
    PID_Class.esum+=PID_Class.ek
    PID_value=PID_Class.kp*PID_Class.ek+PID_Class.ki*PID_Class.esum+PID_Class.kd*(PID_Class.ek-PID_Class.ek1)
    
    PID_Class.ek2=PID_Class.ek1
    PID_Class.ek1=PID_Class.ek
    return PID_value


set1=10     #目标值
act1=0      #实际值
y=[0]
PID_example=PID(0.2,0.1,0)      #各个比例系数,初始化时就决定
for i in range(100):
    temp=PID_Cal(set1,act1,PID_example)
    act1+=temp
    act1-=2                     #引入阻尼
    y.append(act1)

plt.plot(y)                     #作图

结果:
PID控制算法初探_第2张图片
板球系统中PID的应用

与上面软件模拟存在差异,PID计算得到的直接直接作为输入量,而且微分项用的是4帧的差(减小摄像头抖动的误差)。
下面放上代码

//PID结构体,用于存放误差以及三个系数
typedef struct
{
     
	long ek;		//误差
	long ek1;		//上一次的误差
	long ek2;		//上两次的误差
	long ek3;		//上三次的误差
	long ek4;		//上四次的误差
	long esum;	//误差的积分和
	float kp;	//比例系数
	float ki;	//积分系数
	float kd;	//微分系数
	float total_para;	//总系数
} PID_StructureDef;

//PID三个参数设置
void PID_Set_para(float kp,float ki,float kd,float total_para)
{
     
	PID_Structure.kp=kp;
	PID_Structure.ki=ki;
	PID_Structure.kd=kd;
	PID_Structure.total_para=total_para;
}

//PID算法实现 传入误差,返回输入增量 单维
long PID_Calculate(long error,long max_scope,long min_scope)
{
     
	long output;
	PID_Structure.ek=error;
	PID_Structure.esum+=error+PID_Structure.ek1+PID_Structure.ek2+PID_Structure.ek3+PID_Structure.ek4;
	output=PID_Structure.ek*PID_Structure.kp+PID_Structure.esum*PID_Structure.ki+((PID_Structure.ek-PID_Structure.ek4)*PID_Structure.kd/5);
	PID_Structure.ek4=PID_Structure.ek3;
	PID_Structure.ek3=PID_Structure.ek2;
	PID_Structure.ek2=PID_Structure.ek1;
	PID_Structure.ek1=error;
	output*=PID_Structure.total_para;
	
	if(output>max_scope)
		output=max_scope;
	if(output<min_scope)
		output=min_scope;
	
	return output;
}

void main()
{
     
	while(1)
	{
     
		if((USART2_RX_STA&0x8000))
		{
     
			String_To_Int(USART2_RX_BUF);
			
//			USART_SendData(USART1,Centre_x);//发送x坐标
//			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
//			USART_SendData(USART1,Centre_y);//发送y坐标
//			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
			
			
			USART2_RX_STA=0;
			
			if((Centre_x!=0)&&(Centre_y!=0))
			{
     
				TIM_SetCompare1(TIM3,Balance_x+Input_x);
				TIM_SetCompare2(TIM3,Balance_y+Input_y);
				
//				printf("the x pwn is %ld ",Input_x);
//				printf("the y pwn is %ld \r\n",Input_y);
				
				Input_x=PID_Calculate(Goal_x-Centre_x,400,-400);
				
				Input_y=PID_Calculate(Goal_y-Centre_y,400,-400);	
			}
		}
	}
}

PID调节总结

一般不需要调节ki,kd需要调得大些,为的是防止小球的运动过快,kp为的是加快小球到达目标位置的速度

你可能感兴趣的:(#,控制算法)