历史上的今天
返回首页

历史上的今天

今天是:2024年10月28日(星期一)

正在发生

2020年10月28日 | pid算法讲解

2020-10-28 来源:51hei

总所周知,PID算法是个很经典的东西。而做自平衡小车,飞行器PID是一个必须翻过的坎。因此本节我们来好好讲解一下PID,根据我在学习中的体会,力求通俗易懂。并举出PID的形象例子来帮助理解PID。

一、首先介绍一下PID名字的由来:

P:Proportion(比例),就是输入偏差乘以一个常数。

I  :Integral(积分),就是对输入偏差进行积分运算。

D:Derivative(微分),对输入偏差进行微分运算。

注:输入偏差=读出的被控制对象的值-设定值。比如说我要把温度控制在26度,但是现在我从温度传感器上读出温度为28度。则这个26度就是”设定值“,28度就是“读出的被控制对象的值”。然后来看一下,这三个元素对PID算法的作用,了解一下即可,不懂不用勉强。

P,打个比方,如果现在的输出是1,目标输出是100,那么P的作用是以最快的速度达到100,把P理解为一个系数即可;而I呢?大家学过高数的,0的积分才能是一个常数,I就是使误差为0而起调和作用;D呢?大家都知道微分是求导数,导数代表切线是吧,切线的方向就是最快到至高点的方向。这样理解,最快获得最优解,那么微分就是加快调节过程的作用了。


二、然后要知道PID算法具体分两种:一种是位置式的 ,一种是增量式的。在小车里一般用增量式,为什么呢?位置式PID的输出与过去的所有状态有关,计算时要对e(每一次的控制误差)进行累加,这个计算量非常大,而明显没有必要。而且小车的PID控制器的输出并不是绝对数值,而是一个△,代表增多少,减多少。换句话说,通过增量PID算法,每次输出是PWM要增加多少或者减小多少,而不是PWM的实际值。所以明白增量式PID就行了。

三、接着讲PID参数的整定,也就是PID公式中,那几个常数系数Kp,Ti,Td等是怎么被确定下来然后带入PID算法中的。如果要运用PID,则PID参数是必须由自己调出来适合自己的项目的。通常四旋翼,自平衡车的参数都是由自己一个调节出来的,这是一个繁琐的过程。本次我们可以不管,关于PID参数怎么确定的,网上有很多经验可以借鉴。比如那个经典的经验试凑口诀:

                          参数整定找最佳, 从小到大顺序查。

                          先是比例后积分, 最后再把微分加。

                          曲线振荡很频繁, 比例度盘要放大。

                          曲线漂浮绕大弯, 比例度盘往小扳。

                          曲线偏离回复慢, 积分时间往下降。

                          曲线波动周期长, 积分时间再加长。

                          曲线振荡频率快, 先把微分降下来。

                          动差大来波动慢, 微分时间应加长。

                          理想曲线两个波, 前高后低四比一。

                          一看二调多分析, 调节质量不会低。


四、接下来我们用例子来辅助我们把常用的PID模型讲解了。(PID控制并不一定要三者都出现,也可以只是PI、PD控制,关键决定于控制的对象。)(下面的内容只是介绍一下PID模型,可以不看,对理解PID没什么用)

例子:我们要控制一个人,让他一PID的控制方式来行走110步后停下来。

1)P比例控制,就是让他按照一定的比例走,然后停下。比如比例系数为108,则走一次就走了108步,然后就不走了。

说明:P比例控制是一种最简单的控制方式,控制器的输出与输入误差信号成比例关系。但是仅有比例控制时系统输出存在稳态误差。比如上面的只能走到108,无论怎样都走不到110。

2)PI积分控制,就是按照一定的步伐走到112步然后回头接着走,走到108步位置时,然后又回头向110步位置走。在110位置处来回晃荡几次,最后停在110步的位置。说明:在积分I控制中,控制器的输出与输入误差信号的积分成正比关系。对一个自动控制系统来说,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统。为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差的影响取决于时间的积分,随着时间的增加,积分项会增大。这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大,从而使稳态误差进一步减小,直到等于0。因此,比例+积分(PI)控制器可以使系统在进入稳态后无稳态误差。

3)PD微分控制,就是按照一定的步伐走到一百零几步后,再慢慢地走向110步的位置靠近,如果最后能精确停在110步的位置,就是无静差控制;如果停在110步附近(如109步或111步位置),就是有静差控制。

