您的位置:首页 > 编程语言 > C语言/C++

工业PID控制方法的C语言实现详解

2015-05-14 11:57 323 查看
1 典型环节的微分方程、传递函数及C语言实现方法

无论多么复杂的系统,总是可以由简单的子系统构成,分析典型环节的特点,其目的是为了通过典型环节的特点分析更为复杂的系统,实际工程应用中,真正完全通过理论的方式建立模型是非常困难的,实际的模型建立过程是一个复杂的过程,需要通过假设、验证、参数实验给定等多种手段分析完善模型内容,利用实验获取模型的方法又称作系统辨识技术,在下一节中将重点讲解。假设的过程,其实就是根据系统特点,综合典型环节的过程。将不同的环节通过四则运算给予不同的参数进行运算,从而接近真实的模型。从这个角度上讲,透彻理解典型环节的特点,无论对于理论分析系统,还是对于实际建立系统模型都具有重要的意义。

1.1 比例环节

比例环节是自然界普遍存在的一个环节,几乎所有的系统必定存在比例环节。比例环节的特点在于输入输出量成正比例关系,没有失真与延时。其微分方程可表示为:c(t) = kr(t)。其传递函数可表示为:G(s)=c(s)/R(s)。

对于比例环节而言,C语言实现相对比较简单。下面进行C语言实现过程的说明。

float ProElement(float K, float GiveValue)
{
float  result;
result = K*GiveValue;
return result;
}


以上代码用C语言实现了比例环节的处理。使用时直接定义一全局变量,例如float ResultValue; 然后直接调用该函数即可,例如 ResultValue = ProElement(0.1, 10);返回的ResultValue = 1.0。

1.2 惯性环节

惯性环节是自然界普遍存在的另一个环节,其存在的广泛性不亚于比例环节,任何系统,只有时间精度足够高,都必然存在一定的惯性性能。惯性环节的特点是对变化的输入量,输出量不能立刻复现,或多或少的存在一定的延时,在延时的时间内,输出量会逐渐接近输入的给定值。其微分方程可表示为:T(dc(t)/dt)+c(t)=r(t)。其中T为惯性时间常数,T越大,惯性越大,当延时时间约为3-4倍的T时,输出接近输入给定值。其传递函数可表示为:G(s)=1/(Ts+1)。下面讲解用C语言实现惯性环节的过程。这里注意系统的输出为c(t),输入为r(t)。首先将微分方程转化为差分方程的形式:T(c(t)−c(t−1)/t−(t−1))+c(t)=r(t),化简该公式可表示为:c(t)=(r(t)+Tc(t−1))/(T+1)。上述公式表明,当前时刻输出量c(t)与上一时刻输出量c(t-1)相关。利用该原理,可使用C语言通过迭代函数实现。首先定于全局变量,存放上一时刻输出量的值float ResultValueBack。初值设定为0,然后可通过下面函数实现迭代过程。

float InertialElement(float T, float GiveValue)
{
float  result;
result = (T*ResultValueBack + GiveValue)/(1+T);
ResultValueBack = result;
return result;
}


1.3 积分环节

积分环节是设计校正系统是常用的一个环节,经典的PID算法就分别用到了比例、积分、微分三个环节。积分环节的显著特点是,输出量与输入量的积分成正比例关系,当输入量消失后,输出量具有记忆功能,能够储存部分能量。其微分方程可表示为:c(t)=Integral(r(d)dt)。其传递函数可表示为:G(s)=1/s。对于离散系统而言,积分过程实质上是系统输入量的累加和,用C语言实现积分过程可表示为:

定义全局变量ResultValue

float IntegralElement(float GiveValue)
{
float  result;
ResultValue = ResultValue + GiveValue;
result = ResultValue;
return result;
}


1.4 微分环节

微分环节也经常运用到校正环节中,如果被控系统存在较大的惯性环节,可考虑校正环节中加入微分环节,微分环节关注的是给定变化率的特性,所以在一定程度上具有系统预测能力。微分环节根据微分阶数的不同分为一阶微分方程、二阶微分方程及多阶微分方程。这里我们只用C语言实现一阶和二阶微分方程,多阶微分方程可根据实际需要,读者利用本书提到的基本方法自行实现。微分环节的微分方程可表示为,一阶:c(t)=dr(t)dt二阶:c(t)=Tdr(t)/dt+r(t)其传递函数可表示为,一阶:G(s)=s二阶:G(s)=Ts+1下面是C语言实现一阶微分方程与二阶微分方程的过程。定义全局变量GiveValueBack。

float DervativeElementOne(float GiveValue) //一阶微分实现
{
float  result;
result = GiveValue -  GiveValueBack;
GiveValueBack = GiveValue;
return result;
}


