Skip to content

Alarming

The runtime has a built-in alarm manager. It follows the alarm lifecycle of ISA-18.2: an alarm is raised, acknowledged, returns to normal and can be shelved, suppressed or closed. The HMI alarm components, the alarm e-mails and the portal show the same alarms.

Alarming is off by default. You enable it per project in the project tree, with the entry Alarming.

SettingRangeMeaning
Enable alarmingon / offOff: nothing is generated, and the runtime uses no memory for alarms.
Maximum number of alarms (N)1 to 10000Number of alarm slots, the length of LC_ALARMS.
History size (M)0 to 100000Number of history entries, the length of LC_ALARM_HISTORY. 0 means no history.

The editor shows the approximate memory use: about 600 bytes per alarm slot and 200 bytes per history entry.

When alarming is enabled, the build adds read-only Structured Text to the project before it is compiled. You do not see this code in the project tree, but every POU can use it.

TYPE ST_Alarm : STRUCT
Uid : STRING(64); (* written by the program *)
Text : STRING(255);
Area : STRING(32);
Unit : STRING(16);
Priority : INT;
Category : INT;
Active : BOOL;
Value : LREAL;
Limit : LREAL;
AckRequest : BOOL; (* set by the program, reset by the runtime *)
CloseRequest : BOOL; (* set by the program, reset by the runtime *)
State : INT; (* written by the runtime *)
Acked : BOOL;
Shelved : BOOL;
Suppressed : BOOL;
Occurrence : UDINT;
RaisedAt : DT;
AckAt : DT;
RtnAt : DT;
ClosedAt : DT;
ShelveUntil : DT;
AckBy : STRING(64);
END_STRUCT END_TYPE
TYPE ST_AlarmEvent : STRUCT
Seq : ULINT; (* sequence number of the event *)
Uid : STRING(64);
Transition : INT;
At : DT;
Source : STRING(64); (* plc, hmi, email, cloud, ... *)
Value : LREAL;
Occurrence : UDINT;
Priority : INT;
State : INT;
Replayed : BOOL; (* happened while the runtime was down *)
END_STRUCT END_TYPE
TYPE ST_AlarmRequest : STRUCT
Uid : STRING(64);
Occurrence : UDINT;
Source : STRING(64);
Duration : TIME;
Enable : BOOL;
Area : STRING(32);
Priority : INT;
Unacked : BOOL;
END_STRUCT END_TYPE
VAR_GLOBAL
LC_ALARMS : ARRAY[1..N] OF ST_Alarm;
LC_ALARM_HISTORY : ARRAY[1..M] OF ST_AlarmEvent; (* only when M > 0 *)
END_VAR

The build also adds the helper functions below.

FieldWritten byMeaning
UidprogramUnique name of the alarm, at most 64 characters, for example 'TANK1.LEVEL.HIHI'. The HMI and the e-mail configuration use it. An empty Uid marks a free slot.
TextprogramAlarm message, at most 255 characters.
AreaprogramPlant area, at most 32 characters. Used to filter and to acknowledge by area.
UnitprogramEngineering unit of Value and Limit, at most 16 characters.
Priorityprogram1 Critical, 2 High, 3 Medium (default), 4 Low.
Categoryprogram0 none, 1 Safety, 2 Process, 3 Equipment, 4 Quality, 5 Maintenance.
ActiveprogramCondition of the alarm. A rising edge raises it, a falling edge returns it to normal.
Value, LimitprogramCurrent value and limit, shown in the HMI and in e-mails.
AckRequest, CloseRequestprogramSet to TRUE to acknowledge or close the alarm. The runtime handles the request at the end of the cycle and resets the field.
StateruntimeLifecycle state, see States.
Acked, Shelved, SuppressedruntimeFlags of the current occurrence.
OccurrenceruntimeCounts the raises of the alarm.
RaisedAt, AckAt, RtnAt, ClosedAtruntimeTimes (UTC) when the occurrence was raised, acknowledged, returned to normal and closed.
ShelveUntilruntimeEnd of a shelve.
AckByruntimeSource of the acknowledgement, for example plc, hmi or email.
StateNameMeaning
0INACTIVENormal, nothing to do.
1ACTIVE_UNACKCondition present, not acknowledged.
2ACTIVE_ACKCondition present, acknowledged.
3RTN_UNACKCondition cleared, not acknowledged.
4SHELVEDHidden by an operator for a limited time.
5SUPPRESSEDHidden by design, for example during maintenance.

An alarm leaves the active list when it is acknowledged and returned to normal, or when it is closed.

Close acknowledges the alarm, ends a shelve or a suppression and sets ClosedAt. It is allowed in every state. If the condition is still active, the alarm stays closed until the condition is reported inactive once. The next rising edge then raises a new occurrence.

Every transition is written to LC_ALARM_HISTORY. The event with sequence number Seq is stored at index ((Seq - 1) MOD M) + 1. When the history is full, the oldest entry is overwritten.

TransitionName
1RAISE
2ACK
3RTN
4SHELVE
5UNSHELVE
6SUPPRESS
7UNSUPPRESS
8CLOSE

A program can own a slot of LC_ALARMS and write its fields. The runtime evaluates every slot with a non-empty Uid at the end of each task cycle.

