目录

简介

PID实战简介

任务:控制机器车的轮胎达到目标转速。

恒定值控制器(BangBang)

P-Proportional 比例控制器(P)

I-Integral 积分控制器(PI)

D-Derivative 微分控制器(PID)

总结和反思


简介

网上不少关于PID控制的讲解,但是很多依然很抽象,或者只停留在理论层面上不够生动形象,所以自己花时间用Arduino写了一个简单的PID程序来理解+验证,并实现了两轮小车的轮子转速控制、转向控制以及巡线的PID控制。

该项目使用Visual Studio Code编写代码,Arduino Leonardo板子和 Pololu 3pi+ 32U4 五脏俱全小机器人。


PID实战简介

PID叫比例积分控制器,不理解的小伙伴会觉得很抽象,在这里我尝试通过实战让这种控制器更容易理解:我们将通过一个简单的小任务来一步步开发理解简单的PID控制器。

任务:控制机器车的轮胎达到目标转速。

已知:

  • 编码器转速- input。这里需要用到小车轮胎的编码器,但是这不是重点,我们只需要知道编码器是整个控制器的input,它将表示小车车轮的实时转速。
  • 代码 analogWrite(motorID, power); - output。该代码表示将power数值输出到指定硬件pin上运行,它将表示指定ID马达的功率大小。
  • 目标转速Target和差值Error,我们的控制器将根据差值确保车轮达到并维持在该值上。

未知:

  • 输出值u(t), t代表该时刻,t-1代表上一时刻,以此类推之后的(t)

现在就是非常直观简单的问题:根据 调整output使车轮达到Target转速。

恒定值控制器(BangBang)

最简单的方法就是转速小于Target时增大马达功率,转速大于Target时减小马达功率。增大减小值固定,然后我们就能很好的让车轮稳定在预计转速上了,但是它会在目标值附近疯狂摆动,因为每一次调整都是固定值,我们无法动态调整,差值Error大的时候多调一些,小的时候少调一些,所以我们引入P比例控制来解决这个问题。

P-Proportional 比例控制器(P)

P就是为了动态调整,差值Error大的时候多调一些,小的时候少调一些,所以我们直接使用Error带入控制器中,并加入Kp来调节其控制力度。

运行结果可以通过Ardunio的Serial Plotter直接观察到图像,不难看出比例控制效果更好了:

若比例增益Kp大,在相同误差量下,会有较大的输出,反应更为迅速,但若比例增益太大,会使系统不稳出现超调。相反的,若比例增益小,若在相同误差量下,其输出较小,因此控制器会不敏感,容易出现稳态误差

什么是稳态误差?

当轮子转速非常接近预期值时,我们得到的Error差值将会很小,这就导致马达给出的功率变化力度也会响应变小,当环境存在摩擦力等情况时,就会出现马达功率和摩擦力平衡的情况,即虽然控制器一直在告诉马达加点力,马达也确实照做了,但是由于平衡了摩擦,轮子转速无法再有所提高,于是便稳定在了一个还没有到达目标的尴尬境地,这就是为什么我们下一步将用到I-积分控制来避免这个问题

I-Integral 积分控制器(PI)

为了解决稳态误差的问题,我们引入了积分控制。简单理解就是,如果控制器长时间没有让设备达到预期值,I控制器将会不断积累误差并将误差累加到控制器的输出上,这样一来随着时间的积累,控制器的输出越来越大,直到新的大功率克服外界影响从而让机器达到预期值。

虽然I控制器缓解了稳态误差的问题,但又有一个新问题,即它容易超调(累加多了)。

如果Ki值太低,那么I部分控制器的效果将会不明显,需要很长时间才能把稳态误差掰回来;但是一旦提高Ki,那么又容易得到一个过大的累加值,导致PI控制器容易被累加过多的误差值“带偏”,冲出预期值,然后控制器重新纠正错误,但是又一次超调。最终造成实际值在期望值周围来回摆动,但是最终会趋于稳定。

D-Derivative 微分控制器(PID)

D 的出现有时为了缓解I的超调现象,通俗来说就是表示控制器输出值在该时间点的速度。如果PI控制器输出的值变化速度过大,那么相应地D部分就会减去部分值来抵消这一超调。

注意∆Error=此刻Error -上时刻Error ,∆Error总是和PI输出值正负相反。

这样一来一个合适的Kd值能够缓和PI的超调。

最终核心代码实现:

float PID_intergral = 0, PID_derivative = 0, PID_lastError = 0;unsigned long PID_Intergral_Timer = 0, PID_Derivative_Timer = 0, PID_Intergral_RecordDuration = 100, PID_Derivative_RecordDuration = 200;/** Set specific Motor to specific speed by using Motor_PID control method, to avoid state error accumulation from P control method and to avoid the derivative error accumulation from PI control method* @param motorID: find MotorID in GlobalVarables.h* @param targetVelocity: the target velocity* @param Kp: the proportion differential between the target velocity and the current velocity: y= Kp(targetVelocity - currentVelocity)+I(stateError)+D(derivativeError)* @param Ki: the proportion differential between the state error and the current velocity: y= Kp(targetVelocity - currentVelocity)+I(stateError)+D(derivativeError)* @param Kd: the proportion differential between the derivative error and the current velocity: y= Kp(targetVelocity - currentVelocity)+I(stateError)+D(derivativeError)*/void PID_ChangeSpeed_ToTarget(int motorID, float targetVelocity, float Kp, float Ki, float Kd){int LeftOrRight = setMotorLeftOrRight(motorID);//Angular_Velocity[0]表示左轮,Angular_Velocity[1]表示右轮float error = targetVelocity - Angular_Velocity[LeftOrRight];if ((millis() - PID_Intergral_Timer) >= PID_Intergral_RecordDuration) // caculate the Intergal error{// Serial.println("Timer: " + String(millis() - PI_Timer));PID_intergral += error * 0.01;PID_Intergral_Timer = millis();}if ((millis() - PID_Derivative_Timer) >= PID_Derivative_RecordDuration) // caculate the derivative error{// Serial.println("Timer: " + String(millis() - PI_Timer));PID_derivative = (error - PID_lastError) / PID_Derivative_RecordDuration;PID_lastError = error;PID_Derivative_Timer = millis();}//最终PID:,单独拿出来可直接构成P,PI,PID3种控制器Motor_Value[LeftOrRight] += Kp * error + Ki * PI_intergral + Kd * PID_derivative;//防止异常值Motor_Value[LeftOrRight] = constrain(Motor_Value[LeftOrRight], 0, 100);//这里调用需要最终控制的硬件函数:motor.SetSingleMotorPower(motorID, Motor_Value[LeftOrRight]);}

整个工程文件将会放在GitHub上:待补充

总结和反思

PID控制可以应用在许多控制问题,多半在大略调整参数后就有不错的效果,不过有些应用下可能反而会有差的效果,而且一般无法提供非常理想的控制结果。一个好的PID控制器需要大量的调试和实践验证,非常费时费力,而且一旦环境发生大的改变,当前PID控制器可能就不好使了。

BangBang控制器:它是一个简单的控制器。它有很高的精度,不需要太多的功能操作和记忆。它的逻辑简单明了。然而,一个严重的缺点是,它将产生许多振动,导致更多的问题(如对机器人的损害和增加误差)。这就需要更多的逻辑叠加来抑制振动,例如增加几层不同强度的 "如果 "判断来处理多种错误强度。如果所需的应用场景只追求确定的精度而不考虑其他问题,Bang-Bang控制器的成本最低。

P控制器:它比Bang-Bang控制器更平稳。P控制器的输出随着误差值的变化而变化,在某些情况下表现得更好。然而,它最大的问题是它的稳态误差可能相当大。当预期值接近时,P项的再反应变小,这通常发生在Kp的小值或显著的外部阻力影响情况下。然而,如果我们增加Kp的值,这种现象可以得到缓解,如图所示,但太高的Kp会导致系统不稳定。因此,P控制器符合应用场景,只需要高响应速度、低颠簸和低精度。

PI控制器。对于P控制器的大稳态误差问题,叠加积分响应,将一个周期内的误差值之和乘以一个正常数Ki。然而,简单的PI控制器将导致超调,输出将围绕期望值波动,因为系统不能消除冗余的修正。然而,由于正和负的积累相互克服,PI系统最终会稳定在设定值上,所以PI在一段时间后有一个非常准确的再响应。因此,PI控制器适用于需要高精度、低振动和接受某些超调和时间冗余的情况。

PID控制器:为了克服超调,应用了一个导数再响应。它计算误差的导数,并将其乘以一个正的常数Kd,这可以显著地抑制PI控制器的过冲现象。然而,当它突然抑制了积分控制器的过冲时,可能会产生最小量的颠簸。PID控制器整合了上述两个控制器的优点并对其进行了优化。因此,它具有低过冲、快速响应和高精确度。对于组合线任务,由于90度角的任务,P、PI和PID控制器的性能被不断增加的颠簸计数所降低;这是因为在做0-90度的任务时,它触发了车轮逆转的部分。PID的成本时间要调到一个预期的水平,可能不适合所有的情况。例如,在直线跟踪的直角任务中。

我们不敢否认,我们的算法还不够完美,可能需要进一步的研究和实验。此外,由于开发周期较长,它不适合于一些期限有限的项目。此外,在某些情况下,P或Bang-Bang控制器已经足够了。然而,有必要根据实际情况和许多实验来选择最合适的控制器。

PID控制 通俗理解和简单实践相关推荐

  1. PID控制的理解与具体实现

    PID控制的理解与具体实现 摘要 比例积分微分控制,简称PID控制,由于其 算法简单.***鲁棒性好***和 可靠性高,被广泛应用于工业过程控制,至今仍有 90% 左右的控制回路具有PID结构. 简单 ...

  2. 【自动控制理论(一)】对PID控制的理解

    PID公式 以上是离散PID计算公式,PID的连续和离散,以及离散中的位置和增量,原理上都是完全一样的.一般控制都是离散PID,而且离散的表达形式更加直观,这里只给出离散的形式. PID控制的理解 非 ...

  3. PID控制的理解与参数整定

    PID控制器的一般结构 当控制器为比例控制器(P)时,可以减少因扰动而引起的稳态误差,但不能将稳态误差减少到0,增加一项正比于误差的积分项(I)时,可以消除系统的稳态误差,但会影响系统的动态性能,可再 ...

  4. PID控制通俗解释与PID参数的整定方法--以温控系统为例

    PID是比例.积分.微分的简称,PID控制的难点不是编程,而是控制器的参数整定.参数整定的关键是正确地理解各参数的物理意义,PID控制的原理可以用人对炉温的手动控制来理解.阅读本文不需要高深的数学知识 ...

  5. 关于电机双闭环PID控制一些理解

    双闭环结构 目前网上流传的一些关于双闭环的资料有很多我觉得是不对或者不够清楚的,在这边分享一下自己的理解,希望大家也能指点一下. 双闭环的作用 串级控制系统是改善控制质量的有效方法之一,在过程控制中得 ...

  6. 主题模型(LDA)(一)--通俗理解与简单应用

    这篇文章主要给一些不太喜欢数学的朋友们的,其中基本没有用什么数学公式. 目录 直观理解主题模型 LDA的通俗定义 LDA分类原理 LDA的精髓 主题模型的简单应用-希拉里邮件门 1.直观理解主题模型 ...

  7. python装饰器的通俗理解_简单理解Python装饰器

    Python有大量强大又贴心的特性,如果要列个最受欢迎排行榜,那么装饰器绝对会在其中. 刚接触装饰器,会觉得代码不多却难以理解.其实装饰器的语法本身挺简单的,复杂是因为同时混杂了其它的概念.下面我们一 ...

  8. PID算法通俗理解,平衡车,倒立摆,适合不理解PID算法的人来看!

    先插句广告,本人QQ522414928,不熟悉PID算法的可以一起交流学习,随时在线(PID资料再我的另一篇博客里) 倒立摆资料连接↓ https://www.cnblogs.com/LiuXinyu ...

  9. oCPC实践录 | 随你千变万化,oCPC PID控制(2)

    在oCPC实践录 | 随你千变万化,oCPC PID控制(1)中我们分析了比例控制将实时误差考虑进来,具有最快的响应速度,但只有比例控制作用时,real_cpa会偏离given_cpa,产生余差,消除 ...

最新文章

  1. 【分块】#6281. 数列分块入门 5(区间开方,区间求和)
  2. jQuery 变量数字相加
  3. 将多个图片转换成PDF文件-img2pdf
  4. 【桌面虚拟化】之五PCoIP
  5. 使用VSCode写Python代码的推荐安装的插件
  6. android qq 进程保活,Android保活从入门到放弃:乖乖引导用户加白名单吧(附7大机型加白示例)...
  7. wordpress html音乐,WordPress引用百度Ting音乐方法
  8. 使用镜像源安装EASY_INSTALL和PIP教程
  9. Pointcut is not well-formed: expecting #39;name pattern#39; at character position 36
  10. Python3 学习系列 丨 博客目录索引
  11. hashmap value占用空间大小_java-测量和监视大型HashMap的大小
  12. 用户登录提交前,密码加密传输
  13. js change事件 获取新值和旧值_前端总结(JS篇)
  14. 华为云专线接入方案介绍
  15. python下面的代码_求下面python代码的差别。
  16. 找呀志_通过开源框架引AsyncHttpClient处理get/post要求
  17. 开启Accessibility的快捷方式-3次home键或者侧边键
  18. 基于Python的DELMIA二次开发(三):人体建模
  19. Unity如何调用安卓手机摄像头实现拍照和录像
  20. 项目管理过程4W1H

热门文章

  1. ansys workbench17.0 lsdyna模块设置时间步长
  2. 应用程序迁移_加速绿色IT-关于应用程序迁移和重新托管的实用指南
  3. 图像处理中的用于消除高斯噪声的加法运算
  4. 地狱模式的居转户记录05
  5. K8S系列:Pod 的恢复策略restartPolicy
  6. 教你如何打造一个适合学生党的学习型iPad
  7. ThinkPHP5.0之PHPmailer发送邮箱(qq、163)
  8. 华为云开发者官网首页焕新升级,赋能开发者云上成长
  9. 机器学习 线性回归算法_探索机器学习算法简单线性回归
  10. Linux中如何切换中文英文