Plc 多独立输入定时器

Plc 多独立输入定时器,plc,twincat,st,Plc,Twincat,St,假设我们有独立的布尔变量,它们可以独立出现。现在,如果在一段时间内至少有一个变量出现,则会激活警报。常见的解决方案是为每个变量使用一个计时器 是否有一个只能与单个计时器一起使用的最佳解决方案 传递时间为1秒的2个变量示例: VAR Timer1,Timer2:TON; bVar1,bVar2:BOOL; tSetDelay:TIME:=T#1S; Alarm:BOOL; END_VAR Timer1(IN:=bVar1,PT:=tSetDelay); Timer

假设我们有独立的布尔变量,它们可以独立出现。现在,如果在一段时间内至少有一个变量出现,则会激活警报。常见的解决方案是为每个变量使用一个计时器

是否有一个只能与单个计时器一起使用的最佳解决方案

传递时间为1秒的2个变量示例:

VAR
    Timer1,Timer2:TON;
    bVar1,bVar2:BOOL;
    tSetDelay:TIME:=T#1S;
    Alarm:BOOL;
END_VAR

Timer1(IN:=bVar1,PT:=tSetDelay);
Timer2(IN:=bVar2,PT:=tSetDelay);

IF Timer1.Q RO Timer2.Q THEN
     Alarm:=TRUE;
END_IF
如果我们使用
则不正确

Timer(IN:=bVar1 OR bVar2,PT:=tSetDelay);
因为VAR可能在相同的
t延时
时间内重叠,这意味着它们的发生时间可能小于延时,但定时器输出为真


在本例中,我们只有2个变量,但如果我们有更多的变量,则找到更好的解决方案将更为重要。

不可能使用单个计时器来管理此问题。 如果您希望确保触发源是单个变量(没有来自其他变量的任何逻辑干扰),则必须将每个变量与其自身的历史(计时器)进行比较

建议的前进路径是构建一个报警功能块,以一致的方式处理这里的大部分逻辑。此类功能块的示例如下:

报警监视器
不可能用一个计时器来管理它。 如果您希望确保触发源是单个变量(没有来自其他变量的任何逻辑干扰),则必须将每个变量与其自身的历史(计时器)进行比较

建议的前进路径是构建一个报警功能块,以一致的方式处理这里的大部分逻辑。此类功能块的示例如下:

报警监视器
如果没有单独的计时器,则无法执行此操作。以下是我将如何处理这个问题

设置全局常量和变量

VAR_GLOBAL
    glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
    c_EventsNum: INT := 3; (* Number of events *)
END_VAR
现在,您可以将
glbEvents[1]状态映射到PLC的输入

定义新结构

