C语言编程,怎么计算PID控制

C语言编程,怎么计算PID控制,第1张

Step 7写的PID控制的FC模块。带"_IN"与带"_OUT"的变量,如果前缀是一样的,要求连接同一个变量。

FUNCTION FC1 : VOID

VAR_INPUT

Run:BOOL//True-运行,False-停止

Auto:BOOL//True-自动,False-手动

ISW:BOOL//True-积分有效,False-积分无效

DSW:BOOL//True-微分有效,False-微分无效

SetMV:REAL//手动时的开度设定值

SVSW:REAL//当设定值低于SVSW时,开度为零

PV:REAL//测量值

SV:REAL//设定值

DeadBand:REAL//死区大小

PBW:REAL//比例带大小

IW:REAL//积分带大小

DW:REAL//微分带大小

dErr_IN:REAL//误差累积

LastPV_IN:REAL//上一控制周期的测量值

END_VAR

VAR_OUTPUT

MV:REAL//输出开度

dErr_OUT:REAL//误差累积

LastPV_OUT:REAL//上一控制周期的测量值

END_VAR

VAR

Err:REAL//误差

dErr:REAL//误差累积

PBH:REAL//比例带上限

PBL:REAL//比例带下限

PVC:REAL//测量值在一个控制周期内的变化率,即测量值变化速率

P:REAL//比例项

I:REAL//积分项

D:REAL//微分项

END_VAR

IF Run=1 THEN

IF Auto=1 THEN

IF SV>=SVSW THEN

Err:=SV-PV

PBH:=SV+PBW

PBL:=SV-PBW

IF PV<PBL THEN

MV:=1

ELSIF PV>PBH THEN

MV:=0

ELSE

P:=(PBH-PV)/(PBH-PBL)//计算比例项

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////以下为积分项的计算//////////////////////////////////////////////////////////////

IF ISW=1 THEN

dErr:=dErr_IN

IF (PV<(SV-DeadBand)) OR (PV>(SV+DeadBand)) THEN

IF (dErr+Err)<(0-IW) THEN

dErr:=0-IW

ELSIF (dErr+Err)>IW THEN

dErr:=IW

ELSE

dErr:=dErr+Err

END_IF

END_IF

I:=dErr/IW

dErr_OUT:=dErr

ELSE

I:=0

END_IF

/////////////////////////////////////////////以上为积分项的计算//////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////州谈早/////////////////////////////////////

/////////////////////////////////////////////以下为微分项的计算//////////////////////////////////////////////////////////////

IF DSW=1 THEN

PVC:=LastPV_IN-PV

D:=PVC/DW

LastPV_OUT:=PV

ELSE

D:=0

END_IF

/////////////////////////////////////////////以上为微分项的计算//////////////////////////////////////////////////////////////

//////////////////////册雀///////////////////////////////////////////////////////////////////////////////////////////////////////

IF (P+I+D)>1 THEN

MV:=1

ELSIF (P+I+D)<0 THEN

MV:=0

ELSE

MV:=P+I+D

END_IF

END_IF

ELSE

MV:=0

END_IF

ELSE

MV:=SetMV

END_IF

ELSE

MV:=0

END_IF

END_FUNCTION

进行整定时先进行P调节,使I和D作用无效,观察温度变化曲线,若变化曲线多次出现波形则应该放大比例(P)参数,若变侍穗化曲线非常平缓,则应该缩小比例(P)参数。比例(P)参数设定好后,设定积分(I)参数,积分(I)正好与P参数相反,曲线平缓则需要放大积分(I),出现多次波形则需要缩小积分(I)。比例(P)和积分(I)都设定好以后设定微分(D)参数,微分(D)参数与比例(P)参数的设定方法是一样的。

当初写这段程序的就是为了使用调功器来控制炉子的温度的,已经在我单位的调功器上运行成功了,还有就是我单位的调功器没有使用微分(D),只是用了比例(P)和积分(I)。

基本流程

积分环节:主要是用来消除 静差 (系统稳定后输出值和设定值之间的差值,积分环节实际袜腊唯上就是偏差累积的过程,把累积的误差加到原来系统上以抵消系统造成的静差)

微分环节:反映了偏差信号的变化规律,根据偏差信号的变化规律来进行超前调节,从而增加系统的快速性

对上述公式进行离散化(采样):两个公式

