串级PID调试simulink仿真

设计串级PID

串级PID图解:

在这里插入图片描述

在设计串级PID的时候,我们从图可以知道,主控制器的输出是副控制器的输入。

主控制器输出可以是输出实际的物理量,也可以输出百分比。若是输出实际物理量的值,需要知道主控制器输出的物理量与负控制量的实际一些关系,显然是不够合适的。比如外环是位置,内环是速度,外环输出的值,外环PID控制的是位置,经过PID控制器,实际含义已经改变,难以知道这个含义和速度的关系。

若是外环输出百分比,更加灵活,只需将百分比和副控制变量进行量化计算即可。

实际输出的百分比可以这样实现(比如外环是位置,内环是速度),C部分逻辑代码

//输出限幅
#define OUT_MIN        -1000
#define OUT_MAX        1000
             
//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->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;                    // 存储误差,用于下次计算        
    iIncpid=PID_OutputLimit(sptr,iIncpid);//在其他地方进行了限幅处理,此处就不用了                                    
  return(iIncpid);          // 返回计算值
    
}

//PID初始化
//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;
}

float series_pid(void)//串级PID函数
{
    int get_point=30;//内环期望值
    float in_pid,out_pid,temp;
    out_pid=PID_Postion(iError,sptr1);//获取外环PID的值 
    out_pid=(OUT_MAX-OUT_MIN)*out_pid/100;//输出百分比,分为100份
    in_pid=out_pid-get_point;//得到偏差值
    temp=PID_Postion(in_pid,sptr2);//外环输出作为内环输入
    return temp;//返回内环输出值
}

搭建simulink模型,进行串级PID参数调试

结合口诀PID tuner进行调参,PID tuner调整内环PID参数,人工经验整定,调整外环参数。

串级PID调参的一般步骤是先内环后外环。

PID调参一般注意的几个参数:

超调量:最大值超过设定值多少
上升时间:到达设定值的时间
曲线稳定在设定值时间:
以及曲线是否稳定:不发散

可以通过观察这些量来衡量PID调试的质量,一般来说,这些指标不可能同时达到最优,需要根据你的系统进行调整,选择比较适合自己系统,进行一些取舍。比如说,你的系统要求是需要比较灵敏,那上升时间就不能太长。系统需要稳定,那超调量就不能大。

下面结合PID tuner和口诀进行调试,但因为有时候PID tuner是不能够计算出比较合适的PID的值,需要人工整定。
口诀:

参数整定找最佳,从大到小顺次查

先是比例后积分,最后再把微分加

曲线震荡很频繁,比例度盘要放大

曲线漂浮绕大弯,比例度盘往小扳

曲线偏离回复慢,积分时间往下降

曲线波动周期长,积分时间要加长

理想曲线两个波,调节过程高质量

电机控制位置的串级PID,simulink仿真:

因为这里只是说整定方法,没有对PID外环的输出进行处理。

在这里插入图片描述

使用PID tuner调节内环:需要先断开外环

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

可以说调节的非常棒了,计算出的准确的PID参数的值。
但是这个是不够精准的,我们加一些扰动看看(二级扰动)

在这里插入图片描述

可以说,扰动非常大。这个也是PID tuner的一个缺点,不会把一些扰动也计算进去,但是这个得出来的值仍有一定的参考价值。

在这里插入图片描述

把扰动去掉,保持内环PID的值不变,调节外环PID(结合口诀)

在这里插入图片描述

先是比例后积分,最后再把微分加,先调节比例,其他清零。
逐渐增大Kp的值,调节时间减少,超调量增加,曲线震荡变得频繁。

kp=1

在这里插入图片描述

kp=20(曲线漂浮绕大弯,比例度盘往小扳)

在这里插入图片描述

kp=10,这时曲线比较合适

在这里插入图片描述

调试Ki,因为没有静差了,不用Ki也没问题。所以Ki=0

调试Kd,从大到小

kd太大了,曲线发散

在这里插入图片描述

kd减少了几个数量级,曲线还是发散,Kd只能取0

在这里插入图片描述

最后,根据实际情况,Kp=10,Ki=0,Kd=0;口诀不适合这个系统,还是要根据实际情况和PID的调节的一些参数进行调节。口诀只是辅助调试。

扰动对内外环的干扰

我们在内环添加扰动,看看曲线变化情况,

二级扰动干扰情况

在这里插入图片描述

在这里插入图片描述

一级扰动

在这里插入图片描述

在这里插入图片描述

外环添加扰动:

一级扰动

在这里插入图片描述

在这里插入图片描述

外环二级扰动:

在这里插入图片描述

在这里插入图片描述

通过对比,发现,串级PID能够很好地抑制对内环的干扰,对外环就没有很好的效果。