说明:在微分控制D中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳,原因是存在较大惯性组件(环节)或滞后组件,具有抑制误差的作用,其变化总是落后于误差的变化。解决的办法是使抑制误差作用的变化“超前”,即在误差接近于零时,抑制误差的作用就应该是零。这就是说,在控制器中仅引入“比例P”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势。这样,具有比例+微分的控制器就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。所以对有较大惯性或滞后的被控对象,比例P+微分D(PD)控制器能改善系统在调节过程中的动态特性。


五、用小明来说明PID:

小明接到这样一个任务:有一个水缸有点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水。 小明接到任务后就一直守在水缸旁边,时间长就觉得无聊,就跑到房里看小说了,每30分钟来检查一次水面高度。水漏得太快,每次小明来检查时,水都快漏完了,离要求的高度相差很远,小明改为每3分钟来检查一次,结果每次来水都没怎么漏,不需要加水,来得太频繁做的是无用功。几次试验后,确定每10分钟来检查一次。这个检查时间就称为采样周期。 开始小明用瓢加水,水龙头离水缸有十几米的距离,经常要跑好几趟才加够水,于是小明又改为用桶加,一加就是一桶,跑的次数少了,加水的速度也快了,但好几次将缸给加溢出了,不小心弄湿了几次鞋,小明又动脑筋,我不用瓢也不用桶,老子用盆,几次下来,发现刚刚好,不用跑太多次,也不会让水溢出。这个加水工具的大小就称为比例系数。

小明又发现水虽然不会加过量溢出了,有时会高过要求位置比较多,还是有打湿鞋的危险。他又想了个办法,在水缸上装一个漏斗,每次加水不直接倒进水缸,而是倒进漏斗让它慢慢加。这样溢出的问题解决了,但加水的速度又慢了,有时还赶不上漏水的速度。于是他试着变换不同大小口径的漏斗来控制加水的速度,最后终于找到了满意的漏斗。漏斗的时间就称为积分时间。

小明终于喘了一口,但任务的要求突然严了,水位控制的及时性要求大大提高,一旦水位过低,必须立即将水加到要求位置,而且不能高出太多,否则不给工钱。小明又为难了!于是他又开努脑筋,终于让它想到一个办法,常放一盆备用水在旁边,一发现水位低了,不经过漏斗就是一盆水下去,这样及时性是保证了,但水位有时会高多了。他又在要求水面位置上面一点将水缸要求的水平面处凿一孔,再接一根管子到下面的备用桶里这样多出的水会从上面的孔里漏出来。这个水漏出的快慢就称为微分时间。


六、在代码中理解PID:(好好看注释,很好理解的。注意结合下面PID的公式)

首先看PID的增量型公式:

PID=Uk+KP*【E(k)-E(k-1)】+KI*E(k)+KD*【E(k)-2E(k-1)+E(k-2)】

在单片机中运用PID,出于速度和RAM的考虑,一般不用浮点数,这里以整型变量为例来讲述PID在单片机中的运用。由于是用整型来做的,所以不是很精确。但是对于一般的场合来说,这个精度也够了,关于系数和温度在程序中都放大了10倍,所以精度不是很高,但是大部分的场合都够了,若不够,可以再放大10倍或者100倍处理,不超出整个数据类型的范围就可以了。一下程序包括PID计算和输出两部分。当偏差>10度时全速加热,偏差在10度以内时为PID计算输出。

程序说明:下面的程序,先看main函数。可知在对定时器0初始化后就一直在执行PID_Output()函数。在PID_Output()函数中先用iTemp变量来得到PID运算的结果,来决定是启动加热丝加热还是不启动加热丝。下面的if语句结合定时器来决定PID算法多久执行一次。PID_Operation()函数看似很复杂,其实就一直在做一件事:根据提供的数据,用PID公式把最终的PID值算出来。

推荐阅读

史海拾趣

虹冠电子(Champion)公司的发展小趣事

虹冠电子始终秉持着节能环保的理念,将这一理念融入到产品研发和生产过程中。公司推出的电源管理IC产品,不仅具有高效能、低能耗的特点,还具备类零电压切换PFC与PWM技术,进一步提高了电源的使用效率。虹冠电子的产品广泛应用于个人计算机、云端运算服务器、LED显示屏等领域,为全球节能减排事业做出了积极贡献。

Consolidated Wire公司的发展小趣事

在电子行业的早期,Consolidated Wire公司以其出色的技术研发能力崭露头角。公司投入大量资源研发新型导电材料,成功推出了一种具有更高导电性能和更低电阻的新型线材。这一技术突破不仅提升了电子设备的性能,还降低了能耗,赢得了市场的广泛认可。随着新型线材的普及,Consolidated Wire公司的业务规模迅速扩大,逐渐在电子线材市场占据了领先地位。

