1 PID时间系数对PID本身的影响
//积分限幅
//输出限幅
// 滤波系数a(0-1)
//PID结构体
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int Error2; // Error[n-2]
volatile int iError; // Error[n]
volatile int Error_sum;
} PID
/****************************************************************************************/ // 位置式PID
// //pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
/****************************************************************************************/
float PID_Postion (int iError,PID* sptr)
{
float iIncpid=0;
sptr->iError=iError; // 计算当前误差
//sptr->iError=filter(sptr->iError,sptr->Error1); 一阶滤波器
sptr->Error_sum+=sptr->iError;//积分项
///当输出限幅的时候,积分累加部分也应同时进行限幅,以防输出不变而积分项继续累加,也即所谓的积分饱和过深。
//积分量限幅
if(sptr->Error_sum >INERGRAL_MAX)
{
sptr->Error_sum = PID_InitStruct->INERGRAL_MAX ;
}
if(sptr->Error_sum < INERGRAL_MIN)
{
sptr->Error_sum = PID_InitStruct->INERGRAL_MIN ;
}
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum // I
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
sptr->Error1=sptr->iError; // 存储误差,用于下次计算
iIncpid=PID_OutputLimit(sptr,iIncpid);//PID输出限幅
return(iIncpid); // 返回计算值
}
/****************************************************************************************/ //增量式PID
// pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)] //
/****************************************************************************************/
float PID_increase(int iError,PID* sptr)
{
float iIncpid=0;
sptr->iError=iError;//直接检测当前偏差
iIncpid=sptr->Proportion * (sptr->iError-sptr->Error1) // P
+sptr->Integral * sptr->iError // I
+sptr->Derivative * (sptr->iError-2*sptr->Error1+sptr->Error2); // D
sptr->Error2=sptr->Error1; // 存储误差,用于下次计算
sptr->Error1=sptr->iError;
iIncpid=PID_OutputLimit(sptr,iIncpid);//输出限幅处理
return(iIncpid); // 返回增量值
}
//PID初始化
void PID_Init(PID *sptr)
{
sptr->Derivative=0;//Kd
sptr->Proportion=0;//Kp
sptr->Integral=0;//Ki
sptr->Error2=0;//第二次误差
sptr->Error1=0;
sptr->iError=0;
sptr->Error_sum=0;//第一次误差
}
//PID输出限制,根据PWM的输出值进行增量式PID输出限制
float PID_OutputLimit(PID *this, double output)
{
if ((int)output < OUT_MIN)
{
output = OUT_MIN;
}
else if ((int)output > OUT_MAX)
{
output = OUT_MAX;
}
return output;
}
//一阶低通滤波器
//减少毛刺,
//滤波系数。取值范围为0~1, 值越小越稳定,越大越灵敏。使用使需要根据实际情况调整滤波系数
//输入:新的采样值
//输出:滤波后的值
float filter(float value,float new_value)
{
return (1-PARAMETER)*value +PARAMETER*new_value;
}
sptr->Error_sum+=sptr->iError;//积分累加
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum // I
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
#
int index=0;//积分分离标志
//积分分离处理
if(abs(sptr->iError)> 40) sptr->index=0;
else
{
sptr->index=1;
sptr->Error_sum+=sptr->iError;//积分累加
}
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * (sptr->Error_sum * index) // I
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
int index=0;//积分分离标志
//变积分处理
if(abs(sptr->iError)> I_MAX) index=0;
else if(abs(sptr->iError)< I_MIN) index=1;
else index=(I_MAX - abs(sptr->iError) / (I_MAX - I_MIN);
if(index!=0) sptr->Error_sum+=sptr->iError;//积分累加
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * (sptr->Error_sum * index) // I
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
//变速积分也可以这样处理:更加灵活
if(fabs(sptr->iError)> I_MAX) index=0;
else if(fabs(sptr->iError)< I_MIN) index=1;
else if(fabs(sptr->iError>10&&abs(sptr->iError)<20)) index=0.4;
else if(fabs(sptr->iError>30&&abs(sptr->iError)<50)) index=0.8;
else index=(I_MAX - abs(sptr->iError) / (I_MAX - I_MIN);
//PID结构体
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int Error2; // Error[n-2]
volatile int iError; // Error[n]
volatile int Error_sum;
volatile float thisdev;//前一拍时的微分项值
volatile float lastdev ;//前一拍时的微分项值
float dev_per;//微分系数
} PID;
//位置式PID不完全微分
float PID_Postion (int iError,PID* sptr)
{
float iIncpid=0;
sptr->iError=iError; // 计算当前误差
sptr->Error_sum+=sptr->iError;//积分项
//不完全微分
sptr->thisdev=sptr->Derivative*(1-sptr->dev_per)*(sptr->iError-sptr->Error1)+sptr->dev_per*sptr->lastdev;
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum // I
+sptr->thisdev; // D
//更新值
sptr->Error1=sptr->iError;
sptr->lastdev=sptr->thisdev;//更新下次微分值
return(iIncpid); // 返回计算值
}
//增量式PID不完全微分
float PID_increase(int iError,PID* sptr)
{
float iIncpid=0;
sptr->iError=iError;//直接检测当前偏差
sptr->thisdev=sptr->Derivative*(1-sptr->dev_per)*(sptr->iError-2*sptr->Error1+sptr->Error2)+sptr->dev_per*sptr->lastdev;
iIncpid=sptr->Proportion * (sptr->iError-sptr->Error1) // P
+sptr->Integral * sptr->iError // I
+sptr->thisdev; // D
//更新
sptr->Error2=sptr->Error1;
sptr->Error1=sptr->iError;
sptr->lastdev=sptr->thisdev;//更新下次微分值
return(iIncpid); // 返回增量值
}
增量式:
//PID结构体
//位置式
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int Error2; // Error[n-2]
volatile int iError; // Error[n]
volatile int Error_sum;
volatile float lastPv; //前一拍的测量值
volatile float gama; //微分先行滤波系数
volatile float derivative;//微分项
} PID;
//位置式微分先行PID
float PID_Postion (float set_point,float processValue,PID* sptr)
{
float iIncpid=0;
float temp=0,c1,c2,c3;
sptr->iError=set_point-processValue; // 计算当前误差
sptr->Error_sum+=sptr->iError;//积分项
//微分先行
temp=sptr-> gama * sptr-> Derivative+ sptr-> Proportion;//γKp+Kd
c3=sptr-> Derivative/temp;//Kd/γKp+Kd
c2=(sptr-> Derivative+ sptr-> Proportion)/temp;//Kd+Kp/γKp+Kd
c1=c3*sptr-> gama;//γ(Kp/γKp+Kd)
sptr-> derivative=c1* sptr-> derivative+c2*processValue-c3* sptr-> lastPv;
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum // I
+sptr->derivative; // D
//更新值
sptr->Error1=sptr->iError;
sptr->lastPv=sptr->processValue;//更新下次微分值
return(iIncpid); // 返回计算值
}
//***********************************************************//
// 增量式微分先行PID
//***********************************************************//
//增量式PID结构体
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int iError; // Error[n]
volatile float lastout; //上一次的测量量
volatile float lastout_proinc; //前一拍的过程测量增量
volatile float gama; //微分先行滤波系数
volatile float out_proinc; //过程测量增量
volatile float derivative_inc; //微分项
} PID;
//增量式PID不完全微分PID_increase
float PID_increase(float set_point,float processValue,PID* sptr)
{
float iIncpid=0;
float temp=0,c1,c2,c3;
sptr->iError=set_point-processValue; // 计算当前误差
//微分先行
out_proinc=processValue-lastout;//这次输出增量
temp=sptr-> gama * sptr-> Derivative+ sptr-> Proportion;//γKp+Kd
c3=sptr-> Derivative/temp;//Kd/γKp+Kd
c2=(sptr-> Derivative+ sptr-> Proportion)/temp;//Kd+Kp/γKp+Kd
c1=c3*sptr-> gama;//γ(Kp/γKp+Kd)
sptr-> derivative_inc=c1* sptr-> derivative_inc+c2*out_proinc-c3* sptr-> lastout_proinc;
iIncpid=sptr->Proportion * (sptr->iError-sptr-> Error1)// P
+sptr->Integral * sptr->iError// I
+sptr->derivative_inc; // D
//更新值
sptr->Error1=sptr->iError;
sptr->lastout_proinc=sptr->out_proinc;//过程增量更新
sptr->lastout=processValue;//上一次的测量量更新
return(iIncpid); // 返回增量值
}
#//死区控制值 DEAD_BAND 50
#//PID输出上限 PID_OUT_MAX 200
#//PID输出上限 PID_OUT_MAX 200
#
//PID结构体
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int Error2; // Error[n-2]
volatile int iError; // Error[n]
volatile int Error_sum;
} PID
/****************************************************************************************/ // 位置式PID
// //pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
/****************************************************************************************/
float PID_Postion (float set_point,,float now_point,PID* sptr)
{
float iIncpid=0;
sptr->iError=now_point-set_point; // 计算当前误差
//死区控制算法
if(fabs(sptr->iError)>DEAD_BAND)
{
sptr->Error_sum+=sptr->iError;//积分项
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum // I
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
sptr->Error1=sptr->iError ; // 存储误差,用于下次计算
}
else
{
iIncpid=0;
//sptr->Error_sum+=sptr->iError;//积分项
sptr->Error1=sptr->iError; // 存储误差,用于下次计算
}
return(iIncpid); // 返回计算值
}
/****************************************************************************************/ //增量式PID
// pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)] //
/****************************************************************************************/
float PID_increase(int iError,PID* sptr)
{
float iIncpid=0;
sptr->iError=iError;//直接检测当前偏差
if(fabs(sptr->iError)>DEAD_BAND)
{
iIncpid=sptr->Proportion * (sptr->iError-sptr->Error1) // P
+sptr->Integral * sptr->iError // I
+sptr->Derivative * (sptr->iError-2*sptr->Error1+sptr->Error2); // D
sptr->Error2=sptr->Error1; // 存储误差,用于下次计算
sptr->Error1=sptr->iError;
}
else
{
iIncpid=0;//输出增量值为0
sptr->Error2=sptr->Error1; // 存储误差,用于下次计算
sptr->Error1=sptr->iError;
}
return(iIncpid); // 返回增量值
}
typedef struct
{
volatile float Proportion; // 比例常数 Proportional Const
volatile float Integral; // 积分常数 Integral Const
volatile float Derivative; // 微分常数 Derivative Const
volatile int Error1; // Error[n-1]
volatile int Error2; // Error[n-2]
volatile int iError; // Error[n]
volatile int Error_sum;
} PID
/****************************************************************************************/ // 位置式PID
// //pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
/****************************************************************************************/
float PID_Postion (float set_point,,float now_point,PID* sptr)
{
float iIncpid=0;
sptr->iError=now_point-set_point; // 计算当前误差
//死区控制算法
sptr->Error_sum+=sptr->iError;//积分项
iIncpid=sptr->Proportion * sptr->iError // P
+sptr->Integral * sptr->Error_sum/2 // 改变的只是这里,多除了2
+sptr->Derivative * (sptr->iError-sptr->Error1); // D
sptr->Error1=sptr->iError ; // 存储误差,用于下次计算
return(iIncpid); // 返回计算值
}