PID算法实现及参数整定图解(附代码) - Go语言中文社区

PID算法实现及参数整定图解(附代码)


一、 PID含义

PID是英文单词比例(Proportion),积分(Integral),微分(Differential coefficient)的缩写。PID调节实际上是由比例、积分、微分三种调节方式组成,它们各自的作用如下:

比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。

积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器。

微分调节作用:微分作用反映系统偏差信号的变化率,具有预见性,能预见偏差变化的趋势,因此能产生超前的控制作用,在偏差还没有形成之前,已被微分调节作用消除。因此,可以改善系统的动态性能。在微分时间选择合适情况下,可以减少超调,减少调节时间。微分作用对噪声干扰有放大作用,因此过强的加微分调节,对系统抗干扰不利。此外,微分反应的是变化率,而当输入没有变化时,微分作用输出为零。微分作用不能单独使用,需要与另外两种调节规律相结合,组成PD或PID控制器。

离散式PID分为位置型和增量型。

二、 PID位置式计算公式:

 (式1-1)

式中 clip_image002clip_image003 u(n)——第k个采样时刻的控制,T   ——采样周期。

由于计算机的输出u(k)直接控制执行机构(如阀门),u(k)的值与执行机构的位置(如阀门开度)一一对应,所以通常称式(1-1)为位置式PID控制算法。

三、 PID增量式计算公式:

增量式计算公式可由(式1-1)推导得到:

由(1-1)可以得到控制器的第k-1个采样时刻的输出值为:

clip_image005(1-2)

将(1-1)与(1-2)相减并整理,就可以得到增量式PID控制算法公式为:

clip_image007(1-3

其中

clip_image009

由(1-3)可以看出,如果计算机控制系统采用恒定的采样周期T,一旦确定A、B、C,只要使用前后三次测量的偏差值,就可以由(1-3)求出控制量。

增量式PID控制算法与位置式PID算法(1-1)相比,计算量小得多,因此在实际中得到广泛的应用。

位置式PID控制算法也可以通过增量式控制算法推出递推计算公式:

clip_image011(1-4

(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调教总结

1.负反馈

自动控制理论也被称为负反馈控制理论。首先检查系统接线,确定系统的反馈为负反馈。例如电机调速系统,输入信号为正,要求电机正转时,反馈信号也为正(PID算法时,误差=输入-反馈),同时电机转速越高,反馈信号越大。其余系统同此方法。

2.PID调试一般原则

a.在输出不振荡时,增大比例增益P。
b.在输出不振荡时,减小积分时间常数Ti。
c.在输出不振荡时,增大微分时间常数Td。

3.一般步骤

a. 首先选取合适的采样周期T,这里先选取0.05S…待其余参数都调教好后,可再对比修改采样周期T.

clip_image013

T:0.05 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min

clip_image015

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

clip_image017

T:0.3 Kp:0.85 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min

clip_image019

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调试完成。

clip_image023

T:0.05 Kp:3 Ti:0 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min(实验证明此时速度加不到1档)

clip_image025

T:0.05 Kp:3 Ti:0.3 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min(此时速度可以达到1档,但超调过大)

clip_image027

T:0.05 Kp:2 Ti:0.3 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min

clip_image029

% 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调试完成。

clip_image031

% T:0.05 Kp:1 Ti:0.4 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min

clip_image033

% T:0.05 Kp:1 Ti:0.45 Td:0 占空比初始值(电机启动电压对应占空比):1620 速度加到一档400r/min

clip_image034

% 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__



版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Uncle_GUO/article/details/51367764
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-27 11:14:15
  • 阅读 ( 2442 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