B&F Fastener Supply公司的发展小趣事

B&F Fastener Supply公司在上世纪末成立之初,就瞄准了快速发展的电子行业,意识到紧固件和电子元器件的供应将成为行业发展的关键。公司迅速调整战略,开始专注于电子工业用紧固件的研发和销售。通过与多家电子制造厂商建立合作关系,B&F逐渐在电子紧固件市场占据了一席之地。

Amulet Technologies公司的发展小趣事

凭借优质的产品和服务,B&F Fastener Supply公司逐渐赢得了大型电子厂商的青睐。多家知名电子企业选择与B&F建立长期合作关系,将其作为紧固件和电子元器件的主要供应商。这不仅为B&F带来了稳定的订单和收入来源,还进一步提升了公司在电子行业的地位和影响力。

博林(BL)公司的发展小趣事

博林公司自创立以来,一直致力于电子行业的技术创新。公司拥有一支专业的研发团队,不断投入巨资进行技术研发和创新。在某一时期,博林公司成功开发出了一款具有颠覆性的电子产品,凭借其卓越的性能和独特的设计,迅速在市场上获得了广泛认可。这款产品的成功推出,不仅为博林公司带来了巨大的经济效益,也进一步巩固了其在电子行业的领导地位。

Essentra Components公司的发展小趣事

Essentra Components公司一直将客户服务放在首位,通过提供优质的售前咨询、售中支持和售后服务,赢得了客户的广泛赞誉。公司不仅为客户提供了丰富的产品选择,还根据客户的具体需求提供定制化的解决方案。此外,公司还建立了完善的物流配送体系,确保产品能够及时、准确地送达客户手中。这些努力使得Essentra Components在客户中树立了良好的口碑,为公司的发展奠定了坚实的基础。

问答坊 | AI 解惑

全国大学生电子设计竞赛历年题目(1994-2003)

本帖最后由 paulhyde 于 2014-9-15 09:24 编辑 好东西,可以参考一下。  …

查看全部问答>

想找个熟悉LPC1000系列的朋友帮忙~~

正在做LPC1111+显卡的开发板,想找个熟悉LPC1000系列的朋友帮忙。 希望会SPI的兄弟可以帮忙。…

查看全部问答>

LPC1114的Flash读写操作问题及解决办法

使用LPC1114的Flash时遇到些问题,特向各位请教。   (1)LPC1114的Flash是不是每次读写最少得256字节,而不可以一个字节一个字节的进行读写操作? (2)我现在想把一个数组(比较小)的数据随时存储到片内Flash中,并且可以随时读取,是 ...…

查看全部问答>

文件输出,输入的问题

用CreateFile创建文件,并用WriteFile向文件中写入TCHAR字符,但为什么用ReadFile读取内容并显示到listbox中无法实现。…

查看全部问答>

如何在编程实现ip与mac绑定

如题,板子上不支持arp -s命令,可否编一个程序转成2进制烧写进板子里运行~px255的板子~怎么实现呢,拜求各位走过路过的大侠~~…

查看全部问答>

请教一个zigbee的问题?

我刚接触zigbee,正研究协议栈程序(cc2430)。我发现这样的一个问题:      当一个rfd节点申请加入corde节点时,应该在corder节点处有判断PANID(网络号)是否相同,如果相同就可以加入,但是在协议栈corer源程序里不论nwk层,ma ...…

查看全部问答>

如何在WINDOWS平台下仿潜入式环境?

大家好!    由于金钱的问题,没有条件买ARM处理器及相应的环境,看书而不练习,导致我看了就忘了,请问有没有在windows下模拟arm环境及编程的,让我能够熟悉一下ARM的命令及编程?还有我想学windows ce,但是还是只有一台PC机,其他什 ...…

查看全部问答>

学3G,不知道大家能给点建议不?我在上海,交大昂立3G学院如何?

大家好,我是今年刚毕业的一名学生,现在已经处于失业状态了,对找工作已经失去信心了,在校的时候就了解了一点3G的东西,所以现在想要去学个3G开发技术。我在各大网站上了解下来说交大昂立3G学院的老师还有就业方面都比较不错,不知道有在里面学习 ...…

查看全部问答>

msp430f2618驱动ocmj15x20d

我怎么弄液晶屏都没什么反应。。。。求大家给点建议…

查看全部问答>

ATMEGA16A,用循环制作数字时钟程序

#include \"iom16v.h\" #include \"macros.h\" #define uchar unsigned char #define uint unsigned int uint Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,}; void delay(uint ms) {    uint i,j;   ...…

查看全部问答>