You cannot do this without individual timers. Here is how I would approach this.
Set global constant and variables
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
Now you can map glbEvents[1].State
to inputs of PLC
Define new structure
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
Create function
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
Implementation
PROGRAM PLC_PRG
VAR
xAlarm: BOOL; (* Alarm *)
END_VAR
IF ProcessEvents() THEN
// Alarm happened
END_IF;
END_PROGRAM
With this approach although you do not have 1 Timer, you have certain level of abstraction that makes it more flexible to support and modify.
But if you absolutely do not want to have so many TON timers, you can create your own timer. It will be single timer in one 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