用SCL也可以实现多重背景的,这里我就直接封装一个PID 精简PID参数的引脚 增加了PID的正作用和反作用,手动和自动切换过程的无扰动切换等等。。请看程序
//############################################################################
//对FB41 PID控制块进行二次封装简化PID引脚的显示
//1.保留原有PID所有功能
//2.新增加一些接口
//3.积分和微分时间类型修改为DINT类型
//4.增加停止模式,可利用该模式进行调试或者程序连锁,比如某时段把该设备若是阀门即可当开关门来进行控制
// EBC 20171222
//###########################################################################
FUNCTION_BLOCK FB10
TITLE = 'NEW PID'
// FB41块的二次封装
//简化FB41的接入引脚
VERSION: '1.0'
AUTHOR: EBCLW
NAME: NEW_PID
FAMILY: EBC
KNOW_HOW_PROTECT
VAR_INPUT
PV_IN :REAL:= 0.0; // 过程值IN: REAL
SP_INT :REAL:= 0.0; //设定值 IN: REAL
GAIN_NOT:BOOL:=0;//真:反作用;假:正作用
P:REAL:=2.0;//比例参数REAL
I:DINT:=20;//积分参数DINT
D:DINT:=10;//微分参数DINT
MAN_ON :BOOL:=0; // 手自动切换真:手动,假:自动
MAN :REAL:= 0.0; // 手动模式手动输入值值为百分比
LMN_HLM :REAL:= 100.0; //操作值上限,限定PID输出
LMN_LLM:REAL := 0.0; // 操作值下限,限定PID输出
STOP:BOOL:=FALSE;//停止模式 真:启用
STOP_COC:BOOL:=FALSE;//停止模式时全开或全关 真:全开,假:全关
END_VAR
VAR_OUTPUT
// Output Parameters
LMN:REAL; //PID输出值百分比
LMN_PER:WORD; // 接模拟量输出通道
END_VAR
VAR
MS:DINT:=1000;//积分微分时间系数 1000代表秒
P_SEL :BOOL:=TRUE; //启用比例作用
I_SEL :BOOL:= TRUE; //启用积分作用
D_SEL:BOOL := FALSE; //启用微分作用
COM_RST :BOOL:= FALSE; //该块有一个在设置输入COM_RST时自动执行的初始化程序。
INT_HOLD :BOOL:=FALSE; //积分作用暂停
I_ITL_ON :BOOL:= FALSE; //积分作用初始化打开
CYCLE :TIME:= T#1S; //采样时间
PV_PER :WORD:=W#16#0; //过程值(通道值)
TM_LAG:TIME := T#2S; //微分作用的时间延迟
DEADB_W :REAL:=0.0; //死区带宽
PV_FAC :REAL:=1.0; // 过程变量因子"输入与过程变量相乘,调整过程变量范围。
PV_OFF:REAL := 0.0; // 程变量偏移量"输入与过程变量相加,调整过程变量范围。
LMN_FAC:REAL :=1.0; // 将"操作值因子"输入与操作值相乘,调整操作值范围。
LMN_OFF :REAL:= 0.0; // 将"操作值偏移量"与操作值相加,调整操作值范围。
I_ITLVAL:REAL :=0.0; //积分作用的初始化值。
DISV:REAL := 0.0; //前馈控制干扰变量
GAIN:REAL := 2.0; // 比例参数,正反作用后的比例参数
PVPER_ON :BOOL:= FALSE; //启用过程变量外设
TI :TIME; //转换后的积分值"复位时间"输入决定积分器的时间响应。
TD :TIME;//转换后的微分值 "微分时间"输入决定微分单元的时间响应。
//FB41输出值
QLMN_HLM:BOOL; //到达操作值上限
QLMN_LLM:BOOL; //到达操作值下限
LMN_P:REAL; // 比例输出
LMN_I:REAL; // 积分输出
LMN_D:REAL; // 微分输出
PV:REAL; // 有效过程变量输出值
ER:REAL; // 出错信号
NEW_PID:CONT_C;//调用FB41PID控制块
END_VAR
//判断PID正反作用
IF GAIN_NOT THEN
GAIN:=P*(-1.0);
ELSE
GAIN:=P;
END_IF;
//上位机输入双整型的I/D值参数 转换为TIME类型
TI := DINT_TO_TIME (I * MS);
TD := DINT_TO_TIME (D * MS);
//调用FB41程序
(*
注意调用的时候需要拷贝库里面的FB41拷贝到项目下否则直接编译会调用成SFB41,因为名字是一致的
*)
NEW_PID(COM_RST := COM_RST // IN: BOOL
,MAN_ON := MAN_ON // IN: BOOL
,PVPER_ON := PVPER_ON // IN: BOOL
,P_SEL :=P_SEL // IN: BOOL
,I_SEL :=I_SEL // IN: BOOL
,INT_HOLD := INT_HOLD// IN: BOOL
,I_ITL_ON :=I_ITL_ON // IN: BOOL
,D_SEL :=D_SEL // IN: BOOL
,CYCLE :=CYCLE // IN: TIME
,SP_INT := SP_INT // IN: REAL
,PV_IN := PV_IN // IN: REAL
,PV_PER := PV_PER // IN: WORD
,MAN := MAN // IN: REAL
,GAIN :=GAIN // IN: REAL
,TI := TI // IN: TIME
,TD := TD // IN: TIME
,TM_LAG :=TM_LAG // IN: TIME
,DEADB_W := DEADB_W // IN: REAL
,LMN_HLM := LMN_HLM // IN: REAL
,LMN_LLM :=LMN_LLM // IN: REAL
,PV_FAC :=PV_FAC // IN: REAL
,PV_OFF :=PV_OFF // IN: REAL
,LMN_FAC :=LMN_FAC // IN: REAL
,LMN_OFF :=LMN_OFF // IN: REAL
,I_ITLVAL :=I_ITLVAL // IN: REAL
,DISV := DISV // IN: REAL
);
QLMN_HLM:= NEW_PID.QLMN_HLM; // OUT: BOOL
QLMN_LLM :=NEW_PID.QLMN_LLM; // OUT: BOOL
LMN_P:= NEW_PID.LMN_P; // OUT: REAL
LMN_I := NEW_PID.LMN_I; // OUT: REAL
LMN_D:= NEW_PID.LMN_D; // OUT: REAL
PV := NEW_PID.PV; // OUT: REAL
ER := NEW_PID.ER; // OUT: REAL
//手自动无扰动切换
IF NOT(MAN_ON) THEN
MAN:= NEW_PID.LMN;
END_IF;
//PID量程转换输出
IF STOP THEN //若设备停止则PID输出为零
IF STOP_COC THEN//在停止模式下判断是全开还是全关
LMN:=100.0; // OUT: REAL
LMN_PER :=W#16#6C00; // OUT: WORD
ELSE
LMN:=0.0; // OUT: REAL
LMN_PER :=W#16#0; // OUT: WORD
END_IF;
ELSE
LMN:=NEW_PID.LMN; // OUT: REAL
LMN_PER :=NEW_PID.LMN_PER; // OUT: WORD
END_IF;
END_FUNCTION_BLOCK
//原创程序,欢迎交流 QQ:275578306