PID算法详解及实例分析

这篇具有很好参考价值的文章主要介绍了PID算法详解及实例分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.PID算法入门

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

先看公式:
u ( t ) = K p ( e ( t ) + 1 T i ∫ 0 t e ( t ) d t + T d d e ( t ) d t ) 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)+Ti10te(t)dt+Tddtde(t))
如果公式看不懂,没关系,我们先往后面走,回头再分析公式。

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

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

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

K p = 0.5 K_p = 0.5 Kp=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,积分控制就是将历史误差累加起来再乘以积分常数,即
1 T i ∫ 0 t e ( t ) d t \frac{1}{T_i} \int_{0}^{t}e(t)dt Ti10te(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 ) = a 0 s 0 + a 1 s 1 + a 2 s 2 + ⋯ + a n − 1 s n − 1 = 0 , a 0 > 0 D(s) = a_0s^0 + a_1s^1 + a_2s^2 +\cdots + a_{n-1}s^{n-1} = 0, a_0 > 0 D(s)=a0s0+a1s1+a2s2++an1sn1=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文章来源地址https://www.toymoban.com/news/detail-812155.html

到了这里,关于PID算法详解及实例分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 深入理解PID控制算法:原理、举例及参数调试和选择方法

    PID控制算法的原理是基于负反馈控制理论的。当系统处于稳态时,PID算法通过不断测量系统的实际输出和期望输出之间的误差,并根据误差的大小来调整控制器的输出。PID算法可以通过三种不同的控制方式来实现这一目标: 比例控制(P控制):当系统的误差增大时,P控制将

    2024年02月16日
    浏览(9)
  • STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

    STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

    PID是什么,P,I,D的分别功能 你和PID调参大神之间,就差这篇文章! P(比例): 简单来说,P就是凉了加热水,热了加凉水。 比目标值小 ,我就 增加 一点, 比目标值大 ,我就 减小 一点。 (现在) P可能出现的问题: 1.P太小,达到目标值需要花费很长的时间,而且会有

    2024年02月03日
    浏览(20)
  • 【Linux系统进阶详解】Linux核心命令深度实战实现原理详解和每个命令使用场景以及实例分析

    在Linux系统中, find 、 xargs 、 sed 、 grep 、正则表达式和通配符是非常常用的命令和技巧。它们可以结合使用,实现更复杂的文件查找、过滤和操作。下面将详细介绍它们的实现原理和使用场景。 find命令 ``find`命令通过遍历指定目录及其子目录来查找符合条件的文件或目录。

    2024年02月08日
    浏览(17)
  • 【物联网】C语言实现PID算法:原理、例子和代码详解

    【物联网】C语言实现PID算法:原理、例子和代码详解

    PID(Proportional-Integral-Derivative)是一种常用的控制算法,广泛应用于工业控制系统中。本文将详细介绍PID算法的原理,并给出一个具体的例子和相应的C语言代码实现。 PID算法通过不断调整输出值,使得系统的实际值逐渐接近期望值。它由三个部分组成: 比例(P)、积分(

    2024年02月12日
    浏览(8)
  • 超维空间S2无人机使用说明书——55、代码详解:基础PID算法控制无人机的跟随代码详解

    超维空间S2无人机使用说明书——55、代码详解:基础PID算法控制无人机的跟随代码详解

    PID,即比例 Proportion、积分 Integral 和微分 Derivative 三个单词的缩写;比例积分微分控制,简称PID控制。 简单讲,根据给定值和实际输出值构成控制偏差,将偏差按比例、积分和微分通过线性组合构成控制量,对被控对象进行控制。 常规 PID 控制器作为一种线性控制器。 步骤

    2024年01月21日
    浏览(57)
  • 麦克纳姆轮PID控制原理

    麦克纳姆轮PID控制原理

    目录 前言 一、什么是麦克纳姆轮 二、运动原理 ​ 三、pid控制  一、什么是pid?  二、什么是串级PID? 三、麦克娜姆轮的控制思想 总结 目前很多大学生比赛里面经常都会出现麦克娜姆轮,并且麦克娜姆轮在工业上也应用挺广泛,例如物流搬小车。下面是我玩麦克娜姆轮的

    2024年02月02日
    浏览(25)
  • 目标检测算法之YOLOv5在乒乓球赛事中运动员行为分析领域的应用实例详解(基础版--上)

    目录 YOLOv5乒乓球赛事中运动员行为分析 优化措施 优化代码 继续优化 在乒乓球赛事中,YOLOv5可以应用于运动员行为分析,通过实时识别和追踪运动员的动作,帮助教练分析技术动作,或者为观众提供更丰富的观赛体验。下面是一个简单的应用实例和相关代码片段。 首先,需

    2024年02月22日
    浏览(86)
  • 9、基于51单片机PID算法温度控制系统设计(程序+Proteus仿真+原理图+PCB图+参考论文+开题报告+任务书等)

    9、基于51单片机PID算法温度控制系统设计(程序+Proteus仿真+原理图+PCB图+参考论文+开题报告+任务书等)

    目录 摘要 一、硬件方案 二、设计功能 三、成品实物图 四、原理图  五、PCB图 六、Proteus仿真  七、程序源码    资料包括:     随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,其中 数字温度计 就是一个典型

    2024年02月05日
    浏览(10)
  • PI控制算法与PID控制算法

    PI控制算法与PID控制算法

    PI(Proportional-Integral)控制算法 是一种常用的闭环控制策略,用于实现对系统的误差调节。PI控制器结合了比例控制(Proportional,P)和积分控制(Integral,I)两种控制方式。比例控制通过比例增益(Kp)将误差直接转换为控制输出,而积分控制通过积分增益(Ki)对误差进行积

    2024年02月14日
    浏览(8)
  • 自适应PID算法学习(01)——单神经元PID控制

    自适应PID算法学习(01)——单神经元PID控制

      单神经元含有n个输入,仅1个输出,每个输入端可记作 x i ( i = 1 , 2 , . . . n ) x_i (i=1,2,...n) x i ​ ( i = 1 , 2 , ... n ) ,若该神经元为多元组成网络中某一层(输入层/输出层/隐含层)其中的一个单元,记该神经元输出为 o j ( j = 1 , 2 , . . . ) o_j(j=1,2,...) o j ​ ( j = 1 , 2 , ... ) ;不

    2024年02月16日
    浏览(14)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包