算法原理

PID控制器即比例(proportion)积分(integral)微分(differential)控制器, 该算法以误差作为输入量,经过对比例,积分,微分三项加权求和之后得到输出量。PID控制器是非常经典的控制器,简单易懂,不需要精确的系统模型就可以使用,应用非常广泛。

关于PID的介绍资料网上有很多,也有很多讲的通俗易懂的,比如

https://zhuanlan.zhihu.com/p/39573490

我这里介绍算法原理时除了定性分析之外,还会涉及到一部分理论知识,需要一定的《自动控制原理》《信号与系统》的专业知识,不过不会过于深入,都是简单的入门级知识。

我们先说一下为什么需要闭环控制,以控制一个电机的转速为例。在实际控制之前,我们可能会想当然的觉得,只要我给电机一个100转/min的转速期望,它就会乖乖输出100转/min的结果,但是实际情况呢?电机空载的情况下它或许还能够达到期望的转速,但是假如给电机上加了一个10斤的负载呢?它的转速可能就掉到80转/min去了,再继续增加负载,转速可能会继续下降。

再举一个例子,做过智能小车之类的同学应该会深有体会,单片机输出同样脉宽PWM给电机,但是随着电源电压,轮子松紧等因素的干扰,几乎每次电机最后输出的实际转速都会变化。

如何解决这个问题呢?其实我们只需要根据电机的实际转速来改变我们的给电机的输入量就可以了。比如同样是希望电机挂了10斤负载的情况下能够输出100转/min,由于给电机的输入对应于空载100转/min时,实际输出只有80转/min,可以考虑将输入量提高到对应于空载时120转/min,这时电机的实际输出或许就能够达到100转/min。同样的,如果负载继续增加,我们就进一步增大输入量,以控制实际输出保持在100转/min。

Robomaster的大部分电机都是带霍尔传感器,可以反馈转速/位置信息的,因此都可以通过闭环的方式进行控制。

然后我们介绍一下什么是典型的反馈控制器(该模型可以在matlab的simulink中打开):

一般我们会将受控对象的反馈(measured output)与我们的期望(reference)输入相减,得到一个误差值(error),然后以该误差作为输入量给控制器(controller),控制器最后输出结果(control input)直接传给受控对象(plant)。

依然是结合我们之前的电机的例子,这里的期望即我们的期望电机转速100转/min,反馈即我们通过霍尔传感器获得的电机实际转速80转/min,我们将他们做差得到误差,然后将其送入控制器中,控制器根据内部的算法得到结果,算出120转/min的期望给电机,就能够使电机的实际转速恰好等于期望

由于误差控制器输出都是时变的,我们分别假设其为err(t)U(t),这样我们就可以引出连续型PID的公式

\[U(t) = K_p * err(t) + K_i * \int{{err(t)}dt} + K_d * \frac{{\rm d}err(t)}{{\rm d}t}
\]

即对err(t)分别进行比例积分微分运算之后进行加权求和得到输出U(t)。为什么会同时需要这三项呢?我们来定性的分析一下每一项的含义——

首先我们假设KiKd两个系数均为0,则公式变化为

\[U(t) = K_p * err(t)
\]

即输出量随误差大小等比例变化,那么这样得到的输出结果会是什么样的呢?(蓝线为输出,黄线为期望,紫线为误差)

我们会发现输出出现了两个问题——第一,出现了超调,第二,出现了静差

超调即实际输出量出现了一个大于期望值的尖峰,超调可能会引发很严重的问题——系统不稳定,这种情况往往出现在比例项过大的情况。一个超调量引发另一个超调,导致系统处于持续的震荡状态中,比如下图这种情况——

体现在实际的机器人中就会是“嘿,你的云台疯了”或者“嘿,你的底盘疯了”,你会看见自己的机器人的云台抽风一般的抽搐点头,底盘如同脱缰的野马肆意奔驰.......(所以为了安全,一定要给输出添加限幅!!被云台打到或者被底盘撞到真的很疼!!)

静差即输出稳定在一个小于期望的值,引发这一点的问题之一是比例系数过小。因为我们知道输出是和误差成正比例的,如果比例系数小了,则输出自然也会小。适当的增大比例系数可以改善这一问题,但是永远不可能彻底消除静差,因为如果真的达到了输出等于期望,也就是err(t)等于0的情况,则输出U(t)就也为0了......我们来看一下增大比例项的结果:静差大大减小,但是超调也增大了。

所以我们可以看出纯比例控制所遇到的一个矛盾的问题,系数太小则存在静差,系数太大则存在超调,所以为了解决这一问题,我们需要提高系统阶数,引入积分项。

