0 前面的话

好久没有更新了,内心有种罪恶感,,至于原因,可能是因为菜吧,不知道该写什么,还有就是因为懒吧,虽然一部分在B乎上发了,被喷了一地,便没整理到公众号。后面打算整理一个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 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算法

由于作者能力和水平有限,文中难免存在错误和纰漏,请不吝赐教。

 简易PID算法的快速扫盲 

 一文教你搞懂C语言的Q格式

  现成轮子OSAL操作系统抽象层的移植

 一招教你单片机固件快速瘦身

基础知识 | hex文件格式详解

—— The End ——

长按识别二维码关注获取更多内容

增量式PID到底是什么?相关推荐

  1. 增量式速度pid调节策略_增量式PID是什么?不知道你就落伍了

    目录 1 什么是增量式PID? 2 举个例子 2.1 位置式PID 2.2 增量式PID 3 伪算法 4 C语言实现 5 总结 在之前一篇博客中( 简易PID算法的快速扫盲 )简单介绍了PID算法的基 ...

  2. 位置式PID与增量式PID的介绍和代码实现

    PID分为位置式PID与增量式PID. 一.位置式PID 1.表达式为: 2.缺点: 1).由于全量输出,所以每次输出均与过去状态有关,计算时要对ek进行累加,工作量大: 2).因为计算机输出的uk对 ...

  3. C语言实现PID算法:位置式PID和增量式PID

    原创者微信公众号 PID算法可以说是在自动控制原理中比较经典的一套算法,在现实生活中应用的比较广泛. 大学参加过电子竞赛的朋友都应该玩过电机(或者说循迹小车),我们要控制电机按照设定的速度运转,PID ...

  4. 【转】增量式PID控制算法

    (转载 出处blog.ednchina.com/tengjingshu )blog.ednchina.com/tengjingshu/211739/message.aspx# 当执行机构需要的不是控制 ...

  5. 位置式PID与增量式PID区别浅析

    1PID控制算法 什么是PID PID 控制器以各种形式使用超过了 1 世纪,广泛应用在机械设备.气动设备 和电子设备.在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法 PI ...

  6. 基于自适应算法和增量式PID算法的模拟直升飞机控制系统

    基于自适应算法和增量式PID算法的模拟直升飞机控制系统 文章目录 基于自适应算法和增量式PID算法的模拟直升飞机控制系统 控制系统硬件 单片机系统 传感器系统介绍 直升机模拟系统介绍 系统模块介绍 A ...

  7. 位置式和增量式PID控制

    PID控制是一个二阶线性控制器 定义:通过调整比例.积分和微分三项参数,使得大多数的工业控制系统获得良好的闭环控制性能. 优点 a. 技术成熟 b. 易被人们熟悉和掌握 c. 不需要建立数学模型 d. ...

  8. 增量式PID控制算法及仿真

    当执行机构需要的是控制量的增量(例如驱动步进电机)时,应采用增量式PID控制.根据递推原理可得: 增量式PID控制算法: 根据增量式PID控制算法,设计了仿真程序,被控对象如下: PID控制参数:kp ...

  9. 位置式PID与增量式PID区别浅析(百度百科增量式PID讲解思路概念更明确清晰)

    位置式PID与增量式PID区别浅析 Z小旋 2019-04-26 08:55:12  59882  收藏 713 分类专栏: NXP智能车学习 文章标签: 位置式PID PID 增量式PID 版权 1 ...

最新文章

  1. 分布式存储(ceph)技能图谱(持续更新)
  2. Windows下MemCache多端口安装配置
  3. C#中的预编译指令介绍
  4. CShockwaveFlash 函数列表
  5. 个人管理 - 程序员的四个阶段
  6. 故乡的路:十位少数民族摄影师联展
  7. mongo:(1)nosql简介
  8. 中科大 计算机网络10 第一章总结和习题
  9. 一个突变基因保护了欧洲人祖先
  10. PJAX初体验(主要是利用HTML5 新增API pushState和replaceState+AJAX)
  11. 黄聪:wordpress向mysql字段中保存html代码(使用add_option()方法),然后无法显示出问题...
  12. 一文了解新营销,数字经济时代如何以个人为中心重建品牌?
  13. linux虚拟主机的三种方法
  14. 微信公众号小程序怎么做?
  15. 基本社会里模型的源码分析
  16. HDU1071微积分公式求曲线面积
  17. 08#wordcloud2包 词云生成器
  18. ATF:Gicv源码解读系列-gicv2_spis_configure_defaults
  19. Ubuntu下WIFI不稳定问题
  20. 【CTO讲堂】企业该如何打造自身的“安全免疫系统”?

热门文章

  1. 【GUI】Python图形界面(一)
  2. Syncthing - P2P文件同步工具使用
  3. 解惑 功能需求和非功能性需求
  4. Java0921练习
  5. 百度地图实现 区域高亮
  6. 杭电 1248 寒冰王座
  7. 【Win10 UWP】QQ SDK(一):SDK基本使用方法
  8. 【成像】【2】Terahertz辐射发展前景
  9. 一招搞定多Offer选择
  10. 优化大师修复IE右键