PID控制算法学习

PID控制算法学习

这篇文章是转载自:原文链接原文作者
这里仅仅是记录一下自己的学习过程加一些简单的代码注释补全。

1. PID算法控制运用在哪些地方?

PID:比例(Proportion),积分(Integral),微分(Differential)
PID算法可以用来控制温度,压强,流量,化学成分,速度等等。汽车的定速巡航;伺服驱动器中的速度位置控制;冷却系统的温度;液压系统的压力等都可以通过PID算法实现,很好的保证系统的稳定性。

2. PID算法的原理

先了解几个概念:

偏差/误差 e:某时刻的系统的输出值(output)和目标值(target)之差

参数对应概念
K p K_p Kp比例系数
K i K_i Ki积分系数
K d K_d Kd微分系数
T i T_i Ti积分时间
T d T_d Td微分时间

原理图

在这里插入图片描述
如图,当得到输出后,将输出和输入的差值作为偏差,将这个偏差信号经过比例,积分,微分3种运算方式叠加后再以一定的方式加入到输入中,从而控制最终的结果,达到想要的输出值。

公式

PID的公式原理:
e ( t ) = s ( t ) − s ^ ( t ) e(t) = s(t) - \hat{s}(t) e(t)=s(t)s^(t)

y ( t ) = K p e ( t ) + 1 T i ∫ e ( t ) d t + T d d e ( t ) d t y(t) = K_pe(t) + {1\over T_{i}} \int e(t)dt + T_d {d e(t) \over dt} y(t)=Kpe(t)+Ti1e(t)dt+Tddtde(t)

如果需要在计算机上实现,需要将其离散化:

u [ k ] = K p e [ k ] + K i ∑ n = 0 k e [ n ] + K d ( e [ k ] − e [ k − 1 ] ) u[k] = K_p e[k] + K_i \sum_{n=0}^k e[n] + K_d(e[k]-e[k-1]) u[k]=Kpe[k]+Kin=0ke[n]+Kd(e[k]e[k1])

( N o t e   t h a t :   T T i = K i ,   T T d = K d ) (Note \ that: \ {T \over T_i} = K_i, \ {T \over T_d} = K_d) (Note that: TiT=Ki, TdT=Kd)

注:这里的 u [ k ] u[k] u[k]是PID控制的输出,也就是是控制量,而不是系统的输出。表示的是系统输出应该增加(减少)的量。

比例系数 K p K_p Kp:

增大比例系数使系统反应灵敏,调节速度加快,并且可以减小稳态误差。但是比例系数过大会使超调量增大,振荡次数增加,调节时间加长,动态性能变坏,比例系数太大甚至会使闭环系统不稳定。

比例控制不能消除稳态误差。

注:稳态误差可以这么理解:(知乎的例子)假设一个泳池每单位时间漏水0.1,现有蓄水0.8,只用propotion的话并且 K p = 0.5 K_p=0.5 Kp=0.5的时候,注水0.2 * 0.5 = 0.1。这样注水后水池有水0.8+0.1-0.1 = 0.8。这样的话就永远注不满水。这就是稳态误差的一个例子。

积分系数 K i K_i Ki:

使系统消除稳态误差,提高无差度。积分控制的作用是,只要系统有误差存在,积分调节就进行,积分控制器就不断地积累,输出控制量,直至无差,积分调节停止,积分调节输出一常值。因而,只要有足够的时间,积分控制将能完全消除误差,使系统误差为零,从而消除稳态误差。积分作用的强弱取决于积分时间常数Ti,Ti越小,积分作用就越强,积分作用太强会使系统超调加大,甚至使系统出现振荡,反之Ti大则积分作用弱。加入积分调节可使系统稳定性下降,动态响应变慢。

注:用注水的例子来说,假设不仅使用了比例系数,也使用积分系数,那么就算稳态误差存在,由于积分一直在增长,控制量也就会增长而不是停在0.1每单位的注水,这样最终我们能达到1的满水状态。

微分系数 K d K_d Kd:

微分控制可以减小超调量,克服振荡,使系统的稳定性提高,同时加快系统的动态响应速度,减小调整时间,从而改善系统的动态性能。

