增量式PID控制代码的实现

/*************************************************************
函数:  int16_t Idle_PID_Ctrl(uint16_t setpoint,uint16_t point) 
功能:  增量式PID算法,得到增量值
参数:  setpoint:    设定值
       point:       当前值
返回:  uk:          PID算法的控制增量
描述:  返回增量值,即在上一次的控制量的基础上需要增加(负值意味减少)控制量
**************************************************************/
int16_t Idle_PID_Calc(uint16_t setpoint,uint16_t point) 
{
  float Kp = 0.0;                  //Proportion
  float Ki = 0.0;                  //Integral
  float Kd = 0.0;                  //Differential    
    
  static int32_t ek_2 = 0;         //上上次误差
  static int32_t ek_1 = 0;         //上一次误差
  static int32_t ek = 0;           //当前误差                                                                    
  int16_t uk;                      //控制量增量
                                        
  Kp = inpram.RPMOXLimit/100.0;    
  Ki = inpram.TPSOXLimit/1000.0;   //这里上位机将edit里的数据*10,所以Ki的实际结果为edit/100
  Kd = inpram.MAPOXLimit/1000.0;   //这里上位机将edit里的数据*10,所以Kd的实际结果为edit/100 
    
  ek = setpoint - point;           //得到当前误差
    
  uk = (int16_t)(Kp*(ek - ek_1)+ Ki*ek + Kd*(ek - 2*ek_1 + ek_2));  
ek_2
= ek_1; ek_1 = ek;
return (uk); }

上面是增量式PID算法的当前增量值代码段,完整并且实用的程序,还要与历史增量值相加,并要对总历史总量值进行限幅,为何要限幅呢?因为控制的总量要送到执行机构,而执行机构往往是有机械限位的,

比如此例子中,实际是控制节气门的开关角度,而节气门是由舵机控制的,舵机不能变化的太大,否则转速不稳定,造成发动机熄火,还会损坏舵机,减少其寿命。

看下一段代码:

if(cnt_xS++ >= INTERVAL_50MS)  //PID控制周期,在1ms定时中断内
{
  cnt_xS = 0;            
            
  rpm_setpoint = (inpram.RevLimRpm2 - inpram.Idle_rpm)*outpc.tps;            //飞控油门对应的转速增值
  rpm_setpoint = rpm_setpoint/1000 + inpram.Idle_rpm;                        //当前油门对应的目标转速
            
  Idle.PID_increment = Idle_PID_Calc(rpm_setpoint,outpc.rpm);                //得到PID控制增量                                
  Idle.PID_value = Idle.PID_value + Idle.PID_increment;                      //得到PID控制总量,实际赋值给outpc.tps
            
  //PID控制总量(即总历史值)加入限幅算法,控制在10%,防止单个控制周期内节气门波动过大,造成转速不稳
  if(Idle.PID_value > 100) 
    {
      Idle.PID_value = 100;
    }
else
if(Idle.PID_value < -100) { Idle.PID_value = -100; } tps_temp = outpc.tps + Idle.PID_value;
//对舵机进行机械限幅
if(tps_temp > 1000) { Syspara.tps = 1000; } else if(tps_temp < 0) { Syspara.tps = 0; } else { Syspara.tps = tps_temp; }
}

根据自己的需要加入合适的限幅算法,也可以只保留机械限幅,这里在每次总增量控制处加入10%的限幅,是防止PID增量波动过大造成舵机不稳,进而影响转速。

原文地址:https://www.cnblogs.com/xyelectric/p/12199802.html