注:本篇笔记承接备赛电赛学习软件篇(二):PID(1),且本笔记主要是代码部分
一、PID的基本实现
1、位置型PID
结构体部分
/*定义结构体和公用体*/
typedef struct
{
float setpoint; //设定值
float proportiongain; //比例系数
float integralgain; //积分系数
float derivativegain; //微分系数
float lasterror; //前一拍偏差
float result; //输出值
float integral;//积分值
}PID;
接下来实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)
{
float thisError;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;
vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;
}
2、增量型PID
结构体部分
/*定义结构体和公用体*/
typedef struct
{
float setpoint; //设定值
float proportiongain; //比例系数
float integralgain; //积分系数
float derivativegain; //微分系数
float lasterror; //前一拍偏差
float preerror; //前两拍偏差
float deadband; //死区
float result; //输出值
}PID;
接下来实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)
{
float thisError;
float increment;
float pError,dError,iError;
thisError=vPID->setpoint-processValue; //得到偏差值
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError; //增量计算
vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
vPID->lasterror=thisError;
vPID->result+=increment;
}
二、积分分离
1、位置型PID
结构体部分:
/*定义结构体和公用体*/
typedef struct
{
floatsetpoint; //设定值
floatproportiongain; //比例系数
floatintegralgain; //积分系数
floatderivativegain; //微分系数
floatlasterror; //前一拍偏差
floatresult; //输出值
floatintegral;//积分值
float epsilon; //偏差检测阈值
}PID;
接下来实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)
{
floatthisError;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;
uint16_tbeta= BetaGeneration(error,vPID->epsilon);
if(beta==0)
{
vPID->result=vPID->proportiongain*thisError+vPID->derivativegain*(thisError-vPID->lasterror);
}
else
{
vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror);
}
vPID->lasterror=thisError;
}
static uint16_t BetaGeneration(float error,float epsilon)
{
uint16_t beta=0;
if(abs(error)<= epsilon)
{
beta=1;
}
return beta;
}
2、增量式PID
结构体
/*定义结构体和公用体*/
typedef struct
{
floatsetpoint; //设定值
floatproportiongain; //比例系数
floatintegralgain; //积分系数
floatderivativegain; //微分系数
floatlasterror; //前一拍偏差
floatpreerror; //前两拍偏差
floatdeadband; //死区
floatresult; //输出值
float epsilon; //偏差检测阈值
}PID;
接下来实现PID控制器:
void PIDRegulation(PID *vPID, float processValue)
{
floatthisError;
floatincrement;
floatpError,dError,iError;
thisError=vPID->setpoint-processValue; //得到偏差值
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
uint16_tbeta= BetaGeneration(error,vPID->epsilon);
if(beta==0)
{
increment=vPID->proportiongain*pError+vPID->derivativegain*dError; //增量计算
}
else
{
increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError; //增量计算
}
vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
vPID->lasterror=thisError;
vPID->result+=increment;
}
static uint16_t BetaGeneration(float error,float epsilon)
{
uint16_t beta=0;
if(abs(error)<= epsilon)
{
beta=1;
}
return beta;
}
三、抗积分饱和
1、思想
所谓积分饱和就是指系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而扩大,从而导致控制器输出不断增大超出正常范围进入饱和区。当系统出现反响的偏差时,需要首先从饱和区退出,而不能对反向的偏差进行快速的响应。
为了解决积分饱和的问题,人们引入了抗积分饱和的PID算法。所谓抗积分饱和算法,其思路是在计算U(k)的时候,先判断上一时刻的控制量U(k-1)是否已经超出了限制范围。若U(k-1)>Umax,则只累加负偏差;若U(k-1)<Umin,则只累加正偏差。从而避免控制量长时间停留在饱和区。
2、流程图
3、代码部分
3.1位置型
结构体
/*定义结构体和公用体*/
typedef struct
{
floatsetpoint; //设定值
floatproportiongain; //比例系数
floatintegralgain; //积分系数
floatderivativegain; //微分系数
floatlasterror; //前一拍偏差
floatresult; //输出值
floatintegral;//积分值
floatmaximum;//最大值
floatminimum;//最小值
}PID;
PID控制器
void PIDRegulation(PID *vPID, float processValue)
{
floatthisError;
thisError=vPID->setpoint-processValue;
if(vPID->result>vPID->maximum)
{
if(thisError<=0)
{
vPID->integral+=thisError;
}
}
elseif(vPID->result<vPID->minimum)
{
if(thisError>=0)
{
vPID->integral+=thisError;
}
}
else
{
vPID->integral+=thisError;
}
vPID->result=vPID->proportiongain*thisError+vPID->integralgain*vPID->integral+vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;
}
3.2增量式
结构体
/*定义结构体和公用体*/
typedef struct
{
floatsetpoint; //设定值
floatproportiongain; //比例系数
floatintegralgain; //积分系数
floatderivativegain; //微分系数
floatlasterror; //前一拍偏差
floatpreerror; //前两拍偏差
floatdeadband; //死区
floatresult; //输出值
floatmaximum;//最大值
floatminimum;//最小值
}PID;
PID控制器
void PIDRegulation(PID *vPID, float processValue)
{
floatthisError;
floatincrement;
floatpError,dError,iError;
thisError=vPID->setpoint-processValue; //得到偏差值
pError=thisError-vPID->lasterror;
iError=0;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
if(vPID->result>vPID->maximum)
{
if(thisError<=0)
{
iError=thisError;
}
}
elseif(vPID->result<vPID->minimum)
{
if(thisError>=0)
{
iError=thisError;
}
}
else
{
iError=thisError;
}
increment=vPID->proportiongain*pError+vPID->integralgain*iError+vPID->derivativegain*dError; //增量计算
vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
vPID->lasterror=thisError;
vPID->result+=increment;
}