目录
一、位置式PID
在控制信号幅值受限、且给定目标出现大跳变的情况下,积分控制容易产生积分器饱和(integrator windup)的现象,使系统出现大超调和低频震荡,甚至导致不稳定。
课上所学两种抗积分饱和方法:遇限消弱积分法,反馈抑制抗饱和PID。
1.1遇限消弱积分法
遇限消弱积分法是其中比较有效的一种抗饱和方法,其基本思想是:当执行器处于饱和、且误差信号与控制信号同方向(同号)时,积分器停止更新(其值保持不变),除此之外,积分器正常工作。即,在饱和情况下,只进行有助于削弱饱和程度的积分运算。在离散控制(采样周期为T)模式下,相应的控制律如下:
1.2反馈抑制抗饱和PID
如图1所示,反馈抑制抗饱和PID是把计算的控制量超出其限幅范围的偏差值通过反馈进入积分器,从而迫使控制量返回到限幅值之内。在离散时间(采样周期T)域中,其控制律可以表
示为
1.3实现
1.3.1头文件
/*
* AW_PID.h
*
* Created on: 2021年9月29日
* Author: longchentian
*/
#ifndef INCLUDE_AW_PID_H_
#define INCLUDE_AW_PID_H_
typedef struct {
float32 Ref; // 输入:参考输入 Input: Reference input
float32 Fdb; // 输入:反馈输入 Input: Feedback input
float32 Err; // 变量:误差信号e(k)
float32 Err_1; // 变量:误差信号e(k-1) Variable: Error
float32 umax; // 参数:控制量的饱和限幅值
float32 Ts; // 控制周期
float32 kw; // 参数:抗饱和方案:0 (无);1(条件积分);2(反馈抑制)
float32 Kp; // 参数:比例增益 Parameter: Proportional gain
float32 Ki; // 参数:积分增益 Parameter: Integral gain
float32 Kc; // 参数:积分修正增益 Parameter: Integral correction gain
float32 Kd; // 参数:微分增益Parameter: Derivative gain
float32 Up; // 变量:比例输出 Variable: Proportional output
float32 Ui; // 变量:积分输出 Variable: Integral output
float32 Ud; // 变量:微分输出 Variable: Derivative output
float32 Ud1; // 变量:微分输出(k-1) Variable: Derivative output
float32 N; // 变量:低通滤波参数
float32 OutPreSat; // 变量:饱和输出 Variable: Pre-saturated output
float32 OutMax; // 参数:最大输出 Parameter: Maximum output
float32 OutMin; // 参数:最小输出 Parameter: Minimum output
float32 Out; // 输出:AW_PID输出 Output: AW_PID output
float32 SatErr; // 变量:饱和差值 Variable: Saturated difference
void (*calc)(); // 计算函数指针 Pointer to calculation function
} AW_PID;
typedef AW_PID* AW_PID_handle;
/*-----------------------------------------------------------------------------
默认初始化 Default initalizer for the AW_PID object.
-----------------------------------------------------------------------------*/
#define AW_PID_DEFAULTS { 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, \
0, 0, 0, 0, 10, \
0, 0, 0, 0, 0, \
(void (*)(Uint32)) aw_pid_calc }
/*------------------------------------------------------------------------------
函数原型 Prototypes for the functions in <AW_PID.c>
------------------------------------------------------------------------------*/
void aw_pid_calc(AW_PID_handle);
#endif /* INCLUDE_AW_PID_H_ */
1.3.2 源文件
/*============================================================
<<aw_pid.c >> Anti-windup PID controller
------------------------------------------------------------------------------------------------------*/
#include "dmctype.h"
#include "aw_pid.h"
// include the header for PID data structure definition
void aw_pid_calc(AW_PID * v)
{
float32 uk;
v->Err = v->Ref - v->Fdb;
v->Up = v->Kp*v->Err; // Compute the proportional output
// Compute the integral output
if (v->kw==0)
v->Ui = v->Ui + v->Ki*v->Err;
else if (v->kw==1)
{
if ((v->SatErr==0) || ( v->Err*v->SatErr>0))
v->Ui = v->Ui + v->Ki*v->Err;
}
else
v->Ui = v->Ui + v->Ki*v->Err + v->Kc*v->SatErr;
// Compute the derivative output
// v->Ud = v->Ud1/(v->N+1)+v->Kd*(v->Err - v->Err_1)*v->N/(v->N+1);
v->Ud=v->Kd*(v->Err - v->Err_1);
// Compute the pre-saturated output
uk = v->Up + v->Ui + v->Ud;
v->OutPreSat = uk;
// Saturate the output
if (v->OutPreSat > v->OutMax)
v->Out = v->OutMax;
else if (v->OutPreSat < v->OutMin)
v->Out = v->OutMin;
else
v->Out = v->OutPreSat;
// Compute the saturate difference
v->SatErr = v->Out - v->OutPreSat;
// Update the relevant variables
v->Err_1 = v->Err;
v->Ud1 = v->Ud;
}
二、增量式PID
增量式PID
• 增量式算法不需要对积分项累加,控制量增量只与近几次的误差有关,计算误差对控制量计算的影响较小。而位置式算法要对近几次的偏差的进行积分累加,容易产生较大的累加误差;
• 增量式算法得出的是控制量的增量,例如在阀门控制中,只输出阀门开度的变化部分,误动作影响小,必要时还可通过逻辑判断限制或禁止本次输出,不会严重影响系统的工作;而位置式的输出直接对应对象的输出,因此对系统影响较大;
• 增量式算法控制输出的是控制量增量,并无积分作用,因此该方法适用于执行机构带积分部件的对象,如步进电机等,而位置式算法适用于执行机构不带积分部件的对象,如电液伺服阀;
• 积分饱和现象是位置式PID 算法应用常见的一种现象,因此对于位置式PID 算法除了需要对输出进行限幅外还需要对积分输出进行限幅,而增量式算法很好地避免了积分饱和现象,因此在增量式PID 控制算法中只需要对输出限幅,而无需积分限幅。
2.1实现
2.1.1头文件
/*
* eh_pid.h
*
* Created on: 2021年10月10日
* Author: longchentian
*/
#ifndef EH_PID_H_
#define EH_PID_H_
typedef struct {
float32 Ref; // 输入:参考输入 Input: Reference input
float32 Fdb; // 输入:反馈输入 Input: Feedback input、
float32 Err; //变量:误差信号e(k)
float32 Err_1; // 变量:误差信号e(k-1) Variable: Error
float32 Err_2; // 变量:误差信号e(k-2) Variable: Error
float32 umax; // 参数:控制量的饱和限幅值
float32 Ts; // 控制周期
float32 Kp; // 参数:比例增益 Parameter: Proportional gain
float32 Ki; // 参数:积分增益 Parameter: Integral gain
float32 Kd; // 参数:微分增益Parameter: Derivative gain
float32 OutPreSat; // 变量:饱和输出 Variable: Pre-saturated output
float32 OutMax; // 参数:最大输出 Parameter: Maximum output
float32 OutMin; // 参数:最小输出 Parameter: Minimum output
float32 Out; // 输出:SP_PID输出 Output: SP_PID output
void (*calc)(); // 计算函数指针 Pointer to calculation function
} EH_PID;
typedef EH_PID* EH_PID_handle;
/*-----------------------------------------------------------------------------
默认初始化 Default initalizer for the AW_PID object.
-----------------------------------------------------------------------------*/
#define EH_PID_DEFAULTS { 0, 0, 0, 0, 0, 0, 0,\
0, 0, 0, \
0, 0, 0, 0, \
(void (*)(Uint32)) eh_pid_calc }
void eh_pid_calc(EH_PID_handle);
#endif /* EH_PID_H_ */
2.1.2源文件
#include "dmctype.h"
#include "eh_pid.h"
// include the header for PID data structure definition
void eh_pid_calc(EH_PID * v)
{
float32 Delta_Err; //e(k)-e(k-1)
float32 Last_Delta_Err; //e(k-1)-e(k-2)
float32 uk; //本次调节输出值
v->Err = v->Ref - v->Fdb;
Delta_Err=v->Err-v->Err_1;
Last_Delta_Err=v->Err_1-v->Err_2;
uk=v->Out+v->Kp*Delta_Err+v->Ki* v->Err +v->Kd*(Delta_Err-Last_Delta_Err);
v->OutPreSat = uk;
// Saturate the output
if (v->OutPreSat > v->OutMax)
v->Out = v->OutMax;
else if (v->OutPreSat < v->OutMin)
v->Out = v->OutMin;
else
v->Out = v->OutPreSat;
v->Err_2=v->Err_1;
v->Err_1= v->Err ;
}
三、调用范例
//初始化
EH_PID pid3=EH_PID_DEFAULTS;
pid3.Kp = 0.459750444;
pid3.Ki = 0.0539999164;
pid3.Kd = 0.595000153;
pid3.Ts = Ts;
pid3.OutMax = 12;
pid3.OutMin = 0;
pid3.Ref = SpeedRef;
//闭环反馈
pid3.Fdb = speed;
pid3.calc(&pid3);
control_uk = pid3.Out;