简介
当被控对象的结构和参数不能完全掌握,或得不到精确的数学模型时,控制理论的其它技术难以采用时,系统控制器的结构和参数必须依靠经验和现场调试来确定,这时应用PID控制技术最为方便。即当我们不完全了解一个系统和被控对象,或不能通过有效的测量手段来获得系统参数时,最适合用PID控制技术。PID控制,实际中也有PI和PD控制。PID控制器就是根据系统的误差,利用比例、积分、微分计算出控制量进行控制的。
个人理解:对应于一个黑盒系统,想要得到确定的输出,就需要对应的输入。而输入往往是不确定的,这时就需要PID来进行反馈控制。给定一个输入,可以得到输出,通过误差比例、积分、微分三项的反馈可以得到输入的增量值,一直迭代,最终达到理想输出。
对于离散系统,积分转换为求和,微分转换为差分
比例控制(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的应用
与上面软件模拟存在差异,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为的是加快小球到达目标位置的速度