PID含义
PID是英文单词比例(Proportion),积分(Integral),微分(Differential coefficient)的缩写。PID调节实际上是由比例、积分、微分三种调节方式组成,它们各自的作用如下:
比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。
积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器。
微分调节作用:微分作用反映系统偏差信号的变化率,具有预见性,能预见偏差变化的趋势,因此能产生超前的控制作用,在偏差还没有形成之前,已被微分调节作用消除。因此,可以改善系统的动态性能。在微分时间选择合适情况下,可以减少超调,减少调节时间。微分作用对噪声干扰有放大作用,因此过强的加微分调节,对系统抗干扰不利。此外,微分反应的是变化率,而当输入没有变化时,微分作用输出为零。微分作用不能单独使用,需要与另外两种调节规律相结合,组成PD或PID控制器。
PID调试一般原则:
a.在输出不振荡时,增大比例增益P。
b.在输出不振荡时,减小积分时间常数Ti。
c.在输出不振荡时,增大微分时间常数Td。
代码例子1
P参数越大,系统的响应速度就越快,目标值与实际值的差值来实时决定的,误差越大,计算出来的PWM就越大,误差越小计算出来的PWM就越小,而P参数就相当于一条直线的斜率,斜率越大,纵坐标对于横坐标的变化就越敏感,也就是系统对于外界的变化的响应速度越快。
int PwmPID_Kp = 2;
void SetSpeed(u16 PwmSet,u16 PwmReal)//入口参数:目标值,实际值
{
int PwmError=0,PwmIncPWM=0 ;
PwmError=PwmSet-PwmReal;//本次偏差等于目标值减去实际值
PwmError = PwmError>>5;
PwmIncPWM=(int)(PwmPID_Kp*PwmError);
PwmMotor_L+=PwmIncPWM;
PwmMotor_R-=PwmIncPWM;
if(PwmMotor_L>=100)
PwmMotor_L=100;
else if(PwmMotor_L<=10)
PwmMotor_L=10;
if(PwmMotor_R>=100)
PwmMotor_R=100;
else if(PwmMotor_R<=10)
PwmMotor_R=10;
TIM_SetCompare2(TIM5 , PwmMotor_L);
TIM_SetCompare1(TIM5 , PwmMotor_R);
xprintf("\r\n test PwmMotor_L=%d PwmMotor_R=%d PwmIncPWM=%d\r\n",PwmMotor_L,PwmMotor_R,PwmIncPWM);
}
例子2
///
//PID偏差控制计算
void PIDControl() //pid偏差计算
{
e=SpeedSet-num;//设置速度-实际速度,两者的差值
//对应于增量式PID的公式Δuk=uk-u(k-1)
// duk=(Kp*(e-e1))/100;//只调节P
duk=(Kp*(e-e1)+Ki*e)/100;//只调节PI
// duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/100;//调节PID
uk=uk1+duk;//uk=u(k-1)+Δuk
out=(int)uk;//取整后输出
if(out>250) //设置最大限制
out=250;
else if(out<0)//设置最小限制
out=0;
uk1=uk; //为下一次增量做准备
e2=e1;
e1=e;
PWMTime=out; //out对应于PWM高电平的时间
例子3
/******************** (C) COPYRIGHT Adrian *************************************
* 文件名 :PID.c
* 描述 :增量式PID算法和位置式PID算法
* 作者 :Adrian
* 版本更新: 2016-05-01
* 硬件连接:
* 调试方式:J-Link-OB
**********************************************************************************/
#include"PID.h"
//采用增量式计算,采样周期为T时间
//Δu(k)=u(k)-u(k-1) = Kp*Δe(k)+ Ki*e(k)+ Kd*[Δe(k)-Δe(k-1)] ,式中Δe(k)=e(k)-e(k-1)
// = Kp*[e(k)-e(k-1) + (T/Ti)*e(k) + Td*((e(k)-2*e(k-1)+e(k-2))/T)] (式1-1)
// = Kp*(1+T/Ti+Td/T)*e(k) - Kp*(1+2*Td/T)*e(k-1) + Kp*Td/T*e(k-2)
// = A*e(k) - B*e(k-1) + C*e(k-2) (式1-2)
//式中:
// Δu(k)——控制器(也称调节器)的输出增量;
// e(k)——控制器的输入(常常是设定值与被控量之差,即e(k)=r(k)-c(k));
// Ki=(Kp*T)/Ti 为积分系数
// Kd=(Kp*Td)/T 为微分系数
//式中: T:采样周期
// Kp——控制器的比例放大系数;
// Ti——控制器的积分时间;
// Td——控制器的微分时间。
/**
* @file IncrementalPIDInit
* @brief 增量式PID参数初始化
* @param *S:PID结构体 Piont:目标值 T:采样周期 Kp:控制器的比例放大系数 Ti:控制器的积分时间; Td:控制器的微分时间;
* @retval 无
*/
void IncrementalPIDInit(IncrementalPID *S, int32_t Piont, double T, double Kp, double Ti, double Td)
{
S->SetPoint = Piont; //目标值
S->SumError = 0;
S->A = Kp*(1+T/Ti+Td/T); //
S->B = Kp*(1+2*Td/T); //
S->C = Kp*Td/T; //
S->NowError = 0; //当前误差
S->LastError = 0; //上次误差
S->PrevError = 0; //上上次误差
}
//Position type PID
/**
* @file IncrementalPIDCalc(式1-2)
* @brief 增量式PID迭代
* @param *S: x:根据反馈量得到的值(属性和Sptr->SetPoint一样)
* @retval PID调节后控制信号增量
*/
int32_t IncrementalPIDCalc(IncrementalPID *Sptr, int32_t x)
{
int32_t Out = 0;
Sptr->NowError = Sptr->SetPoint - x;
Out = Sptr->A * Sptr->NowError - Sptr->B * Sptr->LastError + Sptr->C * Sptr->PrevError; //(式1-2)
Sptr->PrevError = Sptr->LastError;
Sptr->LastError = Sptr->NowError;
return (Out);
}
void PointSetIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID设置目标值
{
Sptr->SetPoint = Piont; //目标值
}
void PointSubIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID目标值递减
{
Sptr->SetPoint = Sptr->SetPoint - Piont; //目标值
}
void PointAddIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID目标值递增
{
Sptr->SetPoint = Sptr->SetPoint + Piont; //目标值
}
/**
* @file IncrementalPIDInit1
* @brief 增量式PID参数初始化
* @param *S:PID结构体 Piont:目标值 T:采样周期 Kp:控制器的比例放大系数 Ti:控制器的积分时间; Td:控制器的微分时间;
* @retval 无
*/
void IncrementalPIDInit1(IncrementalPID1 *S, int32_t Piont, double T, double Kp, double Ti, double Td)
{
S->SetPoint = Piont; //目标值
S->Kp = Kp; //
S->Ki = Kp*T/Ti; //
S->Kd = Kp*Td/T; //
S->NowError = 0; //当前误差
S->LastError = 0; //上次误差
S->PrevError = 0; //上上次误差
S->SumError = 0;
}
/**
* @file IncrementalPIDCalc1(式1-1)
* @brief 增量式PID迭代
* @param *S: x:根据反馈量得到的值(属性和Sptr->SetPoint一样)
* @retval PID调节后控制信号增量
*/
int32_t IncrementalPIDCalc1(IncrementalPID1 *Sptr, int32_t NowPoint)
{
int32_t Out = 0;
Sptr->NowError = Sptr->SetPoint - NowPoint;
Out = Sptr->Kp * (Sptr->NowError - Sptr->LastError) + Sptr->Ki * Sptr->NowError + Sptr->Kd * (Sptr->NowError - 2 * (Sptr->LastError) + Sptr->PrevError); //(式1-1)
Sptr->PrevError = Sptr->LastError;
Sptr->LastError = Sptr->NowError;
return (Out);
}
/*********************************************END OF FILE**********************/