引入积分项后,公式变成

\[U(t) = K_p * err(t) + K_i * \int{{err(t)}dt}
\]

我们来分析一下积分项是如何解决静差这个问题的。由于积分的累积性,只要存在误差,积分项就会持续作用,即使在err(t)为0时,积分项也不会为0,而是继续保持作用,维持U(t)不为0。但是需要注意的是,积分项对于输出的影响是比较大的,不能贸然给很大的积分系数,否则......(“嘿,你云台/底盘疯了”),此外积分项一定程度上会助长超调的影响,使系统趋于稳定的时间变得更久,如下图所示。

通过增加积分项,我们解决了静差这一问题,但是超调问题依然存在,虽然通过增加减小比例项和积分项可以一定程度上的减小超调,但是代价就是输出消除静差的时间又要被延长了。所以这时我们引入第三项微分项。这时我们就得到了真正的完整PID控制器公式——

\[U(t) = K_p * err(t) + K_i * \int{{err(t)}dt} + K_d * \frac{{\rm d}err(t)}{{\rm d}t}
\]

微分项的意义何在呢?我们可以将其与物理中的阻尼概念联系起来。每当err(t)产生急剧变化时,就会产生一个很大的微分项来抵消这一急剧的变化。这就恰好和我们的超调现象相对应,因为超调正是一个急剧上升后急剧下降的尖峰,而微分项是来和它做抵消的。

我们来看一下引入微分项后的输出结果——

可以看到超调量大大减小,且系统恢复稳定的时间也加快了。

通过以上的分析,我们知道了PID控制器各项的作用。然而注意,上面所说的一切都只是定性分析,下面让我们来结合《信号与系统》以及《自动控制原理》的专业知识,来说一下PID更深层次的原理,没有相关基础的同学可以跳过这一部分。

我们引入传递函数来进行系统稳定性的分析,一个闭环控制系统的系统框图如下——

假设我们已经获得了云台的传递函数(可以通过系统辨识获得)

写出PID控制器的s域表达式如下:

\[U(s) = K_p + K_i * \frac{1}{s} + K_d * s
\]

通过调节积分项,使积分段作用于系统的低频成分,保证系统稳定性,将微分段作用于系统的高频成分,保证系统的动态性能。

在自动控制原理中,我们知道一个系统稳定的条件是该系统的极点全部位于复平面左侧。所以任何控制器所做的首要任务是配置系统极点,举一个例子。假设一个系统传递函数为

\[G(s) = \frac{1}{s-1}
\]

显然其开环不稳定,其闭环传函为

\[\Phi(s) = \frac{G(s)}{1+G(s)H(s)}= \frac{1}{s}
\]

显然闭环系统极点在原点上,不稳定

而在引入前馈纯比例控制器

\[C(s) = 2
\]

之后,我们可以看到闭环传函变为

\[\Phi(s) = \frac{C(s)G(s)}{1+C(s)G(s)H(s)}=\frac{2}{s+1}
\]

系统极点为s=-1,系统稳定。

在保证系统稳定的前提下,我们根据系统闭环传递函数的波特图进行分析,使幅频响应和相频响应满足幅度裕度条件和相位裕度条件,可以借助matlab的工具箱进行分析。

关于系统辨识以及根据系统辨识的结果设计控制器,可以参考官方的开源教程

https://bbs.robomaster.com/thread-4941-1-1.html

https://bbs.robomaster.com/thread-5059-1-1.html

当然,没有掌握这些知识不代表一个人不能调PID,同样一个人掌握了这个知识也不等于他一定能够调好PID,很多情况下系统的传递函数并不容易获取,所以经验依然非常非常重要。

代码实现

需要注意的是,前文我们一直在讨论连续型PID控制器,但是单片机内部是一个数字系统,数字系统必然是离散的,所以我们需要把连续型PID转换出离散型PID,当然这一点其实也没有任何难度,只不过是把积分变成求和,微分变成差分而已。

离散型PID公式如下

\[U(n) = K_p * err(n) + K_i * \sum{err(n)} + K_d * [err(n) - err(n-1)]
\]

眼尖的同学注意到我没有把周期T写在公式里面,其实考虑到周期是一个常数,我把它直接合在了系数中。

这里对应到代码中,也告诉了我们两件事

  1. PID控制器的运算必须在定时中断中执行
  2. 采样周期和控制周期会影响系数

关于第二点特别说明一下,一般来说增加控制周期和采样周期是可以让我们的控制变得更加平滑,控制周期即执行控制代码的周期,一般是放置运算PID代码的定时器的周期,采样周期即获取传感器数据的周期,比如电机的采样周期就是CAN接收中断的周期。

