PID的理解和应用


1. PID控制简介

PID控制,即 比例(proportion) - 积分(integration) - 微分(differentiation) 控制
是自动控制原理中定义的一种控制方法
也可以称为是校正方法
在这里插入图片描述
在这里插入图片描述
t t t:某个时刻
k p kp kp: 比例系数
k i ki ki: 积分系数
k d kd kd: 微分系数
e r r err err: 误差
当得到系统的输出后
将输入加上经过比例,积分,微分调节的输出
从而控制系统的行为


2. 比例控制算法

先只看PID中最简单的比例控制
用一个经典的例子,假设有一个水缸,目的是要保证水缸里的水位永远的维持在1米
假设初始时刻,水缸里的水位是0.2米
那么当前时刻的水位和目标水位之间是存在一个误差的error,所以error=0.8

假设旁边站着一个人,这个人通过往缸里开阀加水的方式来控制水位
如果单纯的用比例控制算法,就是指加入的水量u和误差error是成正比的
u = k p ∗ e r r o r u=kp*error u=kperror

假设 k p = 0.5 kp=0.5 kp=0.5, 那么 t = 1 t=1 t=1 时(表示第1次加水,也就是第一次对系统施加控制)
u = 0.5 ∗ 0.8 = 0.4 u=0.5*0.8=0.4 u=0.50.8=0.4
所以这一次加入的水量会使水位在0.2的基础上上升0.4,达到0.6

t = 2 t=2 t=2时刻(第2次施加控制),当前水位是0.6,所以 e r r o r = 0.4 error=0.4 error=0.4
u = 0.5 ∗ 0.4 = 0.2 u=0.5*0.4=0.2 u=0.50.4=0.2
所以这一次加入的水量会使水位在0.6的基础上上升0.2,达到0.8

如此这么循环下去,就是比例控制算法的运行方法
最终水位会达到需要的1米

但是,单单的比例控制存在着一些不足
其中一点就是 稳态误差,也叫 静态误差

根据kp取值不同,系统最后都会达到1米
只不过kp大了到达的快,kp小了到达的慢一些,不会有稳态误差

但是,考虑另外一种情况,假设这个水缸在加水的过程中,存在漏水的情况
假设每次加水的过程,都会漏掉0.1米高度的水
仍然假设kp取0.5,那么会存在着某种情况
假设经过几次加水,水缸中的水位到0.8时,水位将不会再变换!!!
因为水位为0.8,则误差 e r r o r = 0.2 error=0.2 error=0.2
所以每次往水缸中加水的量为 u = 0.5 ∗ 0.2 = 0.1 u=0.5*0.2=0.1 u=0.50.2=0.1
同时,每次加水,缸里又会流出去0.1米的水!!!
加入的水和流出的水相抵消,水位将不再变化!!

也就是说,目标是1米
但是最后系统达到0.8米的水位就不再变化了,且系统已经达到稳定
由此产生的误差就是稳态误差了

在实际情况中,这种类似水缸漏水的情况往往更加常见
比如控制汽车运动,摩擦阻力就相当于是“漏水”
控制机械臂、无人机的飞行,各类阻力和消耗都可以理解为本例中的“漏水”
所以,单独的比例控制只能控制现在,在很多时候并不能满足要求


2. 积分控制算法

如果仅仅用比例,存在稳态误差,最后的水位就卡在0.8了
于是,在控制中再引入一个分量,该分量和误差的积分是正比关系
所以,比例+积分控制算法为: u = k p ∗ e r r o r + k i ∗ ∫ e r r o r u=kp*error+ki∗∫error u=kperror+kierror

还是用加水的例子来说明:
第一次的误差error是0.8,第二次的误差是0.4
至此,误差的积分(离散情况下积分其实就是做累加): ∫ e r r o r = 0.8 + 0.4 = 1.2 ∫error=0.8+0.4=1.2 error=0.8+0.4=1.2
这个时候的控制量,除了比例的那一部分,还有一部分就是一个系数ki乘以这个积分项
由于这个积分项会将前面若干次的误差进行累计
所以可以很好的消除稳态误差

