0

定时可用于在触发或关闭同一电机时产生延迟,或在不同电机之间产生打开或关闭延迟。这是一项用于保护电机的功能,可避免以非常短的间隔驱动。在警报情况下,电机会自动禁用(随着时间的推移优先)以避免进一步损坏。

通过创建一个子例程来读取机器的状态来启动我的代码,这将告诉我它是打开还是关闭。然后创建一个读取处于警报状态的机器的子程序,然后我检查了机器是否处于警报状态。在这段代码下面,我创建了一个驱动电机的例程,然后创建一个例程来触发必须连接电机上的输出,我用一个 else 完成了我的代码,它关闭了电机。


VAR_INPUT

ENABLE      :   BOOL    := FALSE;       (*ENABLES THE BLOCK OPERATION*)

DEV_STS1    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 1 ON / OFF*)
DEV_STS2    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 2 ON / OFF*)
DEV_STS3    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 3 ON / OFF*)
DEV_STS4    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 4 ON / OFF*)
DEV_STS5    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 5 ON / OFF*)
DEV_STS6    :   BOOL    := FALSE;       (*REPRESENTS MOTOR STATUS 6 ON / OFF*)

DEV_ALA1    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 1*)
DEV_ALA2    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 2*)
DEV_ALA3    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 3*)
DEV_ALA4    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 4*)
DEV_ALA5    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 5*)
DEV_ALA6    :   BOOL    := FALSE;       (*REPRESENTS MOTOR ALARM CONDITION 6*)

T_MIN_ON    :   REAL    := 0.0;         (*MINIMUM TIME ON ONE SAME MOTOR / RANGE 0.0 ~ 9999.0 **)
T_MIN_OFF   :   REAL    := 0.0;         (*MINIMUM TIME OFF OF SAME MOTOR / RANGE 0.0 ~ 9999.0*)
T_ON_ON     :   REAL    := 0.0;         (*MINIMUM TIME BETWEEN TWO PARTS OF THE SAME MOTOR / RANGE 0.0 ~ 9999.0*)
T_ON_OTHER  :   REAL    := 0.0;         (*TIME BETWEEN TURN ON DIFFERENT MOTORS / RANGE 0.0 ~ 9999.0*)
T_OFF_OTHER :   REAL    := 0.0;         (*TIME BETWEEN TURN OFF DIFFERENT MOTORS / RANGE 0.0 ~ 9999.0*)
END_VAR

VAR_OUTPUT

REQ_DEV1    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 1 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV2    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 2 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV3    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 3 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV4    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 4 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV5    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 5 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV6    :   BOOL    := FALSE;       (*STATUS D0 MOTOR 6 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)

END_VAR

VAR

DEV_STS     :   ARRAY[1..6] OF BOOL;    (*MOTOR STATUS READING ARRAY*)
DEV_ALA     :   ARRAY[1..6] OF BOOL;    (*ARRAY READING OF MOTORS ALARMS*)  
REQ_DEV     :   ARRAY[1..6] OF BOOL;    (*ARRAY TO MANIPULATE MOTORS STATES*)

FLAG_STS    :   ARRAY[1..6] OF BOOL;    (*ARRAY FOR PREVIOUS STATUS CONTROL OF MOTORS*)

IDX         :   USINT   := 0;           (*GENERIC INDEX TO HANDLE ARRAY*)
DEV_ON      :   USINT   := 0;           (*AMOUNT OF MOTORS MUST BE TURN ON*)

T_ON_INT    :   ARRAY[1..6] OF REAL;    (*INTERNAL TIME ON A SAME MOTOR*)
T_OFF_INT   :   ARRAY[1..6] OF REAL;    (*INTERNAL TIME OFF A SAME MOTOR*)
T_CYCLE     :   ARRAY[1..6] OF REAL;    (*CYCLE TIME OF SAME MOTOR*)

END_VAR

 IF ENABLE THEN
(*==================================================================================*)
                    (*READINGS OF MOTORS STATUS*)
(*==================================================================================*)
    DEV_STS[1] := DEV_STS1;
    DEV_STS[2] := DEV_STS2;
    DEV_STS[3] := DEV_STS3;
    DEV_STS[4] := DEV_STS4;
    DEV_STS[5] := DEV_STS5;
    DEV_STS[6] := DEV_STS6;