最后我们依然是结合官方开源代码来理解PID的代码实现。

这是pid.c下的pid_calculate函数,结合公式可以很容易理解含义。set即期望,get即反馈,两者相减得到误差err,pid->pout即比例项,直接将err线性放大,pid->iout即积分项,对err进行累加,pid->dout即微分,对err做差分。最后将三者叠加得到pid控制器输出。

/**
* @brief calculate delta PID and position PID
* @param[in] pid: control pid struct
* @param[in] get: measure feedback value
* @param[in] set: target value
* @retval pid calculate output
*/
float pid_calculate(struct pid *pid, float get, float set)
{
pid->get = get;
pid->set = set;
pid->err = set - get;
if ((pid->param.input_max_err != 0) && (fabs(pid->err) > pid->param.input_max_err))
return 0; pid->pout = pid->param.p * pid->err;
pid->iout += pid->param.i * pid->err;
pid->dout = pid->param.d * (pid->err - pid->last_err); abs_limit(&(pid->iout), pid->param.inte_limit);
pid->out = pid->pout + pid->iout + pid->dout;
abs_limit(&(pid->out), pid->param.max_out); return pid->out;
}

调参技巧

最后说一点关于调参的问题,当然不会具体到各个参数的调节上,因为这个东西往往是各执一词,不同的人调起PID来即使大思路一致,具体细节上依然可能会有各种各样的不同。这里更多是推荐一些调参的工具,方法,注意事项等。

首先是工具,这里就要搬出我们无敌的Jscope了,在之前的博文中也提到过,这是一个非常便利的虚拟示波器,在mdk中由于只能看到数值,很难分析系统的动态性能,所以Jscope在这时可以派上大用处——

直接上官网就可以免费下载,建议使用比较新的版本,旧的版本存在不能查看结构体内部变量,不能正常画浮点数波形等一些问题。

https://www.segger.com/products/debug-probes/j-link/tools/j-scope/

然后是方法,这里说的方法不是说PID的参数调节顺序之类的(虽然正常人都是先调P然后I,D),而是如何设计输入与如何评价输出。设计输入时,一般以阶跃信号作为输入,逐步提升阶跃幅值以测定系统鲁棒性。进一步测试时可以将窄方波脉冲当作冲激信号来输入,因为赛场上的冲击一般是被可以看作冲激的,RM这个比赛一定程度上检验的就是稳定性,对自己系统的稳定性界限心知肚明对一个电控队员来说是很重要的。

评价输出则根据超调量,静差,恢复时间等参数作为指标。理想的输出曲线自然是能够又快又不超调的贴合上期望曲线,然后根据实际情况来调整参数,出现超调时适当衰减比例项,恢复时间过长时适当减小积分项,增大微分项等等。必须在调参的一开始就定好系统的静态和动态性能指标,有的放矢才能提高效率。

最后是注意事项:记得给控制器的输出限制幅度,切记,切记,切记,被铁疙瘩狠狠打一下或者撞一下,轻则瘀伤,重则伤筋动骨,希望各位电控同学注意自己的生命安全。一般调车时我个人不会把车放在地上调,而是放在车架上,这样可以在一定程度上避免跑飞带来的危险。

另外可以适当考虑采用无线下载器,磁吸附线等,保护好自己的下载器也是很重要的,在越来越多的队伍使用滑环做小陀螺的RM赛场上,云台抽风打转很有可能直接扯断下载线......

结语

关于PID就先说这么多了,还是那句话,实践出真知。掌握PID的理论可以帮助一个人更加科学地去调参,但是光有理论没有实践是没有意义的,还是得多调,积累经验才行。

