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

目录

  • 1 什么是增量式PID?

  • 2 举个例子

    • 2.1 位置式PID

    • 2.2 增量式PID

  • 3 伪算法

  • 4 C语言实现

  • 5 总结


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

1 什么是增量式PID?

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

2 举个例子

2.1 位置式PID

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

2.2 增量式PID

对于增量式PID来说;
  • 隆哥对一个直流电机进行调速,设定了转速为 1000
  • 这时由于反馈回来的速度和设定的速度偏差为 ,系统中保存上一次的偏差 和上上次的偏差 ,这三个输入量经过 增量PID计算得到
  • 系统中还保存了上一次的 PID输出 ,所以 加上增量 ,就是本次控制周期的 PID输出——
  • 作为 Process的输入值(可以是 PWM的占空比),最终 Process输出相应的 PWM驱动直流电机;
  • 反馈装置检测到电机转速,然后重复以上步骤;
整体框图如下所示;
所以这里不难发现,所谓 增量式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 words

typedef  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、单片机、等等
在公众号内回复「更多资源」,即可免费获取,期待你的关注~

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

当我们谈起C语言,很多人第一印象是面向底层、面向系统的编译型语言,写出来的程序一般都是从头到尾跑一遍就结束,很少和用户交互。但实际上,C语言从诞生开始就支持交互式的程序设计,通过标准输入输出和用户实时交互,接收用户输入、...

关键字: C语言 编程

在STM32嵌入式开发中,精确延时是非常基础但又极其关键的功能。无论是驱动单总线传感器(比如DS18B20)、控制LCD屏幕时序、还是生成精确的脉冲信号,都需要用到微秒级甚至纳秒级精度的延时。很多新手刚开始使用STM32...

关键字: STM32 嵌入式

在C语言开发中,位操作符是最容易被新手忽略,却能在嵌入式开发、底层驱动、算法优化中发挥巨大作用的工具。和常规的算术操作、逻辑操作相比,位操作直接操作二进制位,执行效率更高,占用代码空间更小,能轻松实现很多用常规方法很难实...

关键字: C语言 位操作符

在C语言开发中,原生字符串的使用一直存在诸多不便。传统C语言中,字符串本质是以'\0'结尾的固定字符数组,开发人员必须提前预估字符串的最大长度:如果预估过小,拼接或插入字符时会出现缓冲区溢出,引发内存越界错误;如果预估过...

关键字: C语言 字符串

随着半导体测试向更高复杂性与并行度演进,多工位自动测试设备(ATE)和SiC/GaN测试对电感、电容和电阻(LCR)测量的需求不断提升。然而,传统的外接台式LCR仪表和基于线缆的设置难以扩展,而且会降低可重复性。本文介绍...

关键字: 半导体 电阻 嵌入式

智能高尔夫球追踪系统是一项创新的嵌入式电子项目,旨在展示如何将紧凑型物联网硬件集成到体育科技应用中。在体育领域,高尔夫球扮演着主要角色,但在现代时代,所有设备都变得更加智能化,高尔夫球也由此演变为智能高尔夫球。本项目结合...

关键字: 嵌入式 物联网 NRF无线技术

在工业自动化、智能传感、嵌入式组网等分布式总线系统中,设备自动地址分配是实现节点互联互通、即插即用的核心技术。传统人工配置地址方式存在操作繁琐、扩展性差、地址冲突风险高、维护成本高等诸多问题,已无法适配大规模、动态化的总...

关键字: 总线 嵌入式 组网

2026年6月8日 – 专注于引入新品的全球电子元器件和工业自动化产品授权代理商贸泽电子 (Mouser Electronics) 正式宣布,首次荣获全球嵌入式应用安全连接解决方案知名供应商NXP® Semiconduc...

关键字: 物联网 移动设备 嵌入式

城市灯火通明、生活井然运转的背后,总有人在不被注意的地方,日复一日地坚持着。他们或许没有惊天动地的故事,却在漫长岁月里,用自己的方式守护着他人的生活。近日,乡村教师班爱花、爱心厨房运营者丫丫妈,以及“扛楼女工”云姐的故事...

关键字: 西门子家电 洗碗机 嵌入式

2026年5月15日,正值“世界无幽日”,一组数据再次引发公众关注:据《中国幽门螺杆菌感染防控》白皮书显示,我国幽门螺杆菌人群感染率已接近50%,涉及超过7亿人口,且家庭内传播特征极为显著——父母若感染,子女感染风险升高...

关键字: 洗碗机 AI 嵌入式
关闭