(*==================================================================================*)
                (*READINGS OF THE MOTORS ALARM STATUS*)
(*==================================================================================*)
    DEV_ALA[1] := DEV_ALA1;
    DEV_ALA[2] := DEV_ALA2;
    DEV_ALA[3] := DEV_ALA3;
    DEV_ALA[4] := DEV_ALA4;
    DEV_ALA[5] := DEV_ALA5;
    DEV_ALA[6] := DEV_ALA6;

(*==================================================================================*)
                (*CHECK IF ANY MOTOR IS ALARMED*) 
(*==================================================================================*)
    FOR IDX := 0 TO 6 BY 1 DO
        IF DEV_ALA[IDX] = TRUE THEN
            REQ_DEV[IDX] := FALSE;
        END_IF;
    END_FOR;

(*==================================================================================*)
                (*CHECKING WHAT MOTOR SHOULD BE TURN ON*)
(*==================================================================================*)

    FOR IDX := 0 TO 6 BY 1 DO
        IF DEV_STS[IDX] = TRUE THEN
            DEV_ON := DEV_ON + 1;
        END_IF;
    END_FOR;

(*==================================================================================*)
                            (*ACTING A MOTOR*)
(*==================================================================================*)
    FOR IDX := 0 TO 6 DO
        T_CYCLE[IDX] := T_ON_INT[IDX] + T_OFF_INT[IDX];
        IF DEV_STS[IDX] = TRUE AND FLAG_STS[IDX] = FALSE THEN
            IF T_CYCLE[IDX] > T_ON_ON THEN
                IF T_ON_INT[IDX] < T_MIN_OFF THEN
                    REQ_DEV[IDX] := TRUE;
                END_IF;
            END_IF;
        END_IF;

        IF DEV_STS[IDX] = FALSE AND FLAG_STS[IDX] = TRUE THEN
            IF T_ON_INT[IDX] >= T_MIN_ON THEN
                REQ_DEV[IDX] := FALSE;
            END_IF;
        END_IF;

        IF DEV_STS[IDX] = TRUE AND FLAG_STS[IDX] = TRUE THEN
            T_ON_INT[IDX] := T_ON_INT[IDX] + 1.0;
        END_IF;
    END_FOR;


(*==================================================================================*)
                            (*LEADING OUTPUTS*)
(*==================================================================================*)

    REQ_DEV1 := REQ_DEV[1] ;
    REQ_DEV2 := REQ_DEV[2] ;
    REQ_DEV3 := REQ_DEV[3] ;
    REQ_DEV4 := REQ_DEV[4] ;
    REQ_DEV5 := REQ_DEV[5] ;
    REQ_DEV6 := REQ_DEV[6] ;

(*==================================================================================*)
                                (*FLAG*)
(*==================================================================================*)

    FLAG_STS[1] := REQ_DEV1;
    FLAG_STS[2] := REQ_DEV2;
    FLAG_STS[3] := REQ_DEV3;
    FLAG_STS[4] := REQ_DEV4;
    FLAG_STS[5] := REQ_DEV5;
    FLAG_STS[6] := REQ_DEV6;

ELSE

    REQ_DEV1 := FALSE;
    REQ_DEV2 := FALSE;
    REQ_DEV3 := FALSE;
    REQ_DEV4 := FALSE; 
    REQ_DEV5 := FALSE; 
    REQ_DEV6 := FALSE;

END_IF; 


我还没有测试代码。但是我一般用CFC来测试。

4

1 回答 1

1

对于 CFC 可能没问题,但对于 ST 则不行。在 ST 你必须使用不同的概念。我对你的代码有很多问题,但让我告诉你我是如何理解它的,稍后你会提出问题。

首先,创建一个类型。

TYPE MOTOR : STRUCT
        State:  BOOL;    (* State of the motor translated to DO *)
        Task:   BOOL;    (* Do we want to turn this motor off or on *)
        Alarm:  BOOL;    (* Motor alarm *)
        TimerOnMax: TP;  (* Timer to maximum work for motor *)
        TimerOnMin: TP;  (* Timer to maximum work for motor *)
        TimerOff:   TP;  (* Timer for minimum pause between work *)
        TimeOnMax: TIME; (* Maximum time for motor to work *)
        TimeOnMin: TIME; (* Minimum time for motor to work *)
        TimeOff:   TIME; (* Minimum time for motor to rest *)
    END_STRUCT
