增量式pid_增量式PID是什么?不知道你就落伍了

目录

  • 1 什么是增量式PID?

  • 2 举个例子

    • 2.1 位置式PID

    • 2.2 增量式PID

  • 3 伪算法

  • 4 C语言实现

  • 5 总结

在之前一篇博客中(  简易PID算法的快速扫盲 )简单介绍了 PID算法的基本原理位置式算法的实现过程,由于部分推导过程已经在上一篇文章做过介绍,所以推导过程本文不再赘述,重点将对离散增量式PID的算法进行实现。

1 什么是增量式PID?

先看一下 增量式PID的离散公式如下:
:比例系数 :积分系数 :微分系数 :偏差
对于所谓的 位置式增量式的算法,这两者只是在算法的实现上的存在差异,本质的控制上对于系统控制的影响还是相同,单纯从输入和输出的角度来比较,具体如下表所示; 985094abd02cd3ddf76d0637c5cf96f7.png这里简单的说明一下;
  • 位置式:位置式算法较为简单,直接输入当前的偏差 ,即可得到输出;
  • 增量式:增量式算法需要保存历史偏差,,,即在第次控制周期时,需要使用第和第次控制所输入的偏差,最终计算得到 ,此时,这还不是我们所需要的PID输出量;所以需要进行累加;
不难发现第一次控制周期时,即 时; 由以上公式我们可以推导出下式; 所以可以看出,最终PID的输出量 ,满足以下公式; 可见增量式算法,就是所计算出的PID增量的历史累加和;
f84483893cdb8e2a39ca3dbfe95f71c0.png

2 举个例子

2.1 位置式PID

下面从一个简单的例子中去理解一下增量式 PID,这里依然举一个不是很恰当的例子;如果是 位置式PID算法的话:
  • 隆哥对一个直流电机进行调速,设定了转速为 1000
  • 这时由于反馈回来的速度和设定的速度偏差为 ;
  • 经过位置式PID计算得到;
  • 作为Process的输入值(可以是PWM的占空比),最终Process输出相应的PWM驱动直流电机;
  • 反馈装置检测到电机转速,然后重复以上步骤;
整体框图如下所示;

84d6f088df4c9f6d9831713d879bd34c.png

2.2 增量式PID

对于增量式PID来说;
  • 隆哥对一个直流电机进行调速,设定了转速为 1000
  • 这时由于反馈回来的速度和设定的速度偏差为 ,系统中保存上一次的偏差和上上次的偏差,这三个输入量经过增量PID计算得到;
  • 系统中还保存了上一次的PID输出的,所以加上增量,就是本次控制周期的PID输出——;
  • 作为Process的输入值(可以是PWM的占空比),最终Process输出相应的PWM驱动直流电机;
  • 反馈装置检测到电机转速,然后重复以上步骤;
整体框图如下所示;
e9bbf008b907dbab0b2c40940d9ff832.png
所以这里不难发现,所谓 增量式PID,它的特点有:
  • 需要输入历史的偏差值;
  • 计算得到的是PID输出增量,因此每一次需要累加历史增量最为当前的PID输出;
下面简单介绍一下如何实现 增量式PID算法;

3 伪算法

previous02_error := 0  //上上次偏差
previous01_error := 0  //上一次偏差
integral := 0   //积分和
pid_out := 0   //pid增量累加和//循环 //采样周期为dt
loop://setpoint 设定值//measured_value 反馈值
    error := setpoint − measured_value //计算得到偏差
    proportion := error - previous01_error //计算得到比例输出
    integral := error × dt //计算得到积分累加和
    derivative := (error − 2*previous01_error + previous02_error) / dt //计算得到微分
    pid_delta := Kp × error + Ki × integral + Kd × derivative //计算得到PID增量
    pid_out := pid_out + pid_delta //计算得到PID输出//保存当前的偏差和上一次偏差作为下一次采样所需要的历史偏差
    previous02_error := previous01_error 
    previous01_error := error    //保存当前偏差为下一次采样时所需要的历史偏差
    wait(dt) //等待下一次采用goto loop

4 C语言实现

