• 正文
  • 相关推荐
申请入驻 产业图谱

西门子SCL-电梯案例编程练习

20小时前
159
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

控制要求:

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 FB5

TITLE = '五层电梯控制'//// Block Comment...//VERSION: '1.0'AUTHOR: AuthorNAME: NameFAMILY: Family

// Block ParametersVAR_INPUT    S6  : BOOL;   // 系统启动/停止按钮    S1  : BOOL;   // 1楼呼叫    S2  : BOOL;   // 2楼呼叫    S3  : BOOL;   // 3楼呼叫    S4  : BOOL;   // 4楼呼叫    S5  : BOOL;   // 5楼呼叫

END_VAR
VAR_IN_OUT    // I/O ParametersEND_VAR
VAR_OUTPUT    H6  : BOOL;   // 系统运行指示灯    H1  : BOOL;   // 1楼指示灯    H2  : BOOL;   // 2楼指示灯    H3  : BOOL;   // 3楼指示灯    H4  : BOOL;   // 4楼指示灯    H5  : BOOL;   // 5楼指示灯
END_VAR

VAR_TEMP    // Temporary Variables
END_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 Variables
END_VAR

//系统启动停止  R_TRIG_S6(CLK := S6 );  IF  R_TRIG_S6.Q THEN     SystemRun := NOT SystemRun;    IF SystemRun THEN         // 系统启动:初始化,电梯停在1楼       CurrentFloor := 1;    // 当前所在楼层       TargetFloor  := 0;   // 当前正在前往的目标楼层        NextFloor    := 0;  // 过渡中的下一个中间楼层        ElevState    := 0;  // 状态机        QueueCount   := 0;  // 请求队列(最多5个)        FOR i := 0 TO 4 DO            Queue[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 THEN    H6 := 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 THEN     IF (CurrentFloor <> 1) OR (ElevState <> 0) THEN        _dup := FALSE;          FOR i := 0 TO QueueCount - 1 DO                IF Queue[i] = 1 THEN                     _dup := TRUE;                      END_IF;            END_FOR;            IF NOT _dup AND QueueCount < 5 THEN                 Queue[QueueCount] := 1;                QueueCount := QueueCount + 1;            END_IF;      END_IF;
END_IF;

// --- S2 --- R_TRIG_S2(CLK := S2 );  IF  R_TRIG_S2.Q THEN     IF (CurrentFloor <> 2) OR (ElevState <> 0) THEN        _dup := FALSE;          FOR i := 0 TO QueueCount - 1 DO                IF Queue[i] = 2 THEN                     _dup := TRUE;                      END_IF;            END_FOR;            IF NOT _dup AND QueueCount < 5 THEN                 Queue[QueueCount] := 2;                QueueCount := QueueCount + 1;            END_IF;      END_IF;
END_IF;

// --- S3 --- R_TRIG_S3(CLK := S3 );  IF  R_TRIG_S3.Q THEN     IF (CurrentFloor <> 3) OR (ElevState <> 0) THEN        _dup := FALSE;          FOR i := 0 TO QueueCount - 1 DO                IF Queue[i] = 2 THEN                     _dup := TRUE;                      END_IF;            END_FOR;            IF NOT _dup AND QueueCount < 5 THEN                 Queue[QueueCount] := 3;                QueueCount := QueueCount + 1;            END_IF;      END_IF;
END_IF;

// --- S4--- R_TRIG_S4(CLK := S4 );  IF  R_TRIG_S4.Q THEN     IF (CurrentFloor <> 4) OR (ElevState <> 0) THEN        _dup := FALSE;          FOR i := 0 TO QueueCount - 1 DO                IF Queue[i] = 4 THEN                     _dup := TRUE;                      END_IF;            END_FOR;            IF NOT _dup AND QueueCount < 5 THEN                 Queue[QueueCount] := 4;                QueueCount := QueueCount + 1;            END_IF;      END_IF;END_IF;
// --- S5--- R_TRIG_S5(CLK := S5);  IF  R_TRIG_S5.Q THEN     IF (CurrentFloor <> 5) OR (ElevState <> 0) THEN        _dup := FALSE;          FOR i := 0 TO QueueCount - 1 DO                IF Queue[i] = 5 THEN                     _dup := TRUE;                      END_IF;            END_FOR;            IF NOT _dup AND QueueCount < 5 THEN                 Queue[QueueCount] := 5;                QueueCount := QueueCount + 1;            END_IF;      END_IF;END_IF;
// ============================================================// 第三步:状态机
// ============================================================