float DervativeElementTwo(float T, float GiveValue)//二阶微分实现
{
float  result;
result = (T+1) GiveValue - GiveValueBack;
GiveValueBack = GiveValue;
return result;
}


1.5 滞后环节

滞后环节不同与惯性环节,滞后环节的特点是输入量给定经过一段延时后,输出信号完全复现输入信号。惯性环节则是从输入量给定开始输出量便逐渐趋近于输入量。读者要理解清楚这两个环节的不同。滞后环节的微分方程不易表示,但是C语言实现相对简单,只需要延时赋值即可。

float DelayElement(float Time, float GiveValue)  //Time表示延时时间
{
float  result;
if( T > Time)
{
result =  GiveValue;
}else{
result = 0;
}
return result;
}


震荡环节在平常的控制设计中并不常用,这里暂不做详细介绍。

1.6 小结

以上5小节,详细论述了典型环节的微分方程,传递函数,及C语言实现的方法步骤。需要反复强调的是,用C语言实现系统模型,首先将系统模型的传递函数转化为微分方程的形式,然后再将微分方程转化为差分方程的形式,最后根据差分方程表达式用C语言函数实现。这是控制方法用C语言实现的核心所在。为什么要讲述典型环节的,因为无论多么复杂的系统,也无论多么困难的系统,其无非是几种典型环节的组合与排列的过程。只有弄清楚基本的典型环节,才能在后续的问题分析与解决中游刃有余。

2 PID控制及其C语言实现

PID校正控制方式是工程应用中使用最为广泛的一种线性系统控制方法。其核心思想是利用比例、积分、微分三个环节作为校正环节,提高系统的响应速度、稳定性与准确性。其中比例环节能够成比例的反映误差信号,误差信号一旦产生,比例环节立即产生控制作用,以减少变差;积分环节能够有效的消除系统的静态误差,在系统控制过程中,只要存在误差,则积分一直持续,直至误差完全消除,积分环节的强弱直接决定了系统消除误差时间的快慢;微分环节反映了偏差信号的变化趋势,具有一定的预测功能,能够在偏差信号变化太大之前引入一个有效的早期修正信号,加快系统的动作速度,减少调节时间。

2.1 基本PID控制原理及实现

在工业应用中,最常用的控制方式是PID控制,PID控制框图如图2-1所示。



图2-1 PID控制框图

PID是一种线性控制方法,其运用给定值R(t)与实际输出值C(t)的偏差e(t)作为控制量进行控制。其控制规律的微分方程可表示为



其中Kp为比例系数、Ki为积分系数、Kd为微分系数。这里需要注意的是,并非系统最终输出,而是被控对象之前节点的值。举个例子说明,假如控制电机以某一转速运行,通过PID运算得到的值可能是驱动桥电路的PWM开通值,而并非电机的转速值,PWM开通后作用到电机上才能最终转化到转速上。下面将微分方程转化为差分方程,再用C语言实现。

这里我们采用纯惯性环节作为被控对象,用C语言设计最一般的PID算法,并进行仿真验证。PID的C语言实现过程如下:

float PID(float Kp, float Ki, float Kd, float GiveValue, float ActualValue)
{
float result;
float Err,KpWork, KiWork, KdWork;
Err = GiveValue - ActualValue;
KpWork = Kp*Err;
KiWork = Ki*PIDErrADD;
KdWork = Kd*(Err-ErrBack);
result = KpWork+KiWork+KdWork;
PIDErrADD = PIDErrADD + Err;
ErrBack = Err;
return result;
}


取Kp = 4.5,Ki = 0.5,Kd = 0.1,给定值为阶跃信号100.2,惯性环节的惯性系数取3。最终输出的数据取前100个点波形如图2-2所示。



图2-2 一般PID惯性环节仿真数据图

2.2 积分分离PID控制实现

控制环节中引入积分环节的目的,主要是为了消除静态误差,提高控制的精度。但是,在实际应用中,当系统处于启动、结束或大幅增减设定的过程中时,短时间内系统输出有很大的偏差,如此便会在短时间内产生较大的积分累计,导致控制量超过执行机构可能允许的最大动作范围对应的极限控制量,进而引起系统较大超调,甚至造成系统的震荡。

引入积分分离的目的在于解决上述问题,其基本思想是,当控制量接近给定值时,引入积分控制,消除静态误差;当控制量与给定值相差较大时,取消积分作用,避免积分累加和过大造成的系统不稳定因素增加。

这里我们采用纯惯性环节作为被控对象,用C语言设计积分分离的PID算法,并进行仿真验证。PID的C语言实现过程如下:

