FUNCTION_BLOCK IJ_EAFGroup VAR_EXTERNAL BS_Schedule_Str_W :STRING; BS_Schedule_Str_R :ARRAY[0..60] OF BYTE; END_VAR VAR_INPUT Enable :bool; (*联动启用*) LinkageValue:ARRAY[0..10] of real;(*传感器输入数组*) Dead_Band :real:=10.0; (*联动死区*) MaxRange :real:=1000.0; (*上限切除值*) MinRange :real:=10.0; (*下限切除值*) LinkageSet :real; (*联动目标设定值,平均值大于设定值时动作*) HoldDelay :time:=t#60s; (*波动稳定时间*) EnableNum :INT; (*启用时间段数量 1~4*) SCH_str :STRING; ALLDAY :BOOL; END_VAR VAR_OUTPUT LinkageOut :ARRAY[0..10] of bool; END_VAR VAR OUT_Z :BOOL; TempSum :REAL; TempCount :INT; ValueSum :REAL; ValueCount :INT; ValueAverage:REAL; LinkageEN :BOOL; ton1 :ton; ton2 :ton; i,j,k :INT:=0; TimeSw1 :BOOL; TimeSw2 :BOOL; TimeSw3 :BOOL; TimeSw4 :BOOL; Enable1th :BOOL; Enable2th :BOOL; Enable3th :BOOL; Enable4th :BOOL; OnH1th :INT:=0; OnM1th :INT:=0; OffH1th :INT:=0; OffM1th :INT:=0; OnH2th :INT:=0; OnM2th :INT:=0; OffH2th :INT:=0; OffM2th :INT:=0; OnH3th :INT:=0; OnM3th :INT:=0; OffH3th :INT:=0; OffM3th :INT:=0; OnH4th :INT:=0; OnM4th :INT:=0; OffH4th :INT:=0; OffM4th :INT:=0; Clock : NW_DateTimeGet; HOUR :byte; YEAR :word; MON :byte; DAY :byte; MI :byte; SEC :byte; WEEK :byte; WD_HOUR :INT; WD_MI :INT; SetCompare1th :BOOL; (*开启设定时间大于关闭设定时间为1,反之为0*) TrueSetCloseCompare1th :BOOL; (*关闭设定时间大于实际时间为1,反之为0*) TrueSetOpenCompare1th :BOOL; (*开启设定时间大于实际时间为1,反之为0*) SetCompare2th :BOOL; (*开启设定时间大于关闭设定时间为1,反之为0*) TrueSetCloseCompare2th :BOOL; (*关闭设定时间大于实际时间为1,反之为0*) TrueSetOpenCompare2th :BOOL; (*开启设定时间大于实际时间为1,反之为0*) SetCompare3th :BOOL; (*开启设定时间大于关闭设定时间为1,反之为0*) TrueSetCloseCompare3th :BOOL; (*关闭设定时间大于实际时间为1,反之为0*) TrueSetOpenCompare3th :BOOL; (*开启设定时间大于实际时间为1,反之为0*) SetCompare4th :BOOL; (*开启设定时间大于关闭设定时间为1,反之为0*) TrueSetCloseCompare4th :BOOL; (*关闭设定时间大于实际时间为1,反之为0*) TrueSetOpenCompare4th :BOOL; (*开启设定时间大于实际时间为1,反之为0*) p1,p2 : pointer; v2v : NW_MemCopy; ini :BOOL; str_ini :STRING; END_VAR (* 时 间:20200807 版 本:1.1 作 者: 名 称:排风机组联动程序功能块 说 明: 输入变量 Enable :bool; 联动启用 LinkageValue:ARRAY[0..10] of real; 传感器输入数组 Dead_Band :real:=10.0; 联动死区 MaxRange :real:=1000.0; 上限切除值 MinRange :real:=10.0; 下限切除值 LinkageSet :real; 联动目标设定值,平均值大于设定值时动作 HoldDelay :time:=t#60s; 波动稳定时间 默认60s EnableNum :INT; 启用时间段数量 1~4 SCH_str :STRING; 定时字符串 ALLDAY :BOOL; 全天候模式 0定时时段内运行,1全天候 输出变量 LinkageOut :ARRAY[0..10] of bool; 输出控制数组 1.支持最多4时段或全天候联动设置 2.支持10组数据输入平均取值作为联动依据 3.支持10组设备输出作为联动结果 4.联动值可设置死区范围,上下限切除值,稳定时间 备 注:适配C4版本CPU 依赖块: BS_Runtime; BS_DevC; *) if Enable=1 then if SCH_str<>'' then (*暂通过数组整理字符串,数组读到的值为ASCII码,需通过BS_ASCII2INT进行整理,后期指针功能上线后优化外部引用*) BS_Schedule_Str_W :=SCH_str; (* C2版本 v2m1(EN :=1 , DW_MEM_ADDR :=2000 , W_MAXNUM :=32 , STR_FILENAME :='OPCDA1' , STR_VARNAME :='BS_Schedule_Str_W' ); m2v1(EN :=1 , DW_MEM_ADDR :=2000 , W_MEM_LEN :=32 , STR_FILENAME :='OPCDA1' , STR_VARNAME :='BS_Schedule_Str_R' ); *) (* C4版本 *) p1:=&BS_Schedule_Str_W; p2:=&BS_Schedule_Str_R; v2v(DEST :=p2 , SRC :=p1 , LENGTH :=32 , IQM :=0 ); (*时间数据赋值及限值处理*) if BS_ASCII2INT(BS_Schedule_Str_R[ 0],BS_Schedule_Str_R[ 1])<0 then OnH1th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[ 0],BS_Schedule_Str_R[ 1])>23 then OnH1th:=23; else OnH1th:=BS_ASCII2INT(BS_Schedule_Str_R[ 0],BS_Schedule_Str_R[ 1]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[ 2],BS_Schedule_Str_R[ 3])<0 then OnM1th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[ 2],BS_Schedule_Str_R[ 3])>59 then OnM1th:=59; else OnM1th:=BS_ASCII2INT(BS_Schedule_Str_R[ 2],BS_Schedule_Str_R[ 3]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[ 4],BS_Schedule_Str_R[ 5])<0 then OffH1th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[ 4],BS_Schedule_Str_R[ 5])>23 then OffH1th:=23; else OffH1th:=BS_ASCII2INT(BS_Schedule_Str_R[ 4],BS_Schedule_Str_R[ 5]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[ 6],BS_Schedule_Str_R[ 7])<0 then OffM1th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[ 6],BS_Schedule_Str_R[ 7])>59 then OffM1th:=59; else OffM1th:=BS_ASCII2INT(BS_Schedule_Str_R[ 6],BS_Schedule_Str_R[ 7]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[ 8],BS_Schedule_Str_R[ 9])<0 then OnH2th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[ 8],BS_Schedule_Str_R[ 9])>23 then OnH2th:=23; else OnH2th:=BS_ASCII2INT(BS_Schedule_Str_R[ 8],BS_Schedule_Str_R[ 9]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[10],BS_Schedule_Str_R[11])<0 then OnM2th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[10],BS_Schedule_Str_R[11])>59 then OnM2th:=59; else OnM2th:=BS_ASCII2INT(BS_Schedule_Str_R[10],BS_Schedule_Str_R[11]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[12],BS_Schedule_Str_R[13])<0 then OffH2th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[12],BS_Schedule_Str_R[13])>23 then OffH2th:=23; else OffH2th:=BS_ASCII2INT(BS_Schedule_Str_R[12],BS_Schedule_Str_R[13]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[14],BS_Schedule_Str_R[15])<0 then OffM2th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[14],BS_Schedule_Str_R[15])>59 then OffM2th:=59; else OffM2th:=BS_ASCII2INT(BS_Schedule_Str_R[14],BS_Schedule_Str_R[15]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[16],BS_Schedule_Str_R[17])<0 then OnH3th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[16],BS_Schedule_Str_R[17])>23 then OnH3th:=23; else OnH3th:=BS_ASCII2INT(BS_Schedule_Str_R[16],BS_Schedule_Str_R[17]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[18],BS_Schedule_Str_R[19])<0 then OnM3th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[18],BS_Schedule_Str_R[19])>59 then OnM3th:=59; else OnM3th:=BS_ASCII2INT(BS_Schedule_Str_R[18],BS_Schedule_Str_R[19]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[20],BS_Schedule_Str_R[21])<0 then OffH3th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[20],BS_Schedule_Str_R[21])>23 then OffH3th:=23; else OffH3th:=BS_ASCII2INT(BS_Schedule_Str_R[20],BS_Schedule_Str_R[21]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[22],BS_Schedule_Str_R[23])<0 then OffM3th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[22],BS_Schedule_Str_R[23])>59 then OffM3th:=59; else OffM3th:=BS_ASCII2INT(BS_Schedule_Str_R[22],BS_Schedule_Str_R[23]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[24],BS_Schedule_Str_R[25])<0 then OnH4th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[24],BS_Schedule_Str_R[25])>23 then OnH4th:=23; else OnH4th:=BS_ASCII2INT(BS_Schedule_Str_R[24],BS_Schedule_Str_R[25]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[26],BS_Schedule_Str_R[27])<0 then OnM4th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[26],BS_Schedule_Str_R[27])>59 then OnM4th:=59; else OnM4th:=BS_ASCII2INT(BS_Schedule_Str_R[26],BS_Schedule_Str_R[27]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[28],BS_Schedule_Str_R[29])<0 then OffH4th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[28],BS_Schedule_Str_R[29])>23 then OffH4th:=23; else OffH4th:=BS_ASCII2INT(BS_Schedule_Str_R[28],BS_Schedule_Str_R[29]); end_if; if BS_ASCII2INT(BS_Schedule_Str_R[30],BS_Schedule_Str_R[31])<0 then OffM4th:=0; elsif BS_ASCII2INT(BS_Schedule_Str_R[30],BS_Schedule_Str_R[31])>59 then OffM4th:=59; else OffM4th:=BS_ASCII2INT(BS_Schedule_Str_R[30],BS_Schedule_Str_R[31]); end_if; end_if; (* 有效时间范围内程序执行*) if EnableNum =1 then Enable1th :=1; Enable2th :=0; Enable3th :=0; Enable4th :=0; end_if; if EnableNum =2 then Enable1th :=1; Enable2th :=1; Enable3th :=0; Enable4th :=0; end_if; if EnableNum =3 then Enable1th :=1; Enable2th :=1; Enable3th :=1; Enable4th :=0; end_if; if EnableNum =4 then Enable1th :=1; Enable2th :=1; Enable3th :=1; Enable4th :=1; end_if; if ALLDAY=0 then (*定时控制主程序 4段排程*) Clock( EN:=1 , B_TWELVE_HOUR:=0 | YEAR:= W_YEAR, MON:= BY_MONTH, DAY:= BY_DAY, HOUR:= BY_HOUR,MI := BY_MIN, SEC:= BY_SEC,WEEK := BY_WDAY ); WD_HOUR:=BYTE_TO_int(HOUR); WD_MI:=BYTE_TO_int(MI); if Enable1th=TRUE and (not(OnH1th=OffH1th and OnM1th=OffM1th)) then(*开关时间一致则无效*) (*1判断开关设定时间之间的大小*) if OnH1th>OffH1th then SetCompare1th := 1; end_if; if OnH1thOffM1th then SetCompare1th := 1; else SetCompare1th := 0; end_if; end_if; (*1判断开设定时间与实际时间之间的大小*) if OnH1th>WD_HOUR then TrueSetOpenCompare1th := 1; end_if; if OnH1th=WD_MI then TrueSetOpenCompare1th := 1; else TrueSetOpenCompare1th := 0; end_if; end_if; (*1判断关设定时间与实际时间之间的大小*) if OffH1th>WD_HOUR then TrueSetCloseCompare1th := 1; end_if; if OffH1th=WD_MI then TrueSetCloseCompare1th := 1; else TrueSetCloseCompare1th := 0; end_if; end_if; (*1控制输出*) if SetCompare1th then(*开启设定时间大于关闭设定时间为1*) if TrueSetOpenCompare1th and not (TrueSetCloseCompare1th) then TimeSw1:=0; else TimeSw1:=1; end_if; else if TrueSetCloseCompare1th and not (TrueSetOpenCompare1th) then TimeSw1:=1; else TimeSw1:=0; end_if; end_if; else TimeSw1:=0; end_if; if Enable2th=TRUE and (not(OnH2th=OffH2th and OnM2th=OffM2th)) then(*开关时间一致则无效*) (*2判断开关设定时间之间的大小*) if OnH2th>OffH2th then SetCompare2th := 1; end_if; if OnH2thOffM2th then SetCompare2th := 1; else SetCompare2th := 0; end_if; end_if; (*2判断开设定时间与实际时间之间的大小*) if OnH2th>WD_HOUR then TrueSetOpenCompare2th := 1; end_if; if OnH2th=WD_MI then TrueSetOpenCompare2th := 1; else TrueSetOpenCompare2th := 0; end_if; end_if; (*2判断关设定时间与实际时间之间的大小*) if OffH2th>WD_HOUR then TrueSetCloseCompare2th := 1; end_if; if OffH2th=WD_MI then TrueSetCloseCompare2th := 1; else TrueSetCloseCompare2th := 0; end_if; end_if; (*2控制输出*) if SetCompare2th then(*开启设定时间大于关闭设定时间为1*) if TrueSetOpenCompare2th and not (TrueSetCloseCompare2th) then TimeSw2:=0; else TimeSw2:=1; end_if; else if TrueSetCloseCompare2th and not (TrueSetOpenCompare2th) then TimeSw2:=1; else TimeSw2:=0; end_if; end_if; else TimeSw2:=0; end_if; if Enable3th=TRUE and (not(OnH3th=OffH3th and OnM3th=OffM3th)) then(*开关时间一致则无效*) (*3判断开关设定时间之间的大小*) if OnH3th>OffH3th then SetCompare3th := 1; end_if; if OnH3thOffM3th then SetCompare3th := 1; else SetCompare3th := 0; end_if; end_if; (*3判断开设定时间与实际时间之间的大小*) if OnH3th>WD_HOUR then TrueSetOpenCompare3th := 1; end_if; if OnH3th=WD_MI then TrueSetOpenCompare3th := 1; else TrueSetOpenCompare3th := 0; end_if; end_if; (*3判断关设定时间与实际时间之间的大小*) if OffH3th>WD_HOUR then TrueSetCloseCompare3th := 1; end_if; if OffH3th=WD_MI then TrueSetCloseCompare3th := 1; else TrueSetCloseCompare3th := 0; end_if; end_if; (*3控制输出*) if SetCompare3th then(*开启设定时间大于关闭设定时间为1*) if TrueSetOpenCompare3th and not (TrueSetCloseCompare3th) then TimeSw3:=0; else TimeSw3:=1; end_if; else if TrueSetCloseCompare3th and not (TrueSetOpenCompare3th) then TimeSw3:=1; else TimeSw3:=0; end_if; end_if; else TimeSw3:=0; end_if; if Enable4th=TRUE and (not(OnH4th=OffH4th and OnM4th=OffM4th)) then(*开关时间一致则无效*) (*4判断开关设定时间之间的大小*) if OnH4th>OffH4th then SetCompare4th := 1; end_if; if OnH4thOffM4th then SetCompare4th := 1; else SetCompare4th := 0; end_if; end_if; (*4判断开设定时间与实际时间之间的大小*) if OnH4th>WD_HOUR then TrueSetOpenCompare4th := 1; end_if; if OnH4th=WD_MI then TrueSetOpenCompare4th := 1; else TrueSetOpenCompare4th := 0; end_if; end_if; (*4判断关设定时间与实际时间之间的大小*) if OffH4th>WD_HOUR then TrueSetCloseCompare4th := 1; end_if; if OffH4th=WD_MI then TrueSetCloseCompare4th := 1; else TrueSetCloseCompare4th := 0; end_if; end_if; (*4控制输出*) if SetCompare4th then(*开启设定时间大于关闭设定时间为1*) if TrueSetOpenCompare4th and not (TrueSetCloseCompare4th) then TimeSw4:=0; else TimeSw4:=1; end_if; else if TrueSetCloseCompare4th and not (TrueSetOpenCompare4th) then TimeSw4:=1; else TimeSw4:=0; end_if; end_if; else TimeSw4:=0; end_if; if TimeSw1 or TimeSw2 or TimeSw3 or TimeSw4 then OUT_Z:=1; else OUT_Z:=0; end_if; if OUT_Z=0 and ALLDAY =0 then LinkageEN:=0; end_if; end_if; (* 定时范围内动作 *) if OUT_Z=1 or ALLDAY =1 then (* 组数据联动组设备 *) (*数据处理 过滤超过max,min范围的值,计数有效数据,算出平均值, 取总和*) for i:= 0 to 9 by 1 do if LinkageValue[i]>=MinRange and LinkageValue[i]<=MaxRange then TempSum:=LinkageValue[i]+TempSum; else TempCount:=TempCount+1; end_if; end_for; if i>=9 then i:=0; ValueCount:=10-TempCount; TempCount :=0; ValueSum :=TempSum; TempSum :=0.0; end_if; if ValueCount<>0 then ValueAverage:=ValueSum/int_to_real(ValueCount); end_if; (*比较设定值,稳定有效时间后动作*) ton1(pt:=HoldDelay); ton2(pt:=HoldDelay); if ValueAverage<>0.0 then if (LinkageSet-Dead_Band)-ValueAverage>=0.0 then ton1.in:=1; else ton1.in:=0; end_if; if ton1.q=1 then LinkageEN:=0; end_if; if (LinkageSet+Dead_Band)-ValueAverage<0.0 then ton2.in:=1; else ton2.in:=0; end_if; if ton2.q=1 then LinkageEN:=1; end_if; else LinkageEN:=0; end_if; end_if; (*联动绑定风机*) for j:= 0 to 9 by 1 do LinkageOut[j]:=LinkageEN; end_for; end_if; END_FUNCTION_BLOCK