Handling the alarms for a MotoLogix system.
The MotoLogix data packet has a variable which tells the amount of active
alarms. To read the alarm information we need to call MLxGetErrorDetail
for each active alarm.
That function reads the information as strings (in the active pendant language).
The alarm information is stored in an array
(see MceAlarmsIO
).
This function uses two states machines:
nSmReadAlarms
- getting the alarm information from the controllernSmResetAlarm
- resetting alarms
Usage
MceAlarms
instance.Create the (global) variables for the interface data. These are also used for connecting buttons or an HMI.
stAlarms : ARRAY [0..GVL.MLX_UBOUND] OF MceAlarmsIO; // data for alarm handling of a MotoLogix system
Create the instances:
fbAlarms : ARRAY [0..GVL.MLX_UBOUND] OF MceAlarms;
Map all relevant inputs (see MceAlarmsIO
)
to your HMI.
GVL.stAlarms[0].bReset := ...;
Call the instances in a loop:
// function call
FOR i := 0 TO GVL.MLX_UBOUND DO
fbAlarms[i](
io := GVL.stAlarms[i],
blinkSignals := GVL.stBlinkSignals,
MLX := GVL.stMLX[i]);
END_FOR;
Map all relevant outputs (see MceAlarmsIO
)
to your HMI and/or to higher level state machines:
// this is just a portion of the relevant signals
... := GVL.stAlarms[0].bResetIndicator;
... := GVL.stAlarms[0].nAlarms;
... := GVL.stAlarms[0].aAlarms;
Version history
0.2.0
Changes
- FB names according style guide
show full history
0.1.0
Changes
- initial version
Overview
kind | name | type | default | comment |
---|---|---|---|---|
in_out | io | MceAlarmsIO | interface data | |
in_out | blinkSignals | MceBlinkSignalsIO | signals for blinking indicator lights | |
in_out | MLX | MLxData | MotoLogix shared memory variable |
Details
Interface data for this function.
Check the data type for more information.
blinkSignals
MceBlinkSignalsIO
Signals for blinking indicator lights.
Check the data type for the available blinking patterns.
MLX
MLxData
The MotoLogix variable which acts as the shared memory for a MotoLogix system.
Check the YaskawaMLx library for more information.
Source code
Declarations
(*Alarm reading + alarm reset*)
FUNCTION_BLOCK MceAlarms
(*
* -----------------------------------------------------------------------------
* Name : MceAlarms
* Version : 0.2.0
* Date : 2022-02-23
* Author : deGroot
* Family : YaskawaMce
* Organisation : github.com/YaskawaEurope/mlx-examples
*
* -----------------------------------------------------------------------------
* Alarm reading + alarm reset
* -----------------------------------------------------------------------------
*)
VAR_IN_OUT
io : MceAlarmsIO; (*interface data*)
blinkSignals : MceBlinkSignalsIO; (*signals for blinking indicator lights*)
MLX : MLxData; (*MotoLogix shared memory variable*)
END_VAR
VAR
fbResetAndHold : MLxResetAndHold;
fbGetErrorDetail : MLxGetErrorDetail;
nIndex : USINT; (*index for reading alarms*)
bOsrReset : BOOL; (*rising edge*)
aOneShots : ARRAY [0..0] OF BOOL; (*bits for one shot signals*)
END_VAR
Logic
// -----------------------------------------------------------------------------
// init
// -----------------------------------------------------------------------------
io.bError := FALSE;
fbResetAndHold.Enable := FALSE;
fbGetErrorDetail .Enable := FALSE;
// -----------------------------------------------------------------------------
// common
// -----------------------------------------------------------------------------
// rising edge signals
bOsrReset := io.bReset AND NOT aOneShots[0];
aOneShots[0] := io.bReset;
// -----------------------------------------------------------------------------
// State machine 1: read alarms
// -----------------------------------------------------------------------------
CASE io.nSmReadAlarms OF
// -------------------------------------
// idle, wait for new alarm data
// -------------------------------------
0:
IF (io.nAlarms <> MLX.NumberOfQueuedErrors)
AND MLX.Signals.MLXGatewayConnected THEN
io.nAlarms := DINT_TO_USINT(MLX.NumberOfQueuedErrors);
io.nErrorCode := 0;
io.nSmReadAlarms := 10;
END_IF;
// -------------------------------------
// prepare reading
// -------------------------------------
10:
nIndex := 0;
MEMUtils.MemSet(
pbyBuffer := ADR(io.aAlarms),
byValue := 0,
dwSize := SIZEOF(io.aAlarms));
IF (io.nAlarms > 0) THEN
io.nSmReadAlarms := 20;
ELSE
io.nSmReadAlarms := 0;
END_IF;
// -------------------------------------
// read alarm with MLxGetErrorDetail
// -------------------------------------
20:
fbGetErrorDetail.Enable := TRUE;
IF fbGetErrorDetail.Sts_EN AND fbGetErrorDetail.Sts_DN THEN
IF fbGetErrorDetail.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmReadAlarms;
io.nSmReadAlarms := 99;
ELSE
// store alarm information
io.aAlarms[nIndex].nAlarmNumber :=
fbGetErrorDetail.ErrorDetail.errorNumber;
MEMUtils.MemCpy(
pbySrc := ADR(fbGetErrorDetail.ErrorDetail.Message),
pbyDest := ADR(io.aAlarms[nIndex].sMessage),
dwSize := SIZEOF(io.aAlarms[nIndex].sMessage));
MEMUtils.MemCpy(
pbySrc := ADR(fbGetErrorDetail.ErrorDetail.ExtendedDescription1),
pbyDest := ADR(io.aAlarms[nIndex].sSubCode),
dwSize := SIZEOF(io.aAlarms[nIndex].sSubCode));
MEMUtils.MemCpy(
pbySrc := ADR(fbGetErrorDetail.ErrorDetail.TimeStamp),
pbyDest := ADR(io.aAlarms[nIndex].sTimeStamp),
dwSize := SIZEOF(io.aAlarms[nIndex].sTimeStamp));
nIndex := nIndex + 1;
io.nSmReadAlarms := 30;
END_IF;
END_IF;
// -------------------------------------
// check if done
// -------------------------------------
30:
// more errors to read
IF nIndex < io.nAlarms THEN
io.nSmReadAlarms := 20;
// done
ELSE
io.nSmReadAlarms := 0;
END_IF;
// -------------------------------------
// state machine error
// -------------------------------------
99:
io.bError := TRUE;
io.nSmReadAlarms := 0;
ELSE
io.nSmReadAlarms := 0;
END_CASE;
// -----------------------------------------------------------------------------
// outputs
// -----------------------------------------------------------------------------
io.bAlarmActive := (MLX.NumberOfQueuedErrors <> 0);
// -----------------------------------------------------------------------------
// State machine 2: reset alarm
// -----------------------------------------------------------------------------
CASE io.nSmResetAlarm OF
// -------------------------------------
// idle
// -------------------------------------
0:
IF bOsrReset AND MLX.Signals.RemoteMode
AND MLX.Signals.MLXGatewayConnected THEN
io.nErrorCode := 0;
io.nSmResetAlarm := 10;
END_IF;
// -------------------------------------
// reset alarm
// -------------------------------------
10:
fbResetAndHold.Enable := TRUE;
IF fbResetAndHold.Sts_EN AND fbResetAndHold.Sts_DN THEN
IF fbResetAndHold.Sts_ER THEN
io.nErrorCode := 2000 + io.nSmResetAlarm;
io.nSmResetAlarm := 99;
ELSE
io.nSmResetAlarm := 0;
END_IF;
END_IF;
// -------------------------------------
// state machine error
// -------------------------------------
99:
io.bError := TRUE;
io.nSmResetAlarm := 0;
END_CASE;
// -----------------------------------------------------------------------------
// outputs
// -----------------------------------------------------------------------------
io.bResetIndicator := (io.bAlarmActive AND blinkSignals.bSlow)
OR ((io.nSmResetAlarm = 10) AND blinkSignals.bFast);
// -----------------------------------------------------------------------------
// FB calls
// -----------------------------------------------------------------------------
fbGetErrorDetail(MLX := MLX);
fbResetAndHold(MLX := MLX);
Implementation
fbAlarms : ARRAY[0..0] OF MceAlarms;
fbAlarms[0]( io := dummy, blinkSignals := dummy, MLX := dummy );