增量型PID:

通过告培增量型PID公式可以看出,最终表达结果和最近三次的偏差有关,最终输出结果应该为:

首先定义结构变量体:

然后初始化变量

最后编写控制算法

基本算法,没有考虑死区问题,没有设定上下限

在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成局纳PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应的极限控制量,从而引起较大的超调,甚至是振荡。

为了克服这个问题,引入积分分离的概念,即当被控量和设定值偏差较大时,取消积分作用;当被控量接近设定值时,引入积分控制,以消除静差,提高精度。

abs :绝对值

令index=0使积分环节失效

积分饱和现象:如果系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置。此时计算器输出量超出正常运行范围而进入饱和区,一旦系统出现反向偏差,输出量将逐渐从饱和区退出,进入饱和区越深则退出饱和区时间越长,在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应改变,造成性能恶化。

采用梯形积分能够减小余差,提高精度

改变积分系数,若偏差大,积分作用减弱,系数减小;若偏差小,积分作用增强,系数增大。

变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小对应。

使整个系统的稳定速度非常快

比例系数Kp的作用是加快系统的响应速度提高系统的调节精度

积分系数Ki的作用是消除系统的稳态误差

微分系数Kd的作用是改善系统的动态特性

反应系统性能的两个参数是系统误差和误差变化律

#include <stdlib.h>

#include "global_varible.h"

/****************************************************************************

* 模块名: PID

* 描述: PID调节子程序

* 采用PID-PD算法。在偏差稿举历绝对值大于△e时,用PD算法,以改善动态品质。

* 当偏差绝对值小于△e时,用PID算法,提高稳定精度。

* PIDout=kp*e(t)+ki*[e(t)+e(t-1)+...+e(1)]+kd*[e(t)-e(t-1)]

*============================================================================

* 入口: 无

* 出口: 无

* 改变: PID_T_Run=加热时间控制

*****************************************************************************/

void PID_Math(void)

{

signed long ee1 //偏差一阶

//signed long ee2 //偏差二阶答悉

signed long d_out //积分输出

if(!Flag_PID_T_OK)

return

Flag_PID_T_OK=0

Temp_Set=3700 //温度控制设定值37.00度

PID_e0 = Temp_Set-Temp_Now //本次偏差

ee1 = PID_e0-PID_e1 //计算一阶偏差

//ee2 = PID_e0-2*PID_e1+PID_e2 //计算二阶偏差

if(ee1 >500) /键搜/一阶偏差的限制范围

ee1 = 500

if(ee1 <-500)

ee1 = -500

PID_e_SUM += PID_e0 //偏差之和

if(PID_e_SUM >200) //积分最多累计的温差

PID_e_SUM = 200

if(PID_e_SUM <-200)

PID_e_SUM = -200

PID_Out = PID_kp*PID_e0+PID_kd*ee1 //计算PID比例和微分输出

if(abs(PID_e0) <200) //如果温度相差小于1.5度则计入PID积分输出

{

if(abs(PID_e0) >100) //如果温度相差大于1度时积分累计限制

{

if(PID_e_SUM >100)

PID_e_SUM = 100

if(PID_e_SUM <-100)

PID_e_SUM = -100

}

d_out = PID_ki*PID_e_SUM //积分输出

if(PID_e0 <-5) //当前温度高于设定温度0.5度时积分累计限制

{

if(PID_e_SUM >150)

PID_e_SUM = 150

if(PID_e_SUM >0) //当前温度高于设定温度0.5度时削弱积分正输出

d_out >>= 1

}

PID_Out += d_out //PID比例,积分和微分输出

}

else

PID_e_SUM=0

PID_Out/=100 //恢复被PID_Out系数放大的倍数

if(PID_Out >200)

PID_Out=200

if(PID_Out<0)

PID_Out=0

if(PID_e0 >300) //当前温度比设定温度低3度则全速加热

PID_Out=200

if(PID_e0 <-20) //当前温度高于设定温度0.2度则关闭加热

PID_Out=0

Hot_T_Run=PID_Out //加热时间控制输出

PID_e2 = PID_e1 //保存上次偏差

PID_e1 = PID_e0 //保存当前偏差

}

////////////////////////////////////////////////////////////void PID_Math() end.


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12234566.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-22
下一篇 2023-05-22

发表评论

登录后才能评论

评论列表(0条)

保存