关于增量式PID的代码(C语言)实现的详细说明--应该可以解决部分人的疑惑

关于增量式PID的代码(C语言)实现的详细说明

网上可以找到很多关于增量式PID的一些解释说明;
最终都可以得到如下的公式:

Δu=Kp·{e(n)-e(n-1)}+Ki·e(n)+Kd·{e(n)-2·e(n-1)+e(n-2)} ;

最终转换成代码有很多是

  typedef struct
    {
      float Kp;                       //比例系数Proportional
      float Ki;                       //积分系数Integral
      float Kd;                       //微分系数Derivative
     
      float Ek;                       //当前误差
      float Ek1;                      //前一次误差 e(k-1)
      float Ek2;                      //再前一次误差 e(k-2)
    }PID_IncTypeDef;
    //非本人编写
    float PID_Inc(float SetValue, float ActualValue, PID_IncTypeDef *PID)
    {
      float PIDInc;                                  //增量
     
      PID->Ek = SetValue - ActualValue;
      PIDInc = (PID->Kp * PID->Ek) - (PID->Ki * PID->Ek1) + (PID->Kd * PID->Ek2);
     
      PID->Ek2 = PID->Ek1;
      PID->Ek1 = PID->Ek;  return PIDInc;
    }

有些人对代码存在一定的疑惑,其实代码是没有问题的;
公式为:

Δu=Kp·{e(n)-e(n-1)}+Ki·e(n)+Kd·{e(n)-2·e(n-1)+e(n-2)}

整理为:

Δu=(Kp+Ki)·e(n)-(Kp+2)·e(n-1)+Kd·e(n-2)

由于Pid需要整定参数、因而可以将上式三项误差前的数当作一个整体;
即表示为:

Δu=KP·e(n)-KI·e(n-1)+KD·e(n-2)

将上式对比代码、则可以得出、代码是符合公式的

当然我们也可以将代码完全按照公式来描述

typedef struct{
	float limit;		//输出限幅
	float target;		//目标输出量
	float feedback;		//实际输出量	
	float Kp;	
	float Ki;	
	float Kd;	
	float e_0;			//当前误差
	float e_1;			//上一次误差
	float e_2;			//上上次误差
}PID;
 
#define max(a, b)			(a>b? a:b)
#define min(a, b)			(ae_0 = pid->target - pid->feedback;
	ep = pid->e_0  - pid->e_1;
	ei = pid->e_0;
	ed = pid->e_0 - 2*pid->e_1 + pid->e_2;
	out = pid->Kp*ep + pid->Ki*ei + pid->Kd*ed;
	out = range(out, -pid->limit, pid->limit);
	pid->e_2 = pid->e_1;
	pid->e_1 = pid->e_0;
	return out;
}

个人还是比较建议第二种写法!调参的时候也更加直观一点;

你可能感兴趣的:(关于增量式PID的代码(C语言)实现的详细说明--应该可以解决部分人的疑惑)