//该程序需要设置系统时间存储区为2,还需结合我写的设备运行时间累计的块方可实现
//##############################################################
//四台设备两用两备,当两台设备有一台设备由运行状态跳变为停止状态则
//筛选开头未运行的机组,并判断哪一台时间最短,然后自动启动起来
//##############################################################
FUNCTION_BLOCK FB21
TITLE = 'GEX_WET_CL'
//
// Block Comment...
//
VERSION: '1.0'
AUTHOR: EBC_LW
NAME: GEXWETCL
FAMILY: EBC
KNOW_HOW_PROTECT
VAR_TEMP
// Temporary Variables
NUM1_RUN_LESS:INT;//剩下两台中的一台的运行时间
NUM2_RUN_LESS:INT;//剩下两台中的一台的运行时间
NUM1_FLAG:BOOL;//设备未运行的标志位
NUM2_FLAG:BOOL;
NUM3_FLAG:BOOL;
NUM4_FLAG:BOOL;
I:INT;
J:INT;
TEMP1:INT;
TEMP2:INT;
NOT_RUN_NUM1:INT;
NOT_RUN_NUM2:INT;
SECOND_PN:BOOL;//秒脉冲
INTERLOCK_P:BOOL;//投入自动上升沿
END_VAR
// Block Parameters
VAR_INPUT
// Input Parameters
INTERLOCK:BOOL;//联锁
NUM1_RUN:BOOL;//设备的运行状态
NUM2_RUN:BOOL;//设备的运行状态
NUM3_RUN:BOOL;//设备的运行状态
NUM4_RUN:BOOL;//设备的运行状态
NUM1_RUN_TIME:INT;//设备运行的小时数量
NUM2_RUN_TIME:INT;//设备运行的小时数量
NUM3_RUN_TIME:INT;//设备运行的小时数量
NUM4_RUN_TIME:INT;//设备运行的小时数量
END_VAR
VAR
ARRAY_TEMP: ARRAY[1..2] OF INT;
RUN_ARRAY :
ARRAY[1..4] OF STRUCT
RUN_ID : INT;//设备编号
RUN : BOOL; //上一次的运行状态
RUN_TIME : INT;//运行时间(小时)
END_STRUCT;
NUM1_RUN_N:BOOL;//运行的下降沿
NUM2_RUN_N:BOOL; //运行的下降沿
NUM3_RUN_N:BOOL;//运行的下降沿
NUM4_RUN_N:BOOL;//运行的下降沿
NUM1_RUN_P:BOOL;//运行的上升沿
NUM2_RUN_P:BOOL;//运行的上升沿
NUM3_RUN_P:BOOL;//运行的上升沿
NUM4_RUN_P:BOOL;//运行的上升沿
NUM1_OLD_RUN_N:BOOL;//运行的上一次的值
NUM2_OLD_RUN_N:BOOL;//运行的上一次的值
NUM3_OLD_RUN_N:BOOL;//运行的上一次的值
NUM4_OLD_RUN_N:BOOL;//运行的上一次的值
NUM1_OLD_RUN_P:BOOL;//运行的上一次的值
NUM2_OLD_RUN_P:BOOL;//运行的上一次的值
NUM3_OLD_RUN_P:BOOL;//运行的上一次的值
NUM4_OLD_RUN_P:BOOL;//运行的上一次的值
STATUS:BOOL;
STATUS_OLD:BOOL;
STATUS_P:BOOL;
SECOND_OLD:BOOL;//上一次的秒状态
NUM1_S_COUNT:INT;//计数
NUM2_S_COUNT:INT;//计数
NUM3_S_COUNT:INT;//计数
NUM4_S_COUNT:INT;//计数
INTERLOCK_OLD:BOOL;//投入自动的上一次状态
END_VAR
VAR_IN_OUT
NUM1_OLD_RUN:BOOL;//运行的上一次的值
NUM2_OLD_RUN:BOOL;//运行的上一次的值
NUM3_OLD_RUN:BOOL;//运行的上一次的值
NUM4_OLD_RUN:BOOL;//运行的上一次的值
// I/O Parameters
END_VAR
VAR_OUTPUT
// Output Parameters
NUM_RUN:INT;//实际运行的数量
NUM1_S:BOOL;//开1#设备
NUM2_S:BOOL;//开2#设备
NUM3_S:BOOL;//开3#设备
NUM4_S:BOOL;//开4#设备
ERR:INT;//故障代码
END_VAR
//秒脉冲
SECOND_PN:=M2.5&(NOT SECOND_OLD);
SECOND_OLD:=M2.5;
//投入自动上升沿
INTERLOCK_P:=INTERLOCK&(NOT INTERLOCK_OLD);
INTERLOCK_OLD:=INTERLOCK;
//运行跳变下降沿
NUM1_RUN_N:=NUM1_OLD_RUN_N&(NOT NUM1_RUN);
NUM1_OLD_RUN_N:=NUM1_RUN;
NUM2_RUN_N:=NUM2_OLD_RUN_N&(NOT NUM2_RUN);
NUM2_OLD_RUN_N:=NUM2_RUN;
NUM3_RUN_N:=NUM3_OLD_RUN_N&(NOT NUM3_RUN);
NUM3_OLD_RUN_N:=NUM3_RUN;
NUM4_RUN_N:=NUM4_OLD_RUN_N&(NOT NUM4_RUN);
NUM4_OLD_RUN_N:=NUM4_RUN;
//运行跳变上升沿
NUM1_RUN_P:= NUM1_RUN &(NOT NUM1_OLD_RUN_P);
NUM1_OLD_RUN_P:=NUM1_RUN;
NUM2_RUN_P:= NUM2_RUN &(NOT NUM2_OLD_RUN_P);
NUM2_OLD_RUN_P:=NUM2_RUN;
NUM3_RUN_P:= NUM3_RUN &(NOT NUM3_OLD_RUN_P);
NUM3_OLD_RUN_P:=NUM3_RUN;
NUM4_RUN_P:= NUM4_RUN &(NOT NUM4_OLD_RUN_P);
NUM4_OLD_RUN_P:=NUM4_RUN;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&目前运行的台数&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
NUM_RUN:= BOOL_TO_INT(NUM1_RUN)+BOOL_TO_INT( NUM2_RUN)+BOOL_TO_INT(NUM3_RUN)+BOOL_TO_INT(NUM4_RUN);//实际运行的设备总数
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//####################################################刷新上一次设备的运行情况##########################################################
//上一次运行状态更新,上升沿触发
STATUS_P:=STATUS&(NOT STATUS_OLD);
STATUS_OLD:=STATUS;
//标志位STATUS产生上升沿将当前运行状态存起来留作上一次的状态
IF STATUS_P THEN
NUM1_OLD_RUN:=NUM1_RUN;
NUM2_OLD_RUN:=NUM2_RUN;
NUM3_OLD_RUN:=NUM3_RUN;
NUM4_OLD_RUN:=NUM4_RUN;
STATUS:=0;//状态刷新以后自动进行复位
END_IF;
//######################################################################################################################################
// STATUS:=INTERLOCK=1 ;
//###############################################筛选上一次没有运行的设备并将没有运行的设备编号取出#####################################
//初始化结构体值
RUN_ARRAY[1].RUN_ID:=1;//给结构体设备编号
RUN_ARRAY[2].RUN_ID:=2;
RUN_ARRAY[3].RUN_ID:=3;
RUN_ARRAY[4].RUN_ID:=4;
RUN_ARRAY[1].RUN:=NUM1_OLD_RUN;//将上一次的值赋值给结构体
RUN_ARRAY[2].RUN:=NUM2_OLD_RUN;
RUN_ARRAY[3].RUN:=NUM3_OLD_RUN;
RUN_ARRAY[4].RUN:=NUM4_OLD_RUN;
RUN_ARRAY[1].RUN_TIME:=NUM1_RUN_TIME;//将运行时间赋值给结构体
RUN_ARRAY[2].RUN_TIME:=NUM2_RUN_TIME;
RUN_ARRAY[3].RUN_TIME:=NUM3_RUN_TIME;
RUN_ARRAY[4].RUN_TIME:=NUM4_RUN_TIME;
I:=0;
J:=0;
//判断那个上次是没有运行的,逐台判断
FOR I:= 1 TO 4 BY 1 DO
// Statement Section
IF NOT(RUN_ARRAY[I].RUN) THEN //轮寻的设备是否上次是停止状态的设备
J:=J+1;
ARRAY_TEMP[J]:=RUN_ARRAY[I].RUN_TIME;//将上次是停止状态的设备的时间放到数组
CASE J OF
1:
TEMP1:=ARRAY_TEMP[J]; //将没有运行的该台设备的运行时间放到临时变量
NOT_RUN_NUM1:=I;//将没有运行的其中一个的编号给存起来
ERR:=0;
2:
TEMP2:=ARRAY_TEMP[J];
NOT_RUN_NUM2:=I;
ERR:=0;
ELSE:
// Statements_ELSE
ERR:=1;//若出现上次有三个设备处于停止状态则报警
END_CASE;
END_IF;
END_FOR;
//#################################################################################################################################
//####################################################投入自动情况且有运行跳变情况产生则输出控制指令##############################
//---------------------------------------------
//有停机情况产生
IF (INTERLOCK & NUM1_RUN_N) OR (INTERLOCK & NUM2_RUN_N) OR (INTERLOCK & NUM3_RUN_N) OR (INTERLOCK & NUM4_RUN_N) THEN
// 比较两个存起来的哪一台设备的运行时间最短且现在设备只有一台运行则开启优先权最大的那台设备
IF (TEMP1<=TEMP2) & (NUM_RUN<2) THEN
CASE NOT_RUN_NUM1 OF
1:
NUM1_S:=1;
2:
NUM2_S:=1;
3:
NUM3_S:=1;
4:
NUM4_S:=1;
END_CASE;
ELSE
CASE NOT_RUN_NUM2 OF
1:
NUM1_S:=1;
2:
NUM2_S:=1;
3:
NUM3_S:=1;
4:
NUM4_S:=1;
END_CASE;
END_IF;
END_IF;
//#########################################################################################################################################################################
// 投入自动状态且满足当前运行的是两台设备或有新设备运行起来则刷新上一次设备的运行状态则刷新上一次的设备运行状态
IF ((INTERLOCK_P & ( NUM_RUN=2 )) OR (INTERLOCK & NUM1_RUN_P) OR (INTERLOCK & NUM2_RUN_P) OR (INTERLOCK & NUM3_RUN_P)OR (INTERLOCK & NUM4_RUN_P)) & (NUM_RUN=2) THEN
STATUS:=1;
END_IF;
//###########################################################################################################################################################################
//###############################输出指令3秒钟自动复位##################################################################
IF NUM1_S & SECOND_PN THEN
NUM1_S_COUNT:=NUM1_S_COUNT+1;
IF NUM1_S_COUNT>=3 THEN
NUM1_S_COUNT:=0;
NUM1_S:=0;
END_IF;
END_IF;
IF NUM2_S & SECOND_PN THEN
NUM2_S_COUNT:=NUM2_S_COUNT+1;
IF NUM2_S_COUNT>=3 THEN
NUM2_S_COUNT:=0;
NUM2_S:=0;
END_IF;
END_IF;
IF NUM3_S & SECOND_PN THEN
NUM3_S_COUNT:=NUM3_S_COUNT+1;
IF NUM3_S_COUNT>=3 THEN
NUM3_S_COUNT:=0;
NUM3_S:=0;
END_IF;
END_IF;
IF NUM4_S & SECOND_PN THEN
NUM4_S_COUNT:=NUM4_S_COUNT+1;
IF NUM4_S_COUNT>=3 THEN
NUM4_S_COUNT:=0;
NUM4_S:=0;
END_IF;
END_IF;
//######################################################################################################################
END_FUNCTION_BLOCK
//原创程序请多交流 QQ 275578306