PID是英文单词比例(Proportion),积分(Integral),微分(Differential coefficient)的缩写。PID调节实际上是由比例、积分、微分三种调节方式组成,它们各自的作用如下:
比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。
积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器。
微分调节作用:微分作用反映系统偏差信号的变化率,具有预见性,能预见偏差变化的趋势,因此能产生超前的控制作用,在偏差还没有形成之前,已被微分调节作用消除。因此,可以改善系统的动态性能。在微分时间选择合适情况下,可以减少超调,减少调节时间。微分作用对噪声干扰有放大作用,因此过强的加微分调节,对系统抗干扰不利。此外,微分反应的是变化率,而当输入没有变化时,微分作用输出为零。微分作用不能单独使用,需要与另外两种调节规律相结合,组成PD或PID控制器。
离散式PID分为位置型和增量型。
二、 PID位置式计算公式:
式中 , u(n)——第k个采样时刻的控制,T ——采样周期。
由于计算机的输出u(k)直接控制执行机构(如阀门),u(k)的值与执行机构的位置(如阀门开度)一一对应,所以通常称式(1-1)为位置式PID控制算法。
三、 PID增量式计算公式:
增量式计算公式可由(式1-1)推导得到:
由(1-1)可以得到控制器的第k-1个采样时刻的输出值为:
将(1-1)与(1-2)相减并整理,就可以得到增量式PID控制算法公式为:
其中
由(1-3)可以看出,如果计算机控制系统采用恒定的采样周期T,一旦确定A、B、C,只要使用前后三次测量的偏差值,就可以由(1-3)求出控制量。
增量式PID控制算法与位置式PID算法(1-1)相比,计算量小得多,因此在实际中得到广泛的应用。
位置式PID控制算法也可以通过增量式控制算法推出递推计算公式:
(1-4)就是目前在计算机控制中广泛应用的数字递推PID控制算法。
式(1-3)也即:
Δu(k)=u(k)-u(k-1) = Kp*Δe(k)+ Ki*e(k)+ Kd*[Δe(k)-Δe(k-1)] ,式中Δe(k)=e(k)-e(k-1)
= Kp*[e(k)-e(k-1) + (T/Ti)*e(k) + Td*((e(k)-2*e(k-1)+e(k-2))/T)] (式1-2)
= Kp*(1+T/Ti+Td/T)*e(k) - Kp*(1+2*Td/T)*e(k-1) + Kp*Td/T*e(k-2)
= A*e(k) - B*e(k-1) + C*e(k-2) (式1-3)
式中:
Δu(k)——控制器(也称调节器)的输出增量;
e(k)——控制器的输入(常常是设定值与被控量之差,即e(k)=r(k)-c(k));
Ki=(Kp*T)/Ti 为积分系数
Kd=(Kp*Td)/T 为微分系数
式中:
T: 计算机控制系统的采样周期,其在选定后就不再改变。其选用原则是在被控系统反馈信号的反应时间要求内,尽量小。但过小会增加运算量。
Kp——控制器的比例放大系数;
Ti——控制器的积分时间;
Td——控制器的微分时间。
四、 优缺点
a) 增量式算法优点:①算式中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果;②计算机每次只输出控制增量,即对应执行机构位置的变化量,故机器发生故障时影响范围小、不会严重影响生产过程;③手动—自动切换时冲击小。当控制从手动向自动切换时,可以作到无扰动切换。
b) 位置式PID控制算法的缺点:当前采样时刻的输出与过去的各个状态有关,计算时要对e(k)进行累加,运算量大;而且控制器的输出u(k)对应的是执行机构的实际位置,如果计算机出现故障,u(k)的大幅度变化会引起执行机构位置的大幅度变化。
1、其实是位置式和增量式是一样的,增量式最后那个输出化解完和位置式一样。增量式PID可以通过 u(k) = u(k-1) + Δu(k) 得到位置式输出
2、增量型算法与位置型算法比较:
(1)增量型算法不需做累加,计算误差后产生的计算精度问题,对控制量的计算影响较小。位置型算法用到过去的误差的累加,容易产生较大的累加误差。
(2)增量型算法得出的是控制的增量,误动作影响小,必要时通过逻辑判断限制或禁止本次输出,不会影响系统的工作。位置型算法的输出是控制量的全部输出,误动作影响大。
(3)是的,增量式算法的主要优势体现在对积分环节的处理上,积分作用的累加效果会影响到输出的准确性。
(4)楼上的说法让我获益不少,一直没理解“避免误动作”的原因。另外,增量式算法易于实现手、自动的无扰动切换。
自动控制理论也被称为负反馈控制理论。首先检查系统接线,确定系统的反馈为负反馈。例如电机调速系统,输入信号为正,要求电机正转时,反馈信号也为正(PID算法时,误差=输入-反馈),同时电机转速越高,反馈信号越大。其余系统同此方法。
a.在输出不振荡时,增大比例增益P。
b.在输出不振荡时,减小积分时间常数Ti。
c.在输出不振荡时,增大微分时间常数Td。
a. 首先选取合适的采样周期T,这里先选取0.05S…待其余参数都调教好后,可再对比修改采样周期T.
% T:0.05 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.1 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.2 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/mi
% T:0.3 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.01 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
b.确定比例增益P
确定比例增益P 时,首先去掉PID的积分项和微分项,一般是令Ti=0、Td=0(具体见PID的参数设定说明),使PID为纯比例调节。输入设定为系统允许的最大值的60%~70%,由0逐渐加大比例增益P,直至系统出现振荡;再反过来,从此时的比例增益P逐渐减小,直至系统振荡消失,记录此时的比例增益P,设定PID的比例增益P为当前值的60%~70%。比例增益P调试完成。
T:0.05 Kp:3 Ti:0 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min(实验证明此时速度加不到1档)
T:0.05 Kp:3 Ti:0.3 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min(此时速度可以达到1档,但超调过大)
T:0.05 Kp:2 Ti:0.3 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.05 Kp:1 Ti:0.3 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
c.确定积分时间常数Ti
比例增益P确定后,设定一个较大的积分时间常数Ti的初值,然后逐渐减小Ti,直至系统出现振荡,之后在反过来,逐渐加大Ti,直至系统振荡消失。记录此时的Ti,设定PID的积分时间常数Ti为当前值的150%~180%。积分时间常数Ti调试完成。
% T:0.05 Kp:1 Ti:0.4 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.05 Kp:1 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
% T:0.05 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min
d.确定微分时间常数Td
积分时间常数Td一般不用设定,为0即可。若要设定,与确定 P和Ti的方法相同,取不振荡时的30%。
e.系统空载、带载联调,再对PID参数进行微调,直至满足要求。
1、C文件
/******************** (C) COPYRIGHT Adrian *************************************
* 文件名 :PID.c
* 描述 :增量式PID算法和位置式PID算法
* 作者 :Adrian
* 版本更新: 2016-05-01
* 硬件连接:
* 调试方式:J-Link-OB
**********************************************************************************/
#include"PID.h"
//采用增量式计算,采样周期为T时间
//Δu(k)=u(k)-u(k-1) = Kp*Δe(k)+ Ki*e(k)+ Kd*[Δe(k)-Δe(k-1)] ,式中Δe(k)=e(k)-e(k-1)
// = Kp*[e(k)-e(k-1) + (T/Ti)*e(k) + Td*((e(k)-2*e(k-1)+e(k-2))/T)] (式1-1)
// = Kp*(1+T/Ti+Td/T)*e(k) - Kp*(1+2*Td/T)*e(k-1) + Kp*Td/T*e(k-2)
// = A*e(k) - B*e(k-1) + C*e(k-2) (式1-2)
//式中:
// Δu(k)——控制器(也称调节器)的输出增量;
// e(k)——控制器的输入(常常是设定值与被控量之差,即e(k)=r(k)-c(k));
// Ki=(Kp*T)/Ti 为积分系数
// Kd=(Kp*Td)/T 为微分系数
//式中: T:采样周期
// Kp——控制器的比例放大系数;
// Ti——控制器的积分时间;
// Td——控制器的微分时间。
/**
* @file IncrementalPIDInit
* @brief 增量式PID参数初始化
* @param *S:PID结构体 Piont:目标值 T:采样周期 Kp:控制器的比例放大系数 Ti:控制器的积分时间; Td:控制器的微分时间;
* @retval 无
*/
void IncrementalPIDInit(IncrementalPID *S, int32_t Piont, double T, double Kp, double Ti, double Td)
{
S->SetPoint = Piont; //目标值
S->SumError = 0;
S->A = Kp*(1+T/Ti+Td/T); //
S->B = Kp*(1+2*Td/T); //
S->C = Kp*Td/T; //
S->NowError = 0; //当前误差
S->LastError = 0; //上次误差
S->PrevError = 0; //上上次误差
}
//Position type PID
/**
* @file IncrementalPIDCalc(式1-2)
* @brief 增量式PID迭代
* @param *S: x:根据反馈量得到的值(属性和Sptr->SetPoint一样)
* @retval PID调节后控制信号增量
*/
int32_t IncrementalPIDCalc(IncrementalPID *Sptr, int32_t x)
{
int32_t Out = 0;
Sptr->NowError = Sptr->SetPoint - x;
Out = Sptr->A * Sptr->NowError - Sptr->B * Sptr->LastError + Sptr->C * Sptr->PrevError; //(式1-2)
Sptr->PrevError = Sptr->LastError;
Sptr->LastError = Sptr->NowError;
return (Out);
}
void PointSetIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID设置目标值
{
Sptr->SetPoint = Piont; //目标值
}
void PointSubIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID目标值递减
{
Sptr->SetPoint = Sptr->SetPoint - Piont; //目标值
}
void PointAddIncrementalPID(IncrementalPID *Sptr, int32_t Piont)//增量式PID目标值递增
{
Sptr->SetPoint = Sptr->SetPoint + Piont; //目标值
}
/**
* @file IncrementalPIDInit1
* @brief 增量式PID参数初始化
* @param *S:PID结构体 Piont:目标值 T:采样周期 Kp:控制器的比例放大系数 Ti:控制器的积分时间; Td:控制器的微分时间;
* @retval 无
*/
void IncrementalPIDInit1(IncrementalPID1 *S, int32_t Piont, double T, double Kp, double Ti, double Td)
{
S->SetPoint = Piont; //目标值
S->Kp = Kp; //
S->Ki = Kp*T/Ti; //
S->Kd = Kp*Td/T; //
S->NowError = 0; //当前误差
S->LastError = 0; //上次误差
S->PrevError = 0; //上上次误差
S->SumError = 0;
}
/**
* @file IncrementalPIDCalc1(式1-1)
* @brief 增量式PID迭代
* @param *S: x:根据反馈量得到的值(属性和Sptr->SetPoint一样)
* @retval PID调节后控制信号增量
*/
int32_t IncrementalPIDCalc1(IncrementalPID1 *Sptr, int32_t NowPoint)
{
int32_t Out = 0;
Sptr->NowError = Sptr->SetPoint - NowPoint;
Out = Sptr->Kp * (Sptr->NowError - Sptr->LastError) + Sptr->Ki * Sptr->NowError + Sptr->Kd * (Sptr->NowError - 2 * (Sptr->LastError) + Sptr->PrevError); //(式1-1)
Sptr->PrevError = Sptr->LastError;
Sptr->LastError = Sptr->NowError;
return (Out);
}
/*********************************************END OF FILE**********************/
2、头文件
#ifndef PID_H__
#define PID_H__
#include "stm32f10x.h"
typedef struct IncrementalPID
{
int32_t SetPoint; //设定目标 Desired Value
// double Proportion; //比例常数 Proportional Const
// double Integral; //积分常数 Integral Const
// double Derivative; //微分常数 Derivative Const
double A; //
double B; //
double C; //
int32_t NowError; //Error[0]
int32_t LastError; //Error[-1]
int32_t PrevError; //Error[-2]
int64_t SumError; //误差累计
} IncrementalPID;
void IncrementalPIDInit(IncrementalPID *S, int32_t Piont, double T, double Kp, double Ti, double Td);
int32_t IncrementalPIDCalc(IncrementalPID *Sptr, int32_t x);
void PointSetIncrementalPID(IncrementalPID *Sptr, int32_t Piont);//增量式PID设置目标值
void PointSubIncrementalPID(IncrementalPID *Sptr, int32_t Piont);//增量式PID目标值递减
void PointAddIncrementalPID(IncrementalPID *Sptr, int32_t Piont);//增量式PID目标值递增
// PID结构声明
typedef struct IncrementalPID1
{
int32_t SetPoint; //设定目标 Desired Value
double Kp; //比例常数 Proportional Const
double Ki; //积分常数 Integral Const
double Kd; //微分常数 Derivative Const
int32_t NowError; //Error[0]
int32_t LastError; //Error[-1]
int32_t PrevError; //Error[-2]
int64_t SumError; //Sums of Errors
}IncrementalPID1;
#endif //PID_H__