RoboMaster电控入门(4)PID控制器的更多相关文章

  1. PID控制器开发笔记之十三:单神经元PID控制器的实现

    神经网络是模拟人脑思维方式的数学模型.神经网络是智能控制的一个重要分支,人们针对控制过程提供了各种实现方式,在本节我们主要讨论一下采用单神经元实现PID控制器的方式. 1.单神经元的基本原理 单神经元 ...

  2. PID控制器开发笔记之十二:模糊PID控制器的实现

    在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题.模糊PID控制器是将模糊算法与PID控 ...

  3. PID控制器开发笔记之十一:专家PID控制器的实现

    前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法,基本已经覆盖了无模型和简单模型PID控制经典算法的大部.再接下来的我们将讨论智能PID控制,智能PID控制不同于常规意义下的智能控制,是 ...

  4. PID控制器开发笔记之九:基于前馈补偿的PID控制器的实现

    对于一般的时滞系统来说,设定值的变动会产生较大的滞后才能反映在被控变量上,从而产生合理的调节.而前馈控制系统是根据扰动或给定值的变化按补偿原理来工作的控制系统,其特点是当扰动产生后,被控变量还未变化以 ...

  5. PID控制器开发笔记之六:不完全微分PID控制器的实现

    从PID控制的基本原理我们知道,微分信号的引入可改善系统的动态特性,但也存在一个问题,那就是容易引进高频干扰,在偏差扰动突变时尤其显出微分项的不足.为了解决这个问题人们引入低通滤波方式来解决这一问题. ...

  6. PID控制器开发笔记之一:PID算法原理及基本实现

    在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于更多的应用场景. ...

  7. PID控制器(比例-积分-微分控制器)- I

    形象解释PID算法 小明接到这样一个任务: 有一个水缸点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水. 小明接到任务后就一直守在水 ...

  8. 2022徐特立科学营&BIT机器人队电控课程讲义

    目录 \(\cdot\)电控简介 \(\cdot\)认识单片机   什么是单片机   时钟-单片机的脉搏 \(\cdot\)外设及应用   GPIO   PWM   定时器   UART \(\cdo ...

  9. PID控制器的数字实现及C语法讲解

    PID控制器的数字实现及C语法讲解 概述 为方便学习与交流,根据自己的理解与经验写了这份教程,有错误之处请各位读者予以指出,具体包含以下三部分内容: (1)  PID数字化的推导过程(实质:微积分的近 ...

  10. Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据

    Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据 在这一节中,你将新创建一个新的 MoviesController类,并编写代码,实现获取影片数据和使用视图模板在浏览器中展现 ...

随机推荐

  1. 前端开发系列012-基础篇之Javascript面向对象(一)

    一. JavaScript的范围 JavaScript的范围:BOM + DOM + ECMAScript BOM BOM即Browser Object Mode,浏览器对象模型. BOM提供了独立于 ...

  2. C++ delete [] 与 delete

    简介 对于普通数据类型数组 使用 delete [] pa 和 delete pa, 都不会产生内存泄露. 对于自己定义的对象数组, 会产生内存泄露. 环境 g++ , valgrind 来查看是否产 ...

  3. 谷云科技iPaaS V7.0+企业级AI Agent产品全新发布

    当下,大数据.人工智能等前沿技术迅猛发展,正以前所未有的速度重塑着企业 IT 集成的格局.谷云科技作为深耕国内集成领域多年的专业厂商,始终紧跟技术趋势变化,深度洞察客户需求,致力于以创新驱动为企业数字 ...

  4. ICEE-Bluetooth-5.4(PwAR超级节能长期无连接双向通讯)/5.3/5.2/5.1/5.0/4.0/3.0

    https://cn.silabs.com/blog/the-new-bluetooth-5-4-what-you-should-know-first Bluetooth Core Specifica ...

  5. SciTech-Mathematics-Probability+Statistics- Pandas DataFrame Histogram/BarChart/Boxplot/Scatterplot + Relative Frequency Histogram: Definition + Example()

    Links: How to Plot Multiple Series from a Pandas DataFrame How to Make a Scatterplot From a Pandas D ...

  6. SciTech-EECS-MCU/CPU: DMA(直接内存访问): 开始时由CPU进行协调配对+传数据时DMA+结束时触发硬件中断通知MCU/CPU并解除配对

    MEM可以是: MCU/CPU自带的内存: 容量由"芯片设计师"根据常用场景统计确定大小. 常能满足大多数用途. MCU/CPU的外部内存: 容量由"硬件设计师" ...

  7. 进阶篇:3.1.1.5)DFM塑胶-注射模具和设备

    本章目的:了解塑胶件的注射模具典型结构. 1.前言 本章只是了解章节,介绍了塑胶件注射模具典型的机构.浇口.顶出,目的是为了设计出更好的塑胶零件. 但并非是需要结构设计工程师一定能设计出模具,人的精力 ...

  8. 用 Planet + ENS 构建一个真正去中心化的博客

    你是否也想拥有一个无需服务器.不会被平台下架.使用自己域名的博客? 这篇文章将手把手带你完成这一切,只需要 3 个工具: Planet:macOS 上的开源博客 App ENS 域名(如 yourna ...

  9. mysql的存储引擎选择

    (1) InnoDB : 是Mysql的默认存储引擎,支持事务.外键.如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新.删除操作,那么I ...

  10. 使用.NET实现自带思考的Tool 并且提供mcp streamable http服务

    使用.NET实现自带思考的Tool 并且提供MCP服务 下面我们将使用.net实现自带思考的Tool并且提供mcp streamable http供其他AI客户端使用 创建项目 创建WebAPI项目并 ...