CASE ElevState OF
    // ----------------------------------------------------------    // 状态0:空闲,等待任务    // ----------------------------------------------------------    0:        IF QueueCount > 0 THEN            TargetFloor := Queue[0];            FOR i := 0 TO QueueCount - 2 DO                Queue[i] := Queue[i + 1];            END_FOR;            Queue[QueueCount - 1] := 0;            QueueCount := QueueCount - 1;
            IF TargetFloor > CurrentFloor THEN                NextFloor := CurrentFloor + 1;            ELSE                NextFloor := CurrentFloor - 1;            END_IF;
            ElevState  := 1;        END_IF;    1:
       TON_1(IN:= TRUE , PT := T#3S);        IF TON_1.Q THEN            TON_1(IN:= FALSE , PT := T#3S);            CurrentFloor := NextFloor;            IF CurrentFloor = TargetFloor THEN                ElevState := 3;            ELSE                 _found := FALSE;                 FOR i := 0 TO QueueCount - 1 DO                    IF Queue[i] = CurrentFloor THEN                         _found := TRUE;                            // 从队列中移除该楼层                        FOR j := i TO QueueCount - 2 DO                            Queue[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 THEN            TON_2(IN:= FALSE , PT := T#2S);              // 继续向 TargetFloor 方向移动一层            IF TargetFloor > CurrentFloor THEN                NextFloor := CurrentFloor + 1;            ELSE                NextFloor := CurrentFloor - 1;            END_IF;            ElevState  := 1;        END_IF;    // ----------------------------------------------------------    // 状态3:到达目标层,常亮 2s,然后检查队列    // ----------------------------------------------------------
    3:        TON_3(IN:= TRUE , PT := T#3S);        IF TON_3.Q THEN             TON_3(IN:= FALSE , PT := T#3S);            IF QueueCount > 0 THEN                TargetFloor := Queue[0];                FOR i := 0 TO QueueCount - 2 DO                    Queue[i] := Queue[i + 1];                END_FOR;                Queue[QueueCount - 1] := 0;                QueueCount := QueueCount - 1;
                IF TargetFloor > CurrentFloor THEN                    NextFloor := CurrentFloor + 1;                ELSIF TargetFloor < CurrentFloor THEN                    NextFloor := CurrentFloor - 1;                ELSE                    ElevState := 0;                    RETURN;                END_IF;                ElevState  := 1;             ELSE                ElevState := 0;             END_IF;                    END_IF;
END_CASE;
 // ============================================================// 第四步:输出驱动// ============================================================H1 := FALSE; H2 := FALSE; H3 := FALSE;H4 := FALSE; H5 := FALSE;

CASE ElevState OF    0:        CASE CurrentFloor OF            1: H1 := TRUE;            2: H2 := TRUE;            3: H3 := TRUE;            4: H4 := TRUE;            5: H5 := TRUE;        END_CASE;    1:        CASE NextFloor OF            1: H1 := M10.5;  //系统脉冲1HZ            2: H2 := M10.5;            3: H3 := M10.5;            4: H4 := M10.5;            5: H5 := M10.5;        END_CASE;    2:        CASE CurrentFloor OF            1: H1 := TRUE;            2: H2 := TRUE;            3: H3 := TRUE;            4: H4 := TRUE;            5: H5 := TRUE;        END_CASE;    3:        CASE CurrentFloor OF            1: H1 := TRUE;            2: H2 := TRUE;            3: H3 := TRUE;            4: H4 := TRUE;            5: H5 := TRUE;        END_CASE;END_CASE;
END_FUNCTION_BLOCK
—— 全文完 ——

 

相关推荐