一、PID算法简介

PID是比例(Proportion)、积分(Integral)、微分(Differential) 闭环控制算法,通过偏差值动态输出控制量,在无人机、电机调速、平衡车、温度控制所有闭环项目中,PID是使用频率最高、最稳定、最通用的控制算法。
相比于复杂的现代控制理论(LQR、MPC、自适应控制),PID 有三个绝对优势:
1. 不需要精确数学模型
2. 计算量极小,单片机即可跑
3. 参数物理意义直观、可手动调参
绝大多数 RoboMaster、飞控、云台自稳、电机闭环,核心底层用的就是改良PID。

二、何为闭环控制


在介绍闭环控制之前,我们先简单介绍一下开环控制。


1. 开环控制

 
        开环控制没有反馈回路,控制器只按预设指令,直接输出控制量,不接收反馈量,不检测实际执行结果,无法自动修正偏差。

工作原理:给定目标信号 → 直接驱动执行机构 → 输出动作(全程不采集实际反馈值,不和设定值做对比纠错)

特点:易于控制、调试极易响应速度快,无震荡超调问题,抗干扰能力极差,精度低,负载或环境变化时控制效果会大打折扣。

比如:直接给电机发PWM,不测速、不测角度,单纯让电机转动,如果用手堵住,电机力度不会自动增大,而导致电机堵转。

2. 闭环控制

        闭环控制带反馈检测回路,实时采集被控对象实际值(如当前位置,当前温度等),与设定值对比算偏差,自动修正输出。

工作原理:设定目标值 → 对比实际反馈值(由测量元件返回) → 计算偏差 → 控制器运算调整输出 → 驱动执行机构 → 输出动作 → 再次采样反馈,循环迭代。

特点:自动纠偏,消除静态误差,抗外界干扰、负载波动能力强,控制精度高、稳态性能好,结构复杂、需额外传感硬件、存在调试难度。

常见的应用就是倒立摆,平衡车,恒温控制系统。

区别:开环控制就是相当于你开洗澡水,你只是把水龙头拨到这个位置,实际你并不知道水温多少,是冷是热。而闭环控制系统是你把水龙头打开后用手去试水温,冷了热水开大大点,热了冷水开大点,在这过程是可以感受到水温变化的,从而调节到合适的水温。
 

三、PID算法控制系统

PID算法本质是负反馈调节,PID算法根据测量元件反馈的实际输出与系统的期望输出做对比,得到偏移误差,再自动计算出输出,让系统能够又快又准确的达到目标。PID算法有三个环节,分别是比例环节(KP),积分环节(KI),微分环节(KD),在实际应用过程中通常选取2~3个环节来进行控制,几乎所有的PID算法都会使用KP项,常用的模式有 KP+KI 、 KP+KD 、KP+KI+KD

PID按信号处理方式又可以分为连续PID(模拟PID)和离散PID(数字PID)

连续PID

连续PID公式:u(t)=K_{P}*e(t)+K_{i}*\int_{0}^{t}e(\tau )d\tau +K_{d}*\frac{de(t)}{dt}

e(t):连续的误差信号。

\int_{0}^{t}e(\tau )d\tau:积分,对过去无限时刻的误差求和。

\frac{de(t)}{dt}:微分,误差信号的瞬时变化率。

离散PID

离散PID公式:u(k)=K_{P}*e(k)+K_{i}*\sum_{i=0}^{k}e(i) +K_{d}*\frac{e(k)-e(k-1)}{T}

e(k):第k此采样的误差。

\sum_{i=0}^{k}e(i):离散积分,从0累加到k次的误差。

\frac{e(k)-e(k-1)}{T}:离散微分,第k次误差和第k-1次误差的差值除采样周期。

由于计算机(单片机、DSP、电脑)只能处理数字信号,所以需要把连续信号“采样”变成离散的数字信号,即我们PID算法一般是使用离散PID的形式,以下的介绍我们使用离散PID进行讲解。

核心原理:把连续的微积分换成离散的差分方程。将时间离散化,把时间分成固定的采样周期T;只在 t = kT (k=0,1,2...) 时刻计算 PID。

1.比例环节(KP)

纯比例控制公式: P=K_{P}*e(k)

e(k):偏差,通常是:目标值 - 实际值

k_{p}:比例系数,常数,也就是我们调参要调节的项

P:纯比例控制时的输出,与e(k)是一次函数关系。

当e(k)范围确定,此时 K_{p} 越大,斜率越高,也就是响应更加的迅速,控制作用更明显,过渡更快,但是相应的系统也越容易超过目标值,也就是常见的超调,K_{p} 的选取需要恰当,才能稳定迅速地达到响应的目标。

图一是y=x函数,此时斜率K=1,即可以看作 K_{p} =1

图二是y=5x函数,此时斜率K=5,即可以看作 K_{p} =5

可以看到,相同时间内 K_{p} 越大响应越快,但是也更容易超调。

2.积分环节(KI)

纯积分控制公式: I=K_{i}*\sum_{i=0}^{k}e(i)

K_{i}: :积分系数,常数,需要调节的项

\sum_{i=0}^{k}e(i):历史所有误差的累加和。

作用:

1. 消除稳态静差
纯KP:稳定后会残留固定误差(静差),像上图(红线是纯KP控制的输出图,黑线是需要到达的目标图),因为需要一点误差维持输出,所以无法稳定到目标值的位置;
积分:只要有误差就一直累加输出,可以减小误差,把误差减小到0(使红线逐渐趋于黑线并重合)。
​2. 提高系统稳态精度
小幅度控制稳定输出速度、定点保持。
​3. 滞后、相位滞后(副作用)
积分是滞后环节,会让系统变慢、超调变大、容易震荡。

K_{i} 越大 → 越容易震荡、低频抖、超调、来回晃。

K_{i}越小 → 积分太弱、消静差极慢、接近纯P,半天稳不到目标。

K_{i}合适 → 慢慢抹平静差,曲线平稳贴目标。

3.微分环节(KD)

微分环节是自动控制中一种对输入信号的变化率进行响应的动态环节。

纯微分控制公式:D=K_{d}*\frac{e(k)-e(k-1)}{T}

K_{d}: :积分系数,常数,需要调节的项。

\frac{e(k)-e(k-1)}{T}:在T时间内误差的变化率。

作用:

1. 超前调节(预测作用)

        当误差刚开始快速增大时,D 项立刻输出一个较大的控制量,提前抑制偏差扩大。
即会根据系统的变化率,提前输出一个较大的抑制作用,好比看到前方有障碍物,车辆提前刹车减速慢行这样。

2. 抑制超调

        系统惯性大、容易冲过目标时,D 项提供阻尼力,让系统更平稳,减少震荡,即在出现超调情况时,D项会将其扳回正轨。
 
3. 提高系统稳定性

        适当增大 K_d 可以增加阻尼比,减小超调量,提高系统的稳定性,当然过大的D项可能会导致系统震荡或者过冲。
 
4. 加快响应速度

        在合理范围内,D 项可以让系统初始时产生一个较大的作用,更快接近稳态。

4.PID算法的运用

(1)位置式

在纯裸机开发过程中,我们选择使用定时器进行PID运算,这样就可以不用在运算中考虑时间dt,因为dt每次都是相同的。如果在操作系统中进行PID计算,每次运行时间并不完全相同,我们就需要考虑dt的影响。这里暂时不过深探讨。

位置式PID适用于:

  1. 执行机构本身具有积分作用或保持特性(如步进电机位置控制、阀门开度、数字电位器)。

  2. 控制系统不需要在手动/自动切换时进行无扰切换,或者可以处理输出初始值。

  3. 控制量可以在一段时间内保持稳定,不需要频繁变化。

  4. 系统没有积分饱和问题,或者有抗饱和措施,这个在改良PID算法会提到,积分限幅。

typedef struct
{
    float p;            //KP
    float i;            //KI
    float d;            //KD
	float Now_Error;    //本次误差
	float Last_Error;   //上次误差
	float Error_Sum;    //历史误差和
}pid_t;

float PID_Calc(PID_t *p,float set,float get)  //传入PID结构体指针,设定值,实际值(由传感器测量)
{
    float pid_out;                 //输出值
	p->Last_Error = p->Now_Error;  //更新上次误差 
	p->Now_Error  = set - get;     //记录本次误差
    p->Error_Sum += p->Now_Error;  //历史误差和

	pid_out = p->Kp * p->Now_Error  //计算PID输出
            + p->Ki * p->Error_Sum 
            + p->Kd * (p->Now_Error - p->Last_Error);
return pid_out;
}

(2)增量式

这里的D项部分为什么是: p->Kd * (p->Now_Error - 2*p->Last_Error + p->Last_Last_Error)?

可以将其拆开:

p->Kd * ((p->Now_Error - p->Last_Error) -( p->Last_Error - p->Last_Last_Error))

增量式的:\Delta u(k)=u(k)-u(k-1)

\Delta u(k-1)=u(k-1)-u(k-2)

两式相减:u_{d}==u(k)-2*u(k-1)+u(k-2)

这部分便是增量式的KD需要乘上的项。

位置式PID的微分项近似为误差的一阶导数(速度),增量式PID中,我们计算的是控制量增量 \Delta u(k),相当于对位置式输出再求一次差分。因此对微分项再次差分,这实际上是误差的二阶差分,近似了误差的二阶导数(加速度)。当误差变化率(速度)本身也在快速变化时(例如误差曲线变陡或变缓),二阶差分能提供“超前”的补偿,抑制超调和震荡,提高系统对快速动态的响应能力,所以增量式PID更适用于需要频繁大幅度变化的系统。

typedef struct
{
    float p;            //KP
    float i;            //KI
    float d;            //KD
	float Now_Error;    //本次误差
	float Last_Error;   //上次误差
	float Last_Last_error;    //上上次误差
}pid_t;

float PID_Calc(PID_t *p,float set,float get)  //传入PID结构体指针,设定值,实际值(由传感器测量)
{
    float pid_out;                 //输出值
    p->Last_Last_Error  = p->Last_Error;  //更新上上次误差
	p->Last_Error       = p->Now_Error;   //更新上次误差 
	p->Now_Error        = set - get;      //记录本次误差

	pid_out = p->Kp * (p->Now_Error - p->Last_Error)  //计算PID输出
            + p->Ki * p->Now_Error
            + p->Kd * (p->Now_Error - 2*p->Last_Error + p->Last_Last_Error);
return pid_out;
}

四、改良PID算法

1.输出限幅

2.积分限幅

3.积分分离

4.变速积分

5.梯形积分

6.微分先行

7.不完全微分

8.微分滤波

9.输入死区

10.输出偏移

11.输出滤波

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