这里直接使用了 TI公司的PID算法,做了积分抗饱和;具体可以参考 controlSUITE\libs\app_libs\motor_control\math_blocks\v4.2\pid_grando.h具体代码如下所示; pid_grando.h
/* =================================================================================
File name:       PID_GRANDO.H 
===================================================================================*/#ifndef __PID_H__#define __PID_H__typedef struct {  _iq  Ref;      // Input: reference set-point
      _iq  Fbk;      // Input: feedback
      _iq  Out;      // Output: controller output 
      _iq  c1;      // Internal: derivative filter coefficient 1
      _iq  c2;      // Internal: derivative filter coefficient 2
    } PID_TERMINALS;// note: c1 & c2 placed here to keep structure size under 8 wordstypedef struct {  _iq  Kr;    // Parameter: reference set-point weighting 
      _iq  Kp;    // Parameter: proportional loop gain
      _iq  Ki;       // Parameter: integral gain
      _iq  Kd;           // Parameter: derivative gain
      _iq  Km;           // Parameter: derivative weighting
      _iq  Umax;   // Parameter: upper saturation limit
      _iq  Umin;   // Parameter: lower saturation limit
    } PID_PARAMETERS;typedef struct {  _iq  up;    // Data: proportional term
      _iq  ui;    // Data: integral term
      _iq  ud;    // Data: derivative term
      _iq  v1;    // Data: pre-saturated controller output
      _iq  i1;    // Data: integrator storage: ui(k-1)
      _iq  d1;    // Data: differentiator storage: ud(k-1)
      _iq  d2;    // Data: differentiator storage: d2(k-1) 
      _iq  w1;    // Data: saturation record: [u(k-1) - v(k-1)]
    } PID_DATA;typedef struct {  PID_TERMINALS term;
      PID_PARAMETERS param;
      PID_DATA  data;
    } PID_CONTROLLER;/*-----------------------------------------------------------------------------
Default initalisation values for the PID objects
-----------------------------------------------------------------------------*/                     #define PID_TERM_DEFAULTS {    \                  0,  \
                           0,  \
                           0,  \
                           0,  \                  0   \
                   }#define PID_PARAM_DEFAULTS {    \
                           _IQ(1.0), \
                           _IQ(1.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(1.0), \
                           _IQ(1.0), \
                           _IQ(-1.0) \
                   }#define PID_DATA_DEFAULTS {        \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(0.0), \
                           _IQ(1.0)  \
                   }/*------------------------------------------------------------------------------
  PID Macro Definition
------------------------------------------------------------------------------*/#define PID_MACRO(v)                                         \                                                             \/* proportional term */                                         \
v.data.up = _IQmpy(v.param.Kr, v.term.Ref) - v.term.Fbk;  \                                              \/* integral term */                                          \
v.data.ui = _IQmpy(v.param.Ki, _IQmpy(v.data.w1,                  \
(v.term.Ref - v.term.Fbk))) + v.data.i1;                     \
v.data.i1 = v.data.ui;                                         \                                              \/* derivative term */                                          \
v.data.d2 = _IQmpy(v.param.Kd, _IQmpy(v.term.c1,                  \
(_IQmpy(v.term.Ref, v.param.Km) - v.term.Fbk))) - v.data.d2; \
v.data.ud = v.data.d2 + v.data.d1;                       \
v.data.d1 = _IQmpy(v.data.ud, v.term.c2);                     \                                              \/* control output */                                          \
v.data.v1 = _IQmpy(v.param.Kp,                                    \
(v.data.up + v.data.ui + v.data.ud));                             \
v.term.Out= _IQsat(v.data.v1, v.param.Umax, v.param.Umin);        \
v.data.w1 = (v.term.Out == v.data.v1) ? _IQ(1.0) : _IQ(0.0);      \#endif // __PID_H__
example
/* Instance the PID module */ 
PID   pid1={ PID_TERM_DEFAULTS, PID_PARAM_DEFAULTS, PID_DATA_DEFAULTS }; 
main() { 
    pid1.param.Kp = _IQ(0.5);     
    pid1.param.Ki  = _IQ(0.005);    
    pid1.param.Kd = _IQ(0);      
    pid1.param.Kr  = _IQ(1.0);     
    pid1.param.Km =_IQ(1.0);     
    pid1.param.Umax= _IQ(1.0);      
    pid1.param.Umin= _IQ(-1.0); 
} void interrupt periodic_interrupt_isr() {  
    pid1.Ref = input1_1;   // Pass _iq inputs to pid1 
    pid1.Fbk = input1_2;   // Pass _iq inputs to pid1   
    PID_MACRO(pid1);  // Call compute macro for pid1        
    output1 = pid1.Out;  // Access the output of pid1     
}

5 总结

本文简单总结了 位置式PID算法增量式PID算法的差异,参考了TI公司的增量式PID算法实现,对于不同的控制对象可以根据系统要求选择合适的 PID算法-END-

往期好文合集

PID到底是个啥?来给你讲个故事再论PID,PID其实很简单。。。电子设计竞赛(4)-常用的两种PID算法

  最 后   

若觉得文章不错, 转发分享 ,也是我们继续更新的动力。 5T资源大放送! 包括但不限于: C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、labview、单片机、等等 在公众号内回复「更多资源」,即可免费获取,期待你的关注~ 53ae78c699c9feb574654ae0b2cc1922.png 20c503c8a668a15fc19074292c222e9a.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值