//##############################################################
//两用一备
//判断上次正常运行的设备状态没有出现问题时将上次没有运行的那台设备启动起来
//##############################################################
FUNCTION_BLOCK FB22
TITLE = 'GEX_DRY_CL'
//
// Block Comment...
//
VERSION: '1.0'
AUTHOR: EBC_LW
NAME: GEXDRYCL
FAMILY: EBC
KNOW_HOW_PROTECT
VAR_TEMP
NUM1_FLAG:BOOL;//设备未运行的标志位
NUM2_FLAG:BOOL;
NUM3_FLAG:BOOL;
I:INT;
TEMP1:INT;
TEMP2:INT;
NOT_RUN_NUM: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;//设备的运行状态
END_VAR
VAR
RUN_ARRAY :
ARRAY[1..3] OF STRUCT
RUN_ID : INT;//设备编号
RUN : BOOL; //上一次的运行状态
//RUN_TIME : INT;//运行时间(小时)
END_STRUCT;
NUM1_RUN_N:BOOL;//运行的下降沿
NUM2_RUN_N:BOOL; //运行的下降沿
NUM3_RUN_N:BOOL;//运行的下降沿
NUM1_RUN_P:BOOL;//运行的上升沿
NUM2_RUN_P:BOOL;//运行的上升沿
NUM3_RUN_P:BOOL;//运行的上升沿
NUM1_OLD_RUN_N:BOOL;//运行的上一次的值
NUM2_OLD_RUN_N:BOOL;//运行的上一次的值
NUM3_OLD_RUN_N:BOOL;//运行的上一次的值
NUM1_OLD_RUN_P:BOOL;//运行的上一次的值
NUM2_OLD_RUN_P:BOOL;//运行的上一次的值
NUM3_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;//计数
INTERLOCK_OLD:BOOL;//投入自动的上一次状态
END_VAR
VAR_IN_OUT
NUM1_OLD_RUN:BOOL;//运行的上一次的值
NUM2_OLD_RUN:BOOL;//运行的上一次的值
NUM3_OLD_RUN:BOOL;//运行的上一次的值
END_VAR
VAR_OUTPUT
// Output Parameters
NUM_RUN:INT;//实际运行的数量
NUM1_S:BOOL;//开1#设备
NUM2_S:BOOL;//开2#设备
NUM3_S:BOOL;//开3#设备
//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;
//运行跳变上升沿
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;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&目前运行的台数&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
NUM_RUN:= BOOL_TO_INT(NUM1_RUN)+BOOL_TO_INT( NUM2_RUN)+BOOL_TO_INT(NUM3_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;
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[1].RUN:=NUM1_OLD_RUN;//将上一次的值赋值给结构体
RUN_ARRAY[2].RUN:=NUM2_OLD_RUN;
RUN_ARRAY[3].RUN:=NUM3_OLD_RUN;
I:=0;//初始化循环函数
//判断那个上次是没有运行的,逐台判断
FOR I:= 1 TO 3 BY 1 DO
// Statement Section
IF NOT(RUN_ARRAY[I].RUN) THEN //轮寻的设备是否上次是停止状态的设备
NOT_RUN_NUM:=I;//将没有运行的其中一个的编号给存起来
END_IF;
END_FOR;
//#################################################################################################################################
//####################################################投入自动情况且有运行跳变情况产生则输出控制指令##############################
//---------------------------------------------
//有停机情况产生
IF (INTERLOCK & NUM1_RUN_N) OR (INTERLOCK & NUM2_RUN_N) OR (INTERLOCK & NUM3_RUN_N) THEN
// 有停机情况产生只有一台设备运行则开启上次未开启的那一台设备
IF NUM_RUN<2 THEN
CASE NOT_RUN_NUM OF
1:
NUM1_S:=1;
2:
NUM2_S:=1;
3:
NUM3_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)) & (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;
//######################################################################################################################
END_FUNCTION_BLOCK
//原创程序请多交流