Как определить максимальное n-е появление события за заданную продолжительность?

Как определить, что временной интервал n-го события события не превышает определенного периода времени? Например, событие может произойти до ‍5 ti‍mes every 10 minutes.

В STL мы можем использовать это

VAR
    counter:CTU;
    timer:TON;
    Event:BOOL;
    bMaxEventHappend:BOOL;
    tElapsedTime:TIME;
END_VAR


counter(CU:=Event);
IF counter.CV=1 THEN
    timer(IN:=TRUE);
END_IF
IF counter.CV=5 THEN
    bMaxEventHappend:=TRUE;
    counter(Reset:=TRUE);
END_IF

//resetProcess
IF counter.CV=1 AND timer.et>=T#10M THEN
    timer(IN:=FALSE);
    counter(Reset:=TRUE);
ELSIF counter.CV=2 THEN
    tElapsedTime:=timer.et;
    IF timer.ET-tElapsedTime >=T#10M THEN
       timer(IN:=FALSE);
       counter(Reset:=TRUE);
    END_IF
ELSIF counter.CV=3 THEN
    tElapsedTime:=tElapsedTime+timer.et;
    IF timer.ET-tElapsedTime >=T#10M THEN
       timer(IN:=FALSE);
       counter(Reset:=TRUE);
    END_IF
ELSIF counter.CV=4 THEN
    tElapsedTime:=tElapsedTime+timer.et;
    IF timer.ET-tElapsedTime >=T#10M THEN
       timer(IN:=FALSE);
       counter(Reset:=TRUE);
    END_IF
ELSIF counter.CV=5 THEN
    tElapsedTime:=tElapsedTime+timer.et;
    IF timer.ET-tElapsedTime >=T#10M THEN
       timer(IN:=FALSE);
       counter(Reset:=TRUE);
    END_IF
END_IF

Этот метод не кажется оптимальным для достижения желаемого. Есть ли другой оптимальный метод?

Любая помощь будет оценена по достоинству.


person asys    schedule 17.02.2021    source источник
comment
Вы хотите сравнивать события каждые 10 минут или каждые 10 минут?   -  person Sergey Romanov    schedule 18.02.2021
comment
@SergeyRomanov Представьте, что события происходят последовательно, важно, чтобы ни одно из каждых 5 последовательных событий не происходило менее чем за 10 минут.   -  person asys    schedule 18.02.2021
comment
Если 5-е даже раньше, чем через 10 минут, что мы делаем? Оповещение или блокировка события?   -  person Sergey Romanov    schedule 21.02.2021
comment
@SergeyRomanov в этом случае предупреждения достаточно, но для использования другими пользователями лучше объяснить их обоих.   -  person asys    schedule 27.02.2021


Ответы (2)


К сожалению, я не смог понять, чего именно вы пытаетесь достичь. Если мой ответ не дает ваших идей, просто обновите свой вопрос и объясните, что вы хотите сделать.

TYPE MY_EVENT : STRUCT
        TimeStart : TIME; (* Time when event was started *)
        TimeEnd : TIME; (* Time when event was ended *)
        TimeWorked: TIME; (* Time that event was working *)
        Index: USINT; (* Index in array *)
    END_STRUCT
END_TYPE

PROGRAM PLC_PRG
    VAR
        arEvents: ARARY[1..5] OF MY_EVENTS; (* Last 5 events *)
        xEventStart: BOOL; (* Event started *)
        xEventStartM: BOOL; (* Memmory of event started for edge detection *)
        stEvent: MY_EVENT; (* Current event *)
        usiCount: USINT := 1; (* Current index *)
        usiFor: USINT := 1; (* FOR iterator *)
        stSearchEvent: MY_EVENT; (* Searched event *)
    END_VAR

    (* Raising edge of event. Event starts *)
    IF xEventStart AND NOT xEventStartM THEN
        stEvent.TimeStart := TIME();
    END_IF;
    
    (* Falling edge of event. Event ends *)
    IF NOT xEventStart AND xEventStartM THEN
        (* Finalize event *)
        stEvent.TimeEnd := TIME();
        stEvent.Index := usiCount;
        stEvent.TimeWorked := (stEvent.TimeEnd - stEvent.TimeStart);
        
        (* Save event in array *)
        arEvents[usiCount] := stEvent;

        IF usiCount = 5 THEN
            usiCount := 1;
        ELSE
            usiCount := usiCount + 1;
        END_IF;

        stEvent.TimeEnd    := T#0S;
        stEvent.TimeStart  := T#0S;
        stEvent.TimeWorked := T#0S;
    END_IF;
    xEventStartM := xEventStart;

    (* Current event is longer than 1 minute *)
    IF (TIME() - stEvent.TimeStart) > T#1M THEN
        // Do something
    END_IF;

    (* Get longest event out of last 5 events *)
    stSearchEvent.TimeWorked := T#0S;
    FOR usiFor TO 5 DO
        IF (stSearchEvent.TimeWorked < arEvents[usiFor].TimeWorked) THEN
            stSearchEvent := arEvents[usiFor];
        END_IF;
    END_FOR;
END_PROGRAM

Это пример того, как сохранить последние 5 событий в массиве, а затем узнать, что текущее событие слишком длинное, и как найти самое длинное событие в массиве.

person Sergey Romanov    schedule 18.02.2021

Наконец, я нашел этот метод для этой проблемы:

PROGRAM MAIN
VAR
    trigger:r_Trig();
    event: BOOL;
    tDuration:TIME:=T#10M;
    tTimeInit: TIME:=TIME()-tDuration;
    aTime:ARRAY[1..5] OF TIME:=[tTimeInit,tTimeInit,tTimeInit,tTimeInit,tTimeInit];
    alarm:BOOL;
    i:INT;
END_VAR


trigger(clk:=event);
IF trigger.Q THEN
    IF (TIME()-aTime[i+1]<tDuration) THEN
        alarm:=TRUE;
    END_IF
    aTime[i+1]:=TIME();
    i:=(i+1) MOD 5;
END_IF

и кажется, что это работает (проверено на tDuration:TIME:=T#10s;)

person asys    schedule 18.02.2021