END_TYPE

现在定义全局变量

VAR_GLOBAL
    (* Array of motors to manage *)
    stMotors: ARRAY[1.._MOTORS_NUM] OF MOTOR := [
        _MOTORS_NUM(TimeOnMax := T#1h, TimeOnMin := T#10m, TimeOff := T#30m)
    ];
END_VAR

VAR_GLOBAL CONSTANT
    _MOTORS_NUM: INT := 6; (* Number of motors in array *)
END_VAR

初始化可能因 CoDeSys 版本而异

现在我们的功能块

FUNCTION_BLOCK ManageMotors
    VAR_INPUT
        ENABLE: BOOL; (* Enable motor management *)
        M_NUM: INT; (*  Number of motors to be working *)
    END_VAR
    VAR
        iCount: INT; (* Index for circle *)
        iNumOfMotors: INT; (* Number of currently working motors *)
    END_VAR

    IF NOT ENABLE THEN
        actTurnOffAll();
        actApply();
        RETURN;
    END_IF;

    actCountWroking();

    FOR iCount := 1 TO _MOTORS_NUM DO
        (* If motor in alarm state turn it off *)
        IF stMotors[iCount].Alarm AND stMotors[iCount].State THEN
            stMotors[iCount].Task := FALSE;
            iNumOfMotors := iNumOfMotors - 1;
        END_IF;

        (* If motor works longer that allowed time turn it off *)
        IF stMotors[iCount].State AND
            stMotors[iCount].Task AND
            NOT stMotors[iCount].TimerOnMax.Q
        THEN
            stMotors[iCount].Task := FALSE;
            iNumOfMotors := iNumOfMotors - 1;
        END_IF;

        (* If amout of working motors more that allowed number turn one off *)
        IF iNumOfMotors > M_NUM AND
            stMotors[iCount].State AND
            stMotors[iCount].Task AND
            NOT stMotors[iCount].TimerOnMin.Q
        THEN
            stMotors[iCount].Task := FALSE;
            iNumOfMotors := iNumOfMotors - 1;
        END_IF;

        (* If amount of working motors less then required turn one motor on *)
        IF iNumOfMotors < M_NUM AND
            NOT stMotors[iCount].State AND
            NOT stMotors[iCount].Task AND
            NOT stMotors[iCount].TimerOff.Q
        THEN
            stMotors[iCount].Task := TRUE;
            iNumOfMotors := iNumOfMotors + 1;
        END_IF;

        stMotors[iCount].TimerOnMax(
            IN := (stMotors[iCount].Task AND NOT stMotors[iCount].State),
            PT := stMotors[iCount].TimeOnMax
        );

        stMotors[iCount].TimerOnMin(
            IN := (stMotors[iCount].Task AND NOT stMotors[iCount].State),
            PT := stMotors[iCount].TimeOnMin
        );

        stMotors[iCount].TimerOff(
            IN := (NOT stMotors[iCount].Task AND stMotors[iCount].State),
            PT := stMotors[iCount].TimeOff
        );
    END_FOR;

    actApply();

    ACTION actCountWroking:
        iNumOfMotors := 0;
        FOR iCount := 1 TO _MOTORS_NUM DO
            IF stMotors[iCount].State THEN
                iNumOfMotors := iNumOfMotors + 1;
            END_IF;
        END_FOR;
    END_ACTION;

    ACTION actTurnOffAll:
        FOR iCount := 1 TO _MOTORS_NUM DO
            stMotors[iCount].Task := FALSE;
        END_FOR;
    END_ACTION;

    ACTION actApply:
        FOR iCount := 1 TO _MOTORS_NUM DO
            stMotors[iCount].State := stMotors[iCount].Task;
        END_FOR;
    END_ACTION;
END_FUNCTION_BLOCK

我添加了一些注释,但其余代码必须清楚。我使用ACTION它是因为它在 CDS 2.3 中和在 CDS 3.5 中一样可用,但如果你有 3.5 版本,你可以使用它METHOD

于 2019-06-10T13:01:59.230 回答