TYPE stMyEvents : STRUCT
        State : BOOL; (* Event current state *)
        StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
        Timer: TON := (PT := T#1S); (* Timer *)
    END_STRUCT
END_TYPE
创建函数

FUNCTION ProcessEvents : BOOL
    VAR
        iCount: INT; (* Counter *)
    END_VAR

    FOR iCount := 1 TO c_EventsNum DO
        glbEvents[iCount].Timer(IN := glbEvents[iCount].State);
        IF glbEvents[iCount].Timer.Q THEN
            ProcessEvents := TRUE;
            EXIT;
        END_IF;
    END_FOR;
END_FUNCTION
实施

PROGRAM PLC_PRG
    VAR
        xAlarm: BOOL; (* Alarm *)
    END_VAR

    IF ProcessEvents() THEN
        // Alarm happened        
    END_IF;
END_PROGRAM
使用这种方法,虽然您没有1个计时器,但您有一定的抽象级别,这使得它更灵活地支持和修改

但如果你绝对不想有这么多吨计时器,你可以创建自己的计时器。它将是一个FB中的单个计时器

VAR_GLOBAL
    glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
    c_EventsNum: INT := 3; (* Number of events *)
END_VAR

TYPE stMyEvents : STRUCT
        State : BOOL; (* Event current state *)
        StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
        TimeM: TIME; (* Memmory of event start time *)
    END_STRUCT
END_TYPE

FUNCTION_BLOCK ProcessEvents
    VAR
        iCount: INT; (* Counter *)
    END_VAR
    VAR_OUTPUT
        Q: BOOL; (* Impulse if alarm *)
    END_VAR

    Q := FALSE;
    FOR iCount := 1 TO c_EventsNum DO
        (* Get raising edge and save the timer *)
        IF glbEvents[iCount].State AND NOT glbEvents[iCount].StateM THEN
            glbEvents[iCount].TimeM := TIME();    
        END_IF;
        glbEvents[iCount].StateM := glbEvents[iCount].State;

        (* If event is low reset timer *)
        IF NOT glbEvents[iCount].State THEN
            glbEvents[iCount].TimeM := T#0S; 
        END_IF;
        
        (* if more than a second make impuls on Q *)
        IF (glbEvents[iCount].TimeM > T#0S) AND ((TIME() - glbEvents[iCount].TimeM) >= T#1S) THEN
            Q := TRUE;
            glbEvents[iCount].TimeM := T#0S;    
        END_IF;
    END_FOR;
END_FUNCTION_BLOCK

PROGRAM PLC_PRG
    VAR
        fbeventProcess: ProcessEvents; (* function block *)
    END_VAR

    fbeventProcess();
    IF fbeventProcess.Q THEN
        // Alarm happened        
    END_IF;
END_PROGRAM

如果没有单独的计时器,则无法执行此操作。以下是我将如何处理这个问题

设置全局常量和变量

VAR_GLOBAL
    glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
    c_EventsNum: INT := 3; (* Number of events *)
END_VAR
现在,您可以将
glbEvents[1]状态映射到PLC的输入

定义新结构

TYPE stMyEvents : STRUCT
        State : BOOL; (* Event current state *)
        StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
        Timer: TON := (PT := T#1S); (* Timer *)
    END_STRUCT
END_TYPE
创建函数

FUNCTION ProcessEvents : BOOL
    VAR
        iCount: INT; (* Counter *)
    END_VAR

    FOR iCount := 1 TO c_EventsNum DO
        glbEvents[iCount].Timer(IN := glbEvents[iCount].State);
        IF glbEvents[iCount].Timer.Q THEN
            ProcessEvents := TRUE;
            EXIT;
        END_IF;
    END_FOR;
END_FUNCTION
实施

PROGRAM PLC_PRG
    VAR
        xAlarm: BOOL; (* Alarm *)
    END_VAR

    IF ProcessEvents() THEN
        // Alarm happened        
    END_IF;
END_PROGRAM
使用这种方法,虽然您没有1个计时器,但您有一定的抽象级别,这使得它更灵活地支持和修改

但如果你绝对不想有这么多吨计时器,你可以创建自己的计时器。它将是一个FB中的单个计时器

VAR_GLOBAL
    glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
    c_EventsNum: INT := 3; (* Number of events *)
END_VAR

TYPE stMyEvents : STRUCT
        State : BOOL; (* Event current state *)
        StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
        TimeM: TIME; (* Memmory of event start time *)
    END_STRUCT
END_TYPE

FUNCTION_BLOCK ProcessEvents
    VAR
        iCount: INT; (* Counter *)
    END_VAR
    VAR_OUTPUT
        Q: BOOL; (* Impulse if alarm *)
    END_VAR

    Q := FALSE;
    FOR iCount := 1 TO c_EventsNum DO
        (* Get raising edge and save the timer *)
        IF glbEvents[iCount].State AND NOT glbEvents[iCount].StateM THEN
            glbEvents[iCount].TimeM := TIME();    
        END_IF;
        glbEvents[iCount].StateM := glbEvents[iCount].State;

        (* If event is low reset timer *)
        IF NOT glbEvents[iCount].State THEN
            glbEvents[iCount].TimeM := T#0S; 
        END_IF;
        
        (* if more than a second make impuls on Q *)
        IF (glbEvents[iCount].TimeM > T#0S) AND ((TIME() - glbEvents[iCount].TimeM) >= T#1S) THEN
            Q := TRUE;
            glbEvents[iCount].TimeM := T#0S;    
        END_IF;
    END_FOR;
END_FUNCTION_BLOCK

PROGRAM PLC_PRG
    VAR
        fbeventProcess: ProcessEvents; (* function block *)
    END_VAR

    fbeventProcess();
    IF fbeventProcess.Q THEN
        // Alarm happened        
    END_IF;
END_PROGRAM

你可以把计时器和布尔放在一个数组中,然后在上面循环。你可以把计时器和布尔放在一个数组中,然后在上面循环。