控制要求:
1:系统脉冲设置为10。
2:按下S6 系统启动H6亮 ,再次按下S6系统停止H6灭
3: H1到H5代表着五层电梯到位指示灯
4、系统启动时电梯在1楼停止H1常亮
5、例如当电梯在1楼按下2楼呼叫按钮S2,H1灭,H2 以1HZ闪烁3s代表电梯正在上行,3s后H2常亮代表着到达2层。
当电梯在1楼按下3楼呼叫按钮S3,H1灭,H2 以1HZ闪烁3s代表电梯正在上行,闪烁3s后常亮2s然后H2灯灭,H3以1HZ闪烁3s代表电梯正在上行,闪烁3s后常亮,代表到达3层。
6、例如当电梯在3层时,按下1楼呼叫按钮,电梯下行,H2以1hz闪烁3s后常亮2s后灭,H1以1hz闪烁3s后常亮
7、例如当电梯在5层时,按下1楼呼叫按钮,电梯下行,H4以1hz闪烁3s后常亮2s后灭,H3以1hz闪烁3s后常亮2s后灭,H2以1hz闪烁3s后常亮2s后灭,H1以1hz闪烁3s后常亮
8、例如当电梯在3楼时,如果人在1楼按下呼叫按钮,同时有人在5楼按下呼叫按钮,如果1楼先请求电梯先下行到1楼,1楼停留2s后(H1亮2s)后灯灭,按照顺序2-3-4-5再上升到5楼
9、例如当电梯在1楼时,如果人在5楼按下呼叫按钮,同时有人在3楼按下呼叫按钮,如果5楼先请求电梯,3楼后请求电梯,电梯先上行到3楼,3楼停留2s后(H3亮2s)后灯灭,按照顺序2-3-4-5上升到5楼
完整代码:
FUNCTION_BLOCK FB5TITLE = '五层电梯控制'//// Block Comment...//VERSION: '1.0'AUTHOR: AuthorNAME: NameFAMILY: Family// Block ParametersVAR_INPUTS6 : BOOL; // 系统启动/停止按钮S1 : BOOL; // 1楼呼叫S2 : BOOL; // 2楼呼叫S3 : BOOL; // 3楼呼叫S4 : BOOL; // 4楼呼叫S5 : BOOL; // 5楼呼叫END_VARVAR_IN_OUT// I/O ParametersEND_VARVAR_OUTPUTH6 : BOOL; // 系统运行指示灯H1 : BOOL; // 1楼指示灯H2 : BOOL; // 2楼指示灯H3 : BOOL; // 3楼指示灯H4 : BOOL; // 4楼指示灯H5 : BOOL; // 5楼指示灯END_VARVAR_TEMP// Temporary VariablesEND_VARVAR// 系统标志SystemRun : BOOL := FALSE;// 电梯状态CurrentFloor : INT := 1; // 当前所在楼层TargetFloor : INT := 0; // 当前正在前往的目标楼层NextFloor : INT := 0; // 过渡中的下一个中间楼层// 状态机// 0 = 空闲(当前楼层常亮,等待呼叫)// 1 = 闪烁运行(NextFloor灯1Hz闪烁3s,表示正在经过/前往)// 2 = 中间层短暂常亮(NextFloor灯常亮2s,然后继续)// 3 = 目标层到达常亮(到达最终目标,常亮)ElevState : INT := 0;// 请求队列(最多5个)QueueCount : INT := 0;Queue : ARRAY[0..4] OF INT;// 按钮上升沿检测R_TRIG_S1 : R_TRIG;R_TRIG_S2 : R_TRIG;R_TRIG_S3 : R_TRIG;R_TRIG_S4 : R_TRIG;R_TRIG_S5 : R_TRIG;R_TRIG_S6 : R_TRIG;//时间计时器TON_1 : TON;TON_2 : TON;TON_3 : TON;// 中间变量i : INT;j : INT;LightFloor : INT; // 当前应点亮(常亮或闪烁)的楼层编号IsFinalTarget : BOOL; // NextFloor是否是最终目标楼层_dup : BOOL;_found : BOOL; // 途经楼层检测用CycleTime_ms : INT := 10;FlashTimer : DINT := 0;StayTimer : DINT := 0;FlashClock : DINT := 0;FlashOutput : BOOL := FALSE;// Static VariablesEND_VAR//系统启动停止R_TRIG_S6(CLK := S6 );IF R_TRIG_S6.Q THENSystemRun := NOT SystemRun;IF SystemRun THEN// 系统启动:初始化,电梯停在1楼CurrentFloor := 1; // 当前所在楼层TargetFloor := 0; // 当前正在前往的目标楼层NextFloor := 0; // 过渡中的下一个中间楼层ElevState := 0; // 状态机QueueCount := 0; // 请求队列(最多5个)FOR i := 0 TO 4 DOQueue[i] := 0;END_FOR;TON_1(IN:= FALSE , PT := T#3S);TON_2(IN:= FALSE , PT := T#2S);TON_3(IN:= FALSE , PT := T#2S);ELSE// 系统停止:关闭所有输出H1 := FALSE;H2 := FALSE;H3 := FALSE;H4 := FALSE;H5 := FALSE;H6 := FALSE;END_IF;END_IF;// ============================================================// 以下逻辑仅在系统运行时执行// ============================================================IF NOT SystemRun THENH6 := FALSE;H1 := FALSE; H2 := FALSE; H3 := FALSE;H4 := FALSE; H5 := FALSE;TON_1(IN:= FALSE , PT := T#3S);TON_2(IN:= FALSE , PT := T#2S);TON_3(IN:= FALSE , PT := T#2S);RETURN;END_IF;H6 := TRUE; // 系统运行指示灯常亮// ============================================================// 第二步:楼层呼叫按钮上升沿检测 → 加入请求队列// ============================================================// S1 ~ S5 逐一检测,检测到上升沿且目标楼层不同于当前楼层时入队// 同时过滤掉重复请求(队列中已存在的楼层不重复入队)R_TRIG_S1(CLK := S1 );IF R_TRIG_S1.Q THENIF (CurrentFloor <> 1) OR (ElevState <> 0) THEN_dup := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = 1 THEN_dup := TRUE;END_IF;END_FOR;IF NOT _dup AND QueueCount < 5 THENQueue[QueueCount] := 1;QueueCount := QueueCount + 1;END_IF;END_IF;END_IF;// --- S2 ---R_TRIG_S2(CLK := S2 );IF R_TRIG_S2.Q THENIF (CurrentFloor <> 2) OR (ElevState <> 0) THEN_dup := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = 2 THEN_dup := TRUE;END_IF;END_FOR;IF NOT _dup AND QueueCount < 5 THENQueue[QueueCount] := 2;QueueCount := QueueCount + 1;END_IF;END_IF;END_IF;// --- S3 ---R_TRIG_S3(CLK := S3 );IF R_TRIG_S3.Q THENIF (CurrentFloor <> 3) OR (ElevState <> 0) THEN_dup := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = 2 THEN_dup := TRUE;END_IF;END_FOR;IF NOT _dup AND QueueCount < 5 THENQueue[QueueCount] := 3;QueueCount := QueueCount + 1;END_IF;END_IF;END_IF;// --- S4---R_TRIG_S4(CLK := S4 );IF R_TRIG_S4.Q THENIF (CurrentFloor <> 4) OR (ElevState <> 0) THEN_dup := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = 4 THEN_dup := TRUE;END_IF;END_FOR;IF NOT _dup AND QueueCount < 5 THENQueue[QueueCount] := 4;QueueCount := QueueCount + 1;END_IF;END_IF;END_IF;// --- S5---R_TRIG_S5(CLK := S5);IF R_TRIG_S5.Q THENIF (CurrentFloor <> 5) OR (ElevState <> 0) THEN_dup := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = 5 THEN_dup := TRUE;END_IF;END_FOR;IF NOT _dup AND QueueCount < 5 THENQueue[QueueCount] := 5;QueueCount := QueueCount + 1;END_IF;END_IF;END_IF;// ============================================================// 第三步:状态机// ============================================================CASE ElevState OF// ----------------------------------------------------------// 状态0:空闲,等待任务// ----------------------------------------------------------0:IF QueueCount > 0 THENTargetFloor := Queue[0];FOR i := 0 TO QueueCount - 2 DOQueue[i] := Queue[i + 1];END_FOR;Queue[QueueCount - 1] := 0;QueueCount := QueueCount - 1;IF TargetFloor > CurrentFloor THENNextFloor := CurrentFloor + 1;ELSENextFloor := CurrentFloor - 1;END_IF;ElevState := 1;END_IF;1:TON_1(IN:= TRUE , PT := T#3S);IF TON_1.Q THENTON_1(IN:= FALSE , PT := T#3S);CurrentFloor := NextFloor;IF CurrentFloor = TargetFloor THENElevState := 3;ELSE_found := FALSE;FOR i := 0 TO QueueCount - 1 DOIF Queue[i] = CurrentFloor THEN_found := TRUE;// 从队列中移除该楼层FOR j := i TO QueueCount - 2 DOQueue[j] := Queue[j + 1];END_FOR;Queue[QueueCount - 1] := 0;QueueCount := QueueCount - 1;CONTINUE;END_IF;END_FOR;// 无论是否顺路停靠,都进入状态2常亮2s// (_found=TRUE时是停靠,FALSE时是普通过路)ElevState := 2;END_IF;END_IF;// ----------------------------------------------------------// 状态2:中间层常亮 2s(含顺路停靠和普通过路,行为相同)// ----------------------------------------------------------2:TON_2(IN:= TRUE , PT := T#2S);IF TON_2.Q THENTON_2(IN:= FALSE , PT := T#2S);// 继续向 TargetFloor 方向移动一层IF TargetFloor > CurrentFloor THENNextFloor := CurrentFloor + 1;ELSENextFloor := CurrentFloor - 1;END_IF;ElevState := 1;END_IF;// ----------------------------------------------------------// 状态3:到达目标层,常亮 2s,然后检查队列// ----------------------------------------------------------3:TON_3(IN:= TRUE , PT := T#3S);IF TON_3.Q THENTON_3(IN:= FALSE , PT := T#3S);IF QueueCount > 0 THENTargetFloor := Queue[0];FOR i := 0 TO QueueCount - 2 DOQueue[i] := Queue[i + 1];END_FOR;Queue[QueueCount - 1] := 0;QueueCount := QueueCount - 1;IF TargetFloor > CurrentFloor THENNextFloor := CurrentFloor + 1;ELSIF TargetFloor < CurrentFloor THENNextFloor := CurrentFloor - 1;ELSEElevState := 0;RETURN;END_IF;ElevState := 1;ELSEElevState := 0;END_IF;END_IF;END_CASE;// ============================================================// 第四步:输出驱动// ============================================================H1 := FALSE; H2 := FALSE; H3 := FALSE;H4 := FALSE; H5 := FALSE;CASE ElevState OF0:CASE CurrentFloor OF1: H1 := TRUE;2: H2 := TRUE;3: H3 := TRUE;4: H4 := TRUE;5: H5 := TRUE;END_CASE;1:CASE NextFloor OF1: H1 := M10.5; //系统脉冲1HZ2: H2 := M10.5;3: H3 := M10.5;4: H4 := M10.5;5: H5 := M10.5;END_CASE;2:CASE CurrentFloor OF1: H1 := TRUE;2: H2 := TRUE;3: H3 := TRUE;4: H4 := TRUE;5: H5 := TRUE;END_CASE;3:CASE CurrentFloor OF1: H1 := TRUE;2: H2 := TRUE;3: H3 := TRUE;4: H4 := TRUE;5: H5 := TRUE;END_CASE;END_CASE;END_FUNCTION_BLOCK—— 全文完 ——
159