大家好,我是张巧龙,网上关于PID算法的文章很多,但是感觉有必要自己再进行一次总结,抽丝剥茧地重新认识了一下PID;

  • 1 前言

  • 2 开环控制

  • 3 闭环控制

  • 4 PID

    • 4.1 系统架构

    • 4.2 理论基础

    • 4.3 离散化

    • 4.4 伪算法

  • 5 C++实现

  • 6 总结

1 前言

控制系统通常根据有没有反馈会分为开环系统和闭环系统,在闭环系统的控制中,PID算法非常强大,其三个部分分别为;

  • P:比例环节;

  • I:积分环节;

  • D:微分环节;

PID算法可以自动对控制系统进行准确且迅速的校正,因此被广泛地应用于工业控制系统。

2 开环控制

首先来看开环控制系统,如下图所示,隆哥蒙着眼,需要走到虚线旗帜所表示的目标位置,由于缺少反馈(眼睛可以感知当前距离和位置,由于眼睛被蒙上没有反馈,所以这也是一个开环系统),最终隆哥会较大概率偏离预期的目标,可能会运行到途中实线旗帜所表示的位置。

开环系统的整体结构如下所示;

这里做一个不是很恰当的比喻;

  • Input:告诉隆哥目标距离的直线位置(10米);

  • Controller:隆哥大脑中计算出到达目标所需要走多少步

  • Process:双腿作为执行机构,输出了相应的步数,但是最终仍然偏离了目标;

看来没有反馈的存在,很难准确到达目标位置。

3 闭环控制

所以为了准确到达目标位置,这里就需要引入反馈,具体如下图所示;

在这里继续举个不怎么恰当的比喻;隆哥重获光明之后,基本可以看到目标位置了;

  • 第一步Input:告诉隆哥目标距离的直线位置(10米);

  • 第二步Controller:隆哥大脑中计算出到达目标所需要走多少步

  • 第三步Process:双腿作为执行机构,输出了相应的步数,但是最终仍然偏离了目标;

  • 第四步Feedback通过视觉获取到目前已经前进的距离,(比如前进了2米,那么还有8米的偏差);

  • 第五步err:根据偏差重新计算所需要的步数,然后重复上述四个步骤,最终隆哥达到最终的目标位置。

4 PID

4.1 系统架构

虽然在反馈系统下,隆哥最终到达目标位置,但是现在又来了新的任务,就是又地到达目标位置。所以这里隆哥开始采用PID Controller,只要适当调整PID的参数,就可以到达目标位置,具体如下图所示;

隆哥为了最短时间内到达目标位置,进行了不断的尝试,分别出现了以下几种情况;

  • 跑得太快,最终导致冲过了目标位置还得往回跑

  • 跑得太慢,最终导致到达目标位置所用时间太长

经过不断的尝试,终于找到了最佳的方式,其过程大概如下图所示;这里依然举一个不是很恰当的比喻;

  • 第一步:得到与目标位置的距离偏差(比如最开始是10米,后面会逐渐变小);

  • 第二步:根据误差,预估需要多少速度,如何估算呢,看下面几步;

P比例则是给定一个速度的大致范围,满足下面这个公式;

因此比例作用相当于某一时刻的偏差err)与比例系数的乘积,具体如下所示;

比例作用

绿色线为上述例子中从初始位置到目标位置的距离变化;红色线为上述例子中从初始位置到目标位置的偏差变化,两者为互补的关系;


I积分则是误差在一定时间内的和,满足以下公式;

如下图所示;

红色曲线阴影部分面积即为积分作用的结果,其不断累积的误差,最终乘以积分系数就得到了积分部分的输出;


D微分则是误差变化曲线某处的导数,或者说是某一点的斜率,因此这里需要引入微分;

从图中可知,当偏差变化过快,微分环节会输出较大的负数,作为抑制输出继续上升,从而抑制过冲。


综上,,,,分别增加其中一项参数会对系统造成的影响总结如下表所示;

参数 上升时间 超调量 响应时间 稳态误差 稳定性
Kp 减少 增加 小变化 减少 降级
Ki 减少 增加 增加 消除 降级
Kd 微小的变化 减少 减少 理论上没有影响 小,稳定性会提升

4.2 理论基础

上面扯了这么多,无非是为了初步理解PID在负反馈系统中的调节作用,下面开始推导一下算法实现的具体过程;PID控制器的系统框图如下所示;

图片来自Wiki

因此不难得出输入和输出的关系;

是比例增益;是积分增益;是微分增益;

4.3 离散化

在数字系统中进行PID算法控制,需要对上述算法进行离散化;假设系统采样时间为则将输入序列化得到;

将输出序列化得到;

  • 比例项:离散化

  • 积分项:

  • 微分项:

所以最终可以得到式①,也就是网上所说的位置式PID

将式①再做一下简化;

最终得到增量式PID的离散公式如下:

4.4 伪算法

这里简单总结一下增量式PID实现的伪算法;


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

5 C++实现

这里是增量式PID算法的C语言实现;

pid.cpp

#ifndef _PID_SOURCE_
#define _PID_SOURCE_#include <iostream>
#include <cmath>
#include "pid.h"using namespace std;class PIDImpl
{public:PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki );~PIDImpl();double calculate( double setpoint, double pv );private:double _dt;double _max;double _min;double _Kp;double _Kd;double _Ki;double _pre_error;double _integral;
};PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki )
{pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki);
}
double PID::calculate( double setpoint, double pv )
{return pimpl->calculate(setpoint,pv);
}
PID::~PID()
{delete pimpl;
}/*** Implementation*/
PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki ) :_dt(dt),_max(max),_min(min),_Kp(Kp),_Kd(Kd),_Ki(Ki),_pre_error(0),_integral(0)
{
}double PIDImpl::calculate( double setpoint, double pv )
{// Calculate errordouble error = setpoint - pv;// Proportional termdouble Pout = _Kp * error;// Integral term_integral += error * _dt;double Iout = _Ki * _integral;// Derivative termdouble derivative = (error - _pre_error) / _dt;double Dout = _Kd * derivative;// Calculate total outputdouble output = Pout + Iout + Dout;// Restrict to max/minif( output > _max )output = _max;else if( output < _min )output = _min;// Save error to previous error_pre_error = error;return output;
}PIDImpl::~PIDImpl()
{
}#endif

pid.h

#ifndef _PID_H_
#define _PID_H_class PIDImpl;
class PID
{public:// Kp -  proportional gain// Ki -  Integral gain// Kd -  derivative gain// dt -  loop interval time// max - maximum value of manipulated variable// min - minimum value of manipulated variablePID( double dt, double max, double min, double Kp, double Kd, double Ki );// Returns the manipulated variable given a setpoint and current process valuedouble calculate( double setpoint, double pv );~PID();private:PIDImpl *pimpl;
};#endif

pid_example.cpp

#include "pid.h"
#include <stdio.h>int main() {PID pid = PID(0.1, 100, -100, 0.1, 0.01, 0.5);double val = 20;for (int i = 0; i < 100; i++) {double inc = pid.calculate(0, val);printf("val:% 7.3f inc:% 7.3f\n", val, inc);val += inc;}return 0;
}

编译并测试;

g++ -c pid.cpp -o pid.o
# To compile example code:
g++ pid_example.cpp pid.o -o pid_example

6 总结

本文总结了PID控制器算法在闭环系统中根据偏差变化的具体调节作用,每个环节可能对系统输出造成什么样的变化,给出了位置式和增量式离散PID算法的推导过程,并给出了位置式算法的C++程序实现。

-END-

大家好,我是张巧龙,一名教电子的大学老师,欢迎关注!

PID算法搞不懂?看这篇文章。相关推荐

  1. PID算法搞不懂?看这篇文章就够了。

    点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! 转自知乎: jason 原文链接:https://zhuanlan.zhihu.co ...

  2. 如果你看不懂KMP算法,那就看一看这篇文章( 绝对原创,绝对通俗易懂)

    如果你看不懂KMP算法,那就看一看这篇文章(绝对原创,绝对通俗易懂) KMP算法,俗称"看毛片"算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易.整个 ...

  3. 使用分层网络模型的两个优点是什么_从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了...

    从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了​mp.weixin.qq.com 前言 今天和大家一起谈谈"网络",之前写的文章可能不太通俗易懂,有人就 ...

  4. 如果有人问你数据库的原理,看这篇文章。(超长预警)

    长文,相当的通透.以下为scrat进行总结后的删减版. 下面假定你已经知道时间复杂度 关系型数据库无处不在,而且种类繁多,从小巧实用的 SQLite 到强大的 Teradata .但很少有文章讲解数据 ...

  5. Python-Excel 零基础学习xlwings,看这篇文章就够了

    零基础学习xlwings,看这篇文章就够了 | 一起大数据-技术文章心得 (17bigdata.com) 1.xlwings是什么 2.xlwings安装更新与卸载 3.xlwings详细使用 4.案 ...

  6. i7处理器好吗_二手CPU值得买吗?购买二手CPU不想交智商税就看这篇文章

    二手CPU值得买吗?众所周知,不少装机用户可能因为预算的原因,可能会考虑二手硬件,理论上二手CPU无疑相比全新更加便宜,但是CPU这玩意真的有很多例外,有些二手CPU还真的没有全新划算,较老型号的in ...

  7. 万字心得,PMP学习考试那些事儿,看这篇文章就够了

    声明:文章为原创,首发于知乎,链接:万字长文!PMP考试那些事儿,看这篇文章就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/524966002 以下内 ...

  8. 斗鱼html5插件音画不同步,音画不同步在直播中怎么解决?看这篇文章就够了!...

    原标题:音画不同步在直播中怎么解决?看这篇文章就够了! 什么是音画不同步? 很容易判断,就是画面和声音不匹配. 为什么会音画不同步? 首先我们要明白一个概念,虽然人的肉眼很容易辨别音画是否同步的,但是 ...

  9. 上海nas服务器_想要自己搭建NAS服务器?看这篇文章,小白也能学会!(一)

    原标题:想要自己搭建NAS服务器?看这篇文章,小白也能学会!(一) NAS即网络附加存储(Network Attached Storage),通过网络提供数据访问服务. 本人不推荐自攒NAS,稳定性差 ...

最新文章

  1. demo17 clean-webpack-plugin (清除模式)
  2. EFMVC - ASP.NET MVC 3 and Entity Framework 4.1 Code First 项目介绍
  3. python内置数据结构教程_python课程第二周 内置数据结构——列表和元组
  4. 使用css的类名交集复合选择器
  5. DataGridRow的创建
  6. 安装用户debian7安装oracle11g
  7. 研究机构预计芯片短缺将导致全球轻型汽车今年减产502万辆
  8. Spring如何配置bean属性
  9. 2017年美国大学生数学建模竞赛E题O奖65123论文解读
  10. 怎么将PDF转换成Word?PDF转Word如何不乱码?
  11. vmware esxi6.5安装使用教程(图文安装)
  12. IELTS-writing exercise Expository_Text_18
  13. MATLAB中对tif格式栅格影像读取-保存
  14. toLower toUpper
  15. OSPF高等特性——Forwarding Address
  16. Android 实时滤镜 高斯模糊(带源码)
  17. MySQL数据类型----布尔型,时间型,枚举型的简单介绍
  18. 微信小程序开发之文件上传下载应用场景(附Demo源码)
  19. Delphi 2007 体验
  20. 【修炼七】团队建设-尊重

热门文章

  1. SAP Netweaver和Hybris Commerce启动后执行的默认操作
  2. why quantity change in item can cause CUMULAT_H changed as well
  3. Parent Equipment 和IBASE relationship创建时的检查逻辑
  4. No Authorization to generate extension field
  5. SAP WebClient UI view controller所有可用的属性列表
  6. SAP Spartacus Popover Component 显示与否的逻辑判定
  7. SAP Fiori架构一览
  8. SAP Marketing Cloud的技术架构
  9. 后台nodejs程序如何主动推送数据给浏览器
  10. msdn画圆弧函数_三角函数常识2020