假设在仅有比例项的情况下,系统卡在稳态误差了,即上例中的0.8
由于加入了积分项的存在,会让输入增大
从而使得水缸的水位可以大于0.8,渐渐到达目标的1.0
这就是积分项的作用,可以纠正过去


3. 微分控制算法

平稳的加水过程,当发现快满的时候
为了使得水面产生的波浪不溢出水缸
基本上提前一点就先慢慢的减少加水速度了,关小点阀门,避免溢出水缸

当非常近满的时候,则越不加水,使水不溢出刚刚好满缸
整个过程可以看做一个加入微分的控制策略

微分,说白了在离散情况下,就是error的差值
即 t 时刻和 t-1 时刻error的差
u = k d ∗ ( e r r o r ( t ) − e r r o r ( t − 1 ) ) u=kd*(error(t)-error(t-1)) u=kd(error(t)error(t1)),其中的kd是一个系数项

可以看到,在减缓加水速度的过程中,因为error是越来越小的
所以这个微分控制项一定是 负数
在控制中加入一个负数项,作用就是为了防止由于来不及停止倒水时而溢出水缸

从常识上可以理解,越是靠近满缸的时候,越是应该注意减少加水,不能让水过溢出
所以这个微分项的作用,就可以理解为关阀门
当水离缸面很近并且水流速度很快时
这个微分项的绝对值(实际上是一个负数)就会很大
从而应该立即关小阀门停止加水
这就是微分项的作用,管控未来减少控制过程中的震荡


4. 增量式PID应用

以控制电机转速为例,希望电机通过编码器的反馈,达到平稳变速的效果
假设编码器读取的数据是上个状态电机希望的输出

import matplotlib.pyplot as plt

Kp = 0.2    # 比例系数 调整系统的响应速度
Ki = 0.4    # 积分系数 主要解决达不到设定值的静态误差问题
Kd = 0.025  # 微分系数 主要解决积分项I存在导致系统的响应速度问题

goal = 100       # 目标值
output = 0       # 输出
bmq = 0          # 编码器反馈
err = [0, 0, 0]  # 输出误差 err[0]现误差 err[1],err[2]旧误差


def IncrementalPID_control():
    global bmq, output
    bmq = output     # 假设反馈等于上一次输出
    err[2] = err[1]  # 更新误差
    err[1] = err[0]
    err[0] = goal - bmq

    # 输出变化
    output_u = Kp * (err[0] - err[1]) + Ki * err[0] + Kd * (err[0] - 2 * err[1] + err[2])

    # 限幅
    if output_u > 20:
        output_u = 20
    elif output_u < -20:
        output_u = -20

    # 更新输出
    output += output_u


IncrementalTime = [0]    # 时间次数
IncrementalOutput = [0]  # 输出

for i in range(1, 20):                # 迭代
    IncrementalPID_control()          # 运算一次增量式PID
    IncrementalOutput.append(output)  # 添加输出结果
    IncrementalTime.append(i)         # 添加时间次数

plt.rcParams['font.sans-serif'] = ['SimHei']                  # 设置正常显示中文
plt.plot(IncrementalTime, IncrementalOutput, label='output')  # 设置曲线数值
plt.xticks(IncrementalTime)                                   # 设置X轴坐标数值标识
plt.xlim(0)                                                   # 设置X轴的范围(起始坐标)
plt.ylim(0)                                                   # 设置Y轴的范围(起始坐标)
plt.xlabel('次数')                                            # 设置X轴的名字
plt.ylabel('输出')                                            # 设置Y轴的名字
plt.title("P:{0} I:{1} D:{2} 趋势图".format(Kp, Ki, Kd))      # 设置标题
plt.legend()                                                  # 设置图例
plt.show()                                                    # 显示图表

在这里插入图片描述

可以得到一个相对曲滑的曲线,以达到平稳变速的效果


[1] python的代码地址:
https://github.com/JoveH-H/A-simple-explanation/blob/master/IncrementalPID.py
[2] jupyter notebook的代码地址:
https://github.com/JoveH-H/A-simple-explanation/blob/master/ipynb/IncrementalPID.ipynb


参考:
PID控制算法原理(抛弃公式,从本质上真正理解PID控制)


谢谢!

  • 43
    点赞
  • 197
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氢键H-H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值