微分的控制作用跟偏差的变化的速度有关,微分控制能够预测偏差,产生 超前的校正作用,有助于减少超调。

注:微分系数在注水的例子里可以理解为:如果临近满水的状况下,每次计算出来的注水量仍然很大,这时候就可以算上微分系数的分量作为缓冲,即减少超调量的震荡。

3. PID算法的python实现

首先建立一个PID的算法模块,算法原理就是上面的式子,保存为PID.py,如下:

import time

class PID:
    def __init__(self, P, I, D):
      # 输入系数
        self.Kp = P
        self.Ki = I
        self.Kd = D
        self.sample_time = 0.00
        self.current_time = time.time()
        self.last_time = self.current_time
        self.clear()
    def clear(self):
        self.SetPoint = 0.0	# 真实期望值 0.0
        self.PTerm = 0.0
        self.ITerm = 0.0
        self.DTerm = 0.0
        self.last_error = 0.0
        self.int_error = 0.0
        self.output = 0.0
    def update(self, feedback_value):
        # 计算误差 - 真实误差
        error = self.SetPoint - feedback_value
        # 计算经过的时间(微分的时间) - delta t
        self.current_time = time.time()
        delta_time = self.current_time - self.last_time
        # 计算误差的变化(微分的误差) - delta e
        delta_error = error - self.last_error
        if (delta_time >= self.sample_time):
            self.PTerm = self.Kp * error # 比例系数项
            self.ITerm += error * delta_time # 积分系数项
            self.DTerm = 0.0
            if delta_time > 0:
                self.DTerm = delta_error / delta_time # 微分系数项
            self.last_time = self.current_time # 记录新时间节点
            self.last_error = error # 记录新误差
            self.output = self.PTerm + (self.Ki * self.ITerm) + (self.Kd * self.DTerm)


    def setSampleTime(self, sample_time):
        self.sample_time = sample_time

然后在相同路径下建立一个test_pid.py,实现PID控制的算法示意,如下:

import PID #导入上面的PID算法
import time
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import make_interp_spline


def test_pid(P, I , D, L):
	# 初始化实例
    pid = PID.PID(P, I, D)
	
	# 真实期望值1.1
    pid.SetPoint=1.1
    # 开始采样时间.01
    pid.setSampleTime(0.01)
	
	# 采样数量
    END = L
    feedback = 0
    feedback_list = []
    time_list = []
    setpoint_list = []

    for i in range(1, END):
        pid.update(feedback)
        output = pid.output
        feedback += output # PID控制系统的函数 - 返回的修正值
        time.sleep(0.01)
        feedback_list.append(feedback) # 记录每次PID算法调整后的输出值
        setpoint_list.append(pid.SetPoint)
        time_list.append(i)

	# 画图部分
    time_sm = np.array(time_list)
    time_smooth = np.linspace(time_sm.min(), time_sm.max(), 300)
    # 插值 - 绘制平滑曲线,为了更好的展示效果
    feedback_smooth = make_interp_spline(time_list, feedback_list)(time_smooth)
    plt.figure(0)
    plt.grid(True)
    plt.plot(time_smooth, feedback_smooth,'b-')
    plt.plot(time_list, setpoint_list,'r')
    plt.xlim((0, L))
    plt.ylim((min(feedback_list)-0.5, max(feedback_list)+0.5))
    plt.xlabel('time (s)')
    plt.ylabel('PID (PV)')
    plt.title('PythonTEST PID--xiaomokuaipao',fontsize=15)

    plt.grid(True)
    plt.show()

if __name__ == "__main__":
    test_pid(1.2, 1, 0.001, L=100)

最终的输出如下:
在这里插入图片描述
其中,红色线是目标值(setpoint),蓝色线是在当前 K p K_p Kp K i K_i Ki K d K_d Kd参数下的震荡结果,最终趋于目标值,实现了控制。

从而用python实现了PID算法的简单示意。

4. PID调试的一些经验

PID调试的一般原则:

在输出不震荡时,增大比例增益;

在输出不震荡时,减少积分时间常数;

在输出不震荡时,增大微分时间常数;

PID调节口诀:

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

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

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

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

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

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值