1.PID算法入门

PID算法算是控制领域最经典,最重要,也是最实用的算法了。所谓的PID,指的是proportion,integration,differentiation,比例,积分,微分。
因此,PID是结合了比例积分微分三个模块于一身的控制算法。

先看公式:
u(t)=Kp(e(t)+1Ti∫0te(t)dt+Tdde(t)dt)u(t) = K_p\left(e(t) + \frac{1}{T_i} \int_{0}^{t}e(t)dt + T_d \frac{de(t)}{dt}\right) u(t)=Kp​(e(t)+Ti​1​∫0t​e(t)dt+Td​dtde(t)​)
如果公式看不懂,没关系,我们先往后面走,回头再分析公式。

2.通过实例对PID进行理解

为了更好了解PID算法,我们选取一个例子进行分析,这个例子在很多地方被使用,我们也选过来作为例子进行分析。

小明现在有一个任务:有个水桶,水桶的水位高度需要时刻保持1m,目前水桶的水是0.2m,小命采用比例的方式加水(即P),即每次测量与1m 的误差,并加入与误差成比例的水量。

设Kp=0.5K_p = 0.5Kp​=0.5
第一次的误差:1-0.2=0.8,于是加入的水为0.50.8=0.4,此时桶内水0.6。
第二次的误差:1-0.6=0.4,于是加入的水为0.5
0.6=0.3,此时桶内水0.9。
第三次的误差:1-0.9=0.1,于是加入的水为0.5*0.1=0.05,此时桶内水0.95。
以此类推,不断加下去,通过P控制就可以将水加满到1,完美!

3.积分环节

上面的比例环节,貌似就可以解决问题。但是实际中没有这么理想的情况,比如水桶有个洞,每次加水都会流出0.1m。这个时候就比较接近真实情况了,比如系统的各种摩擦力,阻力什么的。

如果我们还是用上面的比例控制(P环节)
第一次的误差:1-0.2=0.8,于是加入的水为0.50.8=0.4,此时桶内水0.6-0.1=0.5。
第二次的误差:1-0.5=0.5,于是加入的水为0.5
0.5=0.25,此时桶内水0。5+0.25-0.1=0.65。
第三次的误差:1-0.65=0.35,于是加入的水为0.5*0.35=0.175,此时桶内水0.65+0.175-0.1=0.725。

我们多算几次以后发现,水位最终会在0.8m处稳定。如果反推一下,我们也很好理解:当误差为0.2m时,每次加水量为0.1,漏掉的也是0.1,正好加的等于漏掉的。

这就是系统稳定误差的概念。

关于系统稳态误差,引用胡寿松老爷子自动控制原理一书中的描述:

控制系统的稳态误差,是系统控制准确度的一种度量,通常称为稳态性能。在控制系统设计中,稳态误差是一项重要的技术指标,对于一个实际的控制系统,由于系统结构,输入作用的类型(控制量或扰动量) ,输入函数的形式(阶跃,斜坡或加速度)不同,控制系统的稳态输出不可能在任何情况下与输入量一致,也不可能在任何形式的扰动作用下都能准确地恢复到平衡位置。此外,控制系统中不可避免的存在摩擦,间隙,不灵敏区,零位输出等非线性因素,都会造成附加稳态误差。因此,控制系统的稳态误差是不可避免的,控制系统设计的任务之一,就是尽量减小系统的稳态误差,或者使稳态误差小于某一容许值。显然,只有当系统稳定时,研究稳态误差才有意义。对于不稳定系统而言,根本不存在研究稳态误差的可能性。

为了消除稳态误差,我们的做法就是引入积分项,就是PID中的I,积分控制就是将历史误差累加起来再乘以积分常数,即
1Ti∫0te(t)dt\frac{1}{T_i} \int_{0}^{t}e(t)dtTi​1​∫0t​e(t)dt

前面的例子,我们还是设置为Kp=0.5,Ki= 0.3。
第一次,误差为0.8, 比例部分 Kp0.8=0.4, 积分部分 Ki(e(1))= 0.24,加入水量u为0.4+0.24=0.64. 最终水位0.2+0.64-0.1= 0.74m
第二次,误差为0.26,比例部分Kp0.26=0.13,积分部分Kp*(e(1)+e(2))= 0.318,加入水量u为 0.13+0.318=0.448.最终水位 0.74+0.448-0.1=1.088m。

如果这样一直下去,最终会到达一个稳定值。

4.微分环节

前面我们已经分析了,积分环节能消除稳态误差,但是积分环境又会带来另外一个问题:积分环节会带来超调量。而且随着Ki值的变大,超调量也会边大。
所谓的超调量,是指峰值超过终止的比例。从直观上来说,超调量对应的对就是波峰位置。波峰越高,超调量越大。

为了消减超调,我们引入微分运算,也就PID中的D。
上面的例子,我们假设Kp=0.5,Ki= 0.5,Kd=0.3。

第一次: 误差为0.8, 比例部分 Kp0.8=0.4, 积分部分 Ki(e(1))= 0.24,微分部分 =0 (因为没加水前水位差就是0.8) 加入水量u为0.4+0.4=0.8. 最终水位0.2+0.8-0.1= 0.9m