LC_ALARMS[1].Uid := 'TANK1.LEVEL.HIHI';
LC_ALARMS[1].Text := 'Tank 1 level high high';
LC_ALARMS[1].Priority := 1;
LC_ALARMS[1].Area := 'TANK_FARM';
LC_ALARMS[1].Limit := 95.0;
LC_ALARMS[1].Value := Tank1.Level;
LC_ALARMS[1].Active := Tank1.Level > LC_ALARMS[1].Limit;
IF AckButton THEN
LC_ALARMS[1].AckRequest := TRUE;
END_IF

The helper functions address an alarm by its Uid. An unknown Uid takes the first free slot of LC_ALARMS. The result is visible in LC_ALARMS in the same cycle.

VAR
hiHi : ST_Alarm := (Uid := 'TANK1.LEVEL.HIHI', Text := 'Tank 1 level high high',
Priority := 1, Area := 'TANK_FARM', Limit := 95.0, Unit := '%');
state : INT;
rc : INT;
END_VAR
hiHi.Value := Tank1.Level;
hiHi.Active := Tank1.Level > hiHi.Limit;
state := SetAlarm(hiHi); (* call it every cycle *)
IF AckButton THEN
AckAlarmAsync('TANK1.LEVEL.HIHI');
END_IF
IF ServiceMode THEN
state := ShelveAlarm(Uid := 'TANK1.LEVEL.HIHI', Duration := T#30m, Result => rc);
END_IF

Every helper has two optional parameters:

  • Timeout : TIME := T#100ms, passed to RPC_CALL.
  • Result => INT, the RPC_CALL result code. It is 0 when the command was understood and -2 when the parameters were not valid.

Inputs with a default value can be left out. A call either lists the values in order (AckAlarm('A')) or names them (AckAlarm(Uid := 'A', Result => rc)). A call cannot mix both forms, so name every parameter as soon as you read Result.

Synchronous helpers return the result of the command: a state (0 to 5), a count, or a negative code. Asynchronous helpers (...Async) apply the command in the same way, but do not return its result. They return the RPC_CALL result code, which is 0 when the call was accepted. Use them when the program does not need the result.

HelperInputs (default)Returns
SetAlarm, SetAlarmAsyncAlarm : ST_AlarmState. Level-triggered: call it every cycle with Alarm.Active set to the condition. A rising edge raises, a falling edge returns to normal.
RaiseAlarm, RaiseAlarmAsyncAlarm : ST_AlarmState. Edge-triggered: call it once when the condition starts.
UpdateAlarm, UpdateAlarmAsyncAlarm : ST_AlarmState (unchanged). Changes Text, Area, Unit, Priority, Category, Value and Limit. Empty texts and a zero Priority or Category keep the stored value.
ClearAlarm, ClearAlarmAsyncUidState. Edge-triggered: returns the alarm to normal.
AckAlarm, AckAlarmAsyncUid, Occurrence (0 = any), Source ('' = plc)State.
AckAllAlarms, AckAllAlarmsAsyncArea ('' = all areas), SourceNumber of alarms acknowledged.
ShelveAlarm, ShelveAlarmAsyncUid, Duration (T#1h), Occurrence, SourceState.
UnshelveAlarm, UnshelveAlarmAsyncUidState.
SuppressAlarm, SuppressAlarmAsyncUid, Enable (TRUE)State. Enable := FALSE ends the suppression.
CloseAlarm, CloseAlarmAsyncUid, Occurrence, SourceState. See Close.
GetAlarmStateUidState. An unknown alarm is 0.
CountAlarmsPriority (0 = all), Unacked (FALSE)Number of alarms in the active list that are not shelved or suppressed. With Unacked := TRUE, only the unacknowledged ones.

GetAlarmState and CountAlarms have no asynchronous variant: they only read, so an asynchronous call would discard their only result.

Prefer SetAlarm to RaiseAlarm and ClearAlarm. After a restart, the runtime can only reconcile alarms that the program keeps reporting with SetAlarm.

Each helper calls RPC_CALL with the topic 'alarm'. You can also call it directly:

state := RPC_CALL('alarm', 'set', hiHi, T#100ms, -1, FALSE, rc); (* = SetAlarm(hiHi) *)
rc := SetAlarmAsync(hiHi); (* = RPC_CALL('alarm', 'set', hiHi, T#100ms, -1, TRUE, rc) *)

The commands are set, raise, update, clear, ack, ackall, shelve, unshelve, suppress, close, state and count. The parameter is an ST_Alarm, an ST_AlarmRequest, or a STRING that is taken as the Uid.

CodeMeaning
-10Unknown alarm: no slot, or its lifecycle has finished.
-11Invalid parameters, for example a shelve without a duration.
-12Stale occurrence: the alarm was raised again in the meantime.
-13No free slot in LC_ALARMS. Increase the maximum number of alarms.
-17Alarming is not enabled in the project.

The runtime stores the alarm state in its storage file, like retained variables. After a restart, acknowledgements, shelves and occurrence counters are kept. The program writes Text, Area, Unit, Priority, Category, Value and Limit again. The cloud action Reset retained values also clears the alarm state.