float SeqIntPID(float Kp, float Ki, float Kd, float GiveValue, float ActualValue)
{
float result;
float Err,KpWork, KiWork, KdWork;
Err = GiveValue - ActualValue;
KpWork = Kp*Err;
KiWork = Ki*SeqIntPIDErrADD;
KdWork = Kd*(Err-SeqIntErrBack);
if(fabs(Err) > 100)
{
result = KpWork+KdWork;
}else{
result = KpWork+KiWork+KdWork;
}
SeqIntPIDErrADD = SeqIntPIDErrADD + Err;
SeqIntErrBack = Err;
return result;
}


取Kp = 4.5,Ki = 0.5,Kd = 0.1,给定值为阶跃信号100.2,惯性环节的惯性系数取30。最终输出的数据取前100个点波形如图2-3所示。



图2-3 积分分离PID惯性环节仿真数据图

2.3 抗积分饱和PID控制实现

实际系统的积分项饱和是指,在实际应用系统中,由于误差在一段较长的时间内在一个方向上积累,造成积分的累计误差和过大,从而造成整个积分环节的值过大,当系统趋于稳定或者超调过冲的时候,比例项与微分项的调节作用相对减弱,从而减慢调节速度,甚至长时间不能够到达给定值。

比如对于一个较大的惯性系统,给定系统一个值后,当控制系统极限输出时,惯性系统仍然需要一段时间消除误差,那么在这段时间内容,正常误差一直在累加,等到输出值大于给定值时,由于前面一段时间累积的误差和太大,从而不能很快的通过误差调整过来。图2-4说明了积分饱和的概念。



图2-4 积分饱和说明图

如图2-4所示,u为控制器输出,X为执行机构的开度,若系统存在一个方向的偏差,PID控制器的输出由于积分作用累积,导致执行机构达到极限位置,如果此时控制器输出u继续增大,执行器的实际开度已经不可能再增大,此时计算机输出的控制量超出了正常运行的范围而进入饱和状态,一旦系统出现反向偏差,控制器的输出u会逐渐的退出饱和区。但是进入饱和区越深,退出所需时间越久,从而造成系统的失控。为了防止积分项饱和,需要对积分项进行限制。实际当中常用的限制方法方法有两种:

方法一:直接限制积分累加和最大值。所谓直接限制积分累加和是指通过限制积分累加和最大值的方式限制积分项的值使其不能过于深入的进入饱和状态。比如稳定状态下积分累加和的值是100,那么可以将积分累加和的上下限分别限定到+110与-110,但是此值的选择需要斟酌,此值选取太小,容易造成系统调整速度慢,甚至不能调整到给定值,此值限制的太大,起不到抗饱和积分的作用。在实际应用中,此种方法以其操作简单被广泛用到。

方法二:动态限制积分累加和。该方法的思路是在计算本次输出u(k)时,首先判断上一时刻的控制量u(k-1)是否已经超出限制范围;若超出最大限值范围,则只累加负偏差;反之则只累加正偏差。这种算法可以避免控制量长时间停留在饱和区。

以上两种方法,对于方法一用C语言实现较为简便,不再赘述,本处着重对第二种方法进行C语言实现。

float OverIntPID(float Kp, float Ki, float Kd, float GiveValue, float ActualValue)
{
float result;
float Err,KpWork, KiWork, KdWork;
Err = GiveValue - ActualValue;
if(OverIntResultBack > 120)
{
if(Err < 0)
{
OverIntPIDErrADD = OverIntPIDErrADD + Err;
}
}else if(OverIntResultBack < 120){
if(Err > 0)
{
OverIntPIDErrADD = OverIntPIDErrADD + Err;
}
}else{
OverIntPIDErrADD = OverIntPIDErrADD + Err;
}

KpWork = Kp*Err;
KiWork = Ki*OverIntPIDErrADD;
KdWork = Kd*(Err-OverIntErrBack);
result = KpWork+KiWork+KdWork;
OverIntErrBack = Err;
OverIntResultBack = result;
return result;
}


取Kp = 4.5,Ki = 0.5,Kd = 0.1,给定值为阶跃信号100.2,惯性环节的惯性系数取30。最终输出的数据取前100个点波形如图2-5所示。



图2-5 抗饱和积分PID惯性环节仿真数据图

对比2-3与2-5,可以发现抗饱和积分可以使系统更加稳定。

2.6 其他PID控制实现

PID的在工业上广泛的应用,具体使用过程中会针对不同的控制系统研究选择不同的PID控制形式,PID实际应用中多种多样,上述五个小节中讲述了五种PID的实现形式,实际的工业应用中常用的PID还有带前馈的PID、基于滤波器的PID以及智能PID等其他使用形式,读者需掌握系统与控制校正环节的分析方法,灵活运用,实现适合自身系统的PID控制器。

关注技术人生公众平台,获取更多技术资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 控制 方法 系统