第二次: 误差为0.1,比例部分Kp0.1=0.5,积分部分Kp(e(1)+e(2))= 0.45,微分部分为Kd*(e(2)-e(1))加入水量u为 0.5+0.45-0.21=0.29.最终水位 0.9+0.29-0.1=1.09m

最后我们计算发现,引入微分运算以后,超调量比之前有减小。

5.PID各模块小结

比例部分P:
比例环节的作用是对偏差瞬间作出反应。偏差一旦产生控制器立即产生控制作用, 使控制量向减少偏差的方向变化。 控制作用的强弱取决于比例系数Kp, 比例系数Kp越大,控制作用越强, 则过渡过程越快, 控制过程的静态偏差也就越小; 但是Kp越大,也越容易产生振荡, 破坏系统的稳定性。 故而, 比例系数Kp选择必须恰当, 才能过渡时间少, 静差小而又稳定的效果。

积分部分I:
从积分部分的数学表达式可以知道, 只要存在偏差, 则它的控制作用就不断的增加; 只有在偏差e(t)=0时, 它的积分才能是一个常数,控制作用才是一个不会增加的常数。 可见,积分部分可以消除系统的偏差。
积分环节的调节作用虽然会消除静态误差,但也会降低系统的响应速度,增加系统的超调量。积分常数Ti越大,积分的积累作用越弱,这时系统在过渡时不会产生振荡; 但是增大积分常数Ti会减慢静态误差的消除过程,消除偏差所需的时间也较长, 但可以减少超调量,提高系统的稳定性。

微分部分D:
实际的控制系统除了希望消除静态误差外,还要求加快调节过程。在偏差出现的瞬间,或在偏差变化的瞬间, 不但要对偏差量做出立即响应(比例环节的作用), 而且要根据偏差的变化趋势预先给出适当的纠正。为了实现这一作用,可在 PI 控制器的基础上加入微分环节,形成 PID 控制器。
微分环节的作用使阻止偏差的变化。它是根据偏差的变化趋势(变化速度)进行控制。偏差变化的越快,微分控制器的输出就越大,并能在偏差值变大之前进行修正。微分作用的引入, 将有助于减小超调量, 克服振荡, 使系统趋于稳定, 特别对髙阶系统非常有利, 它加快了系统的跟踪速度。但微分的作用对输入信号的噪声很敏感,对那些噪声较大的系统一般不用微分, 或在微分起作用之前先对输入信号进行滤波。

6.系统稳定性判断

前面提到了系统稳定性的问题,顺便我们复习一下系统稳定性判据。
同样来自胡寿松老爷子自动控制原理一书

线性系统稳定的充分必要条件是:闭环系统特征方程的所有跟具有负实部,或者说,闭环传递函数的极点均位于s左半平面。

劳斯-赫尔维茨稳定性判据:
根据稳定的充分必要条件判别线性系统的稳定性,假设线性系统的特征方程为
D(s)=a0s0+a1s1+a2s2+⋯+an−1sn−1=0,a0>0D(s) = a_0s^0 + a_1s^1 + a_2s^2 +\cdots + a_{n-1}s^{n-1} = 0, a_0 > 0 D(s)=a0​s0+a1​s1+a2​s2+⋯+an−1​sn−1=0,a0​>0

即线性系统稳定的必要条件是,在特征方程中,各项系数均为正数。

7.PID的简单实例实现

假设我们的采样间隔为T,那么在第K个T时刻:
偏差err(K) = rin(K) - rout(K)
积分环节用加和的方式表示, err(1) + err(2) + … + err(K)
微分的环节则用斜率的形式表示, [err(K) - err(K-1)] / T

#include <iostream>using namespace std;struct _pid{float SetSpeed; //定义设定值float ActualSpeed; //定义实际值float err; //定义偏差值float err_last; //定义上一个偏差值float Kp,Ki,Kd; //定义比例、积分、微分系数float voltage; //定义电压值(控制执行器的变量)float integral; //定义积分值
}pid;void PID_init(){printf("PID_init begin \n");pid.SetSpeed=0.0;pid.ActualSpeed=0.0;pid.err=0.0;pid.err_last=0.0;pid.voltage=0.0;pid.integral=0.0;pid.Kp=0.2;pid.Ki=0.015;pid.Kd=0.2;printf("PID_init end \n");
}float PID_realize(float speed){pid.SetSpeed=speed;pid.err=pid.SetSpeed-pid.ActualSpeed;pid.integral+=pid.err;pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);pid.err_last=pid.err;pid.ActualSpeed=pid.voltage*1.0;return pid.ActualSpeed;
}int run_pid(){printf("System begin \n");PID_init();int count=0;while(count<1000) {float actual_speed=PID_realize(200.0);printf("count is: %d, actual_speed is: %f\n", count, actual_speed);count++;}return 0;
}int main(int argc, char const *argv[])
{run_pid();return 0;
}

代码的最终输出为

System begin
PID_init begin
PID_init end
count is: 0, actual_speed is: 83.000000
count is: 1, actual_speed is: 11.554998
count is: 2, actual_speed is: 59.559681
count is: 3, actual_speed is: 28.175407
count is: 4, actual_speed is: 52.907417
count is: 5, actual_speed is: 38.944157
...
count is: 996, actual_speed is: 199.999435
count is: 997, actual_speed is: 199.999451
count is: 998, actual_speed is: 199.999466
count is: 999, actual_speed is: 199.999481

上述代码,模拟的就是通过PID算法,将速度最终控制在200的场景。

参考文献

1.https://zhuanlan.zhihu.com/p/74131690
2.https://www.cxyzjd.com/article/weibo1230123/80812211
3.https://zhuanlan.zhihu.com/p/41425508

PID算法详解及实例分析相关推荐

  1. PID算法详解(精华知识汇总)

    注:本篇文章针对PID算法的类型做了较为全面的整理和归纳,有的类型理解较为困难,但是希望读者能有所了解和印象,不懂的地方可以通过查阅相关书籍和网站自行领悟. 文章末尾附有PID相关资料书籍和知识总结的 ...

  2. java list用法_Java List 用法详解及实例分析

    Java List 用法详解及实例分析 Java中可变数组的原理就是不断的创建新的数组,将原数组加到新的数组中,下文对Java List用法做了详解. List:元素是有序的(怎么存的就怎么取出来,顺 ...

  3. MySQL——存储过程详解及实例分析

    目录 一.储存过程简介 1.什么是存储过程 2.存储过程优缺点 3.存储过程入门程序 4.在idea中如何调用储存过程? 二.存储过程编程 1.存储过程的变量 2.存储过程中的参数 3.选择结构if ...

  4. ICMP详解和实例分析

    ICMP是网际报文控制协议,它是一个对IP协议的补充协议.允许主机或路由器报告差错情况和异常状况. 一.ICMP报文格式和各个字段的含义 ICMP报文的格式如下: ICMP协议封装在ip协议中,ICM ...

  5. mmap函数的用法详解及实例分析

    1.mmap函数是一个比较神奇的函数,它可以把文件映射到进程的虚拟内存空间.通过对这段内存的读取和修改,可以实现对文件的读取和修改,而不需要用read和write函数.如下图所示,为mmap实现原理的 ...

  6. select函数详解及实例分析

    Select函数在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv或recvfrom这样的阻塞 ...

  7. PID算法详解(1)

    根据偏差的比例(P).积分(I).微分(D)进行控制(简称PID控制),是 控制系统中应用最为广泛的一种控制规律. PID调节器之所以经久不衰,主要有以下优点: (1)技术成熟,通用性强 (2)原理简 ...

  8. RTMP协议详解及实例分析

    1.简介 RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiple ...

  9. C# 事件详解附实例分析

    一.定义 事件是两个对象间发布消息和响应后处理消息的过程,通过委托类型来实现的. 事件的机制被称为发布-订阅机制,其算法过程为:首先定义一个委托类型,然后在发布者类中声明一个event事件,同时此类中 ...

  10. python中flush什么意思_python flush()定义及作用详解(实例分析)

    今天这篇文章我们来了解一下python之中的flush,在进入文章之前我们首先要知道我们要学的是什么东西,今天讲的是pythonflush,了解什么是flush,并且知道flash什么意思.这些东西我 ...

最新文章

  1. 简单介绍一下solr
  2. linux6.5dns装什么,CentOS6.5安装DNS服务
  3. 工作242:关于第二个git仓库提交代码
  4. Redis命令总结及其基础知识讲述
  5. 数据科学和人工智能技术笔记 一、向量、矩阵和数组
  6. vs多项目模板及add-in开发
  7. 设计模式 ( 十九) 中介者模式
  8. 自然语言处理--基于规则(AIML)的问答机器人
  9. linux tomcat war解压吗,Tomcat 何时解压war包
  10. 幽暗镰刀:隐私安全下的收割者们
  11. Mac电脑网速慢的问题之一(硬件:MTU)
  12. 淘宝API item_history_price - 获取商品历史价格信息
  13. libguestfs java_rhel7.0(libguestfs) 挂载windows虚机镜像
  14. 为何需要物联网设备管理平台
  15. Android删除系统的WIFI功能
  16. matlab如何画波特图,matlab画波特图
  17. Altium Designer布局布线时元器件移动
  18. uni-app 打开外部网页地址 web url
  19. 【计量经济学导论】02. 多元回归模型
  20. 阿铭Linux培训课视频第四期

热门文章

  1. 计算机控制系统电梯控制,计算机控制系统实验报告1.doc
  2. 虚拟化服务器杀毒软件,虚拟机需要安装杀毒软件吗
  3. web 应用程序与桌面应用程序的区别与优缺点
  4. H5页面调起手机打电话功能
  5. 移动 app 测试工具 bugtags
  6. CDA LEVEL I 数据分析认证考试模拟题库(一)
  7. MATLAB绘制散点图
  8. 超酷!Python 绘制属于你的世界地图
  9. AIDA64内存与缓存测试过了算稳定吗_KLEVV BLOT XR DDR4内存:锐龙平台兼容性测试
  10. LayoutLM: Pre-training of Text and Layout for Document Image Understanding