Start/stop logic for a MotoLogix system. This also implements a robot controller speed override.
For these purposes it uses two states machines:
nSmStartStop
- handling the start/stop (resulting in changing theMLX.systemState
)nSmSpeedOverride
- handling the controller speed override
Usage
MceStartStop
instance.We start by creating the (global) variables for the interface data. These variables are also used for connecting buttons or an HMI.
stStartStop : ARRAY [0..GVL.MLX_UBOUND] OF MceStartStopIO; // data for start/stop of a MotoLogix system
Now we create the instances:
fbMceStartStop : ARRAY [0..GVL.MLX_UBOUND] OF MceStartStop;
Map all relevant inputs (see MceStartStopIO
)
to your HMI and/or to higher level state machines.
// this is just a portion of the relevant signals
GVL.stStartStop[0].bStart := ...;
GVL.stStartStop[0].bStop := ...;
GVL.stStartStop[0].fSpeedOverride := ...;
GVL.stStartStop[0].bExternalConditionsOk := ...;
Since we defined the variables as arrays we can process the function calls in a loop:
// function call
FOR i := 0 TO GVL.MLX_UBOUND DO
fbStartStop[i](
io := GVL.stStartStop[i],
blinkSignals := GVL.stBlinkSignals,
MLX := GVL.stMLX[i]);
END_FOR;
Map all relevant outputs (see MceStartStopIO
)
to your HMI and/or to higher level state machines.
// this is just a portion of the relevant signals
... := GVL.stStartStop[0].bStartIndicator;
... := GVL.stStartStop[0].bStopIndicator;
... := GVL.stStartStop[0].bSystemReady;
Version history
0.2.0
Changes
- FB names according style guide
- don’t brutally force the state machine to 0 on lost connection
show full history
0.1.0
Changes
- initial version
Overview
kind | name | type | default | comment |
---|---|---|---|---|
in_out | io | MceStartStopIO | 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
(*Start/stop logic + speed override*)
FUNCTION_BLOCK MceStartStop
(*
* -----------------------------------------------------------------------------
* Name : MceStartStop
* Version : 0.2.0
* Date : 2022-02-23
* Author : deGroot
* Family : YaskawaMce
* Organisation : github.com/YaskawaEurope/mlx-examples
*
* -----------------------------------------------------------------------------
* Start/stop logic + speed override
* -----------------------------------------------------------------------------
*)
VAR_IN_OUT
io : MceStartStopIO; (*interface data*)
blinkSignals : MceBlinkSignalsIO; (*signals for blinking indicator lights*)
MLX : MLxData; (*MotoLogix shared memory variable*)
END_VAR
VAR
fbAbort : MLxAbort;
fbEnable : MLxEnable;
fbReset : MLxReset;
fbHold : MLxHold;
fbRestart : MLxRestart;
fbSetGlobalParameter : MLxSetGlobalParameter;
fbStop : MLxStop;
fbIdleTime : TON;
fSpeedOverrideStored : REAL; (*stored value for comparison*)
bOsrStart : BOOL; (*rising edge*)
bOsrStop : BOOL; (*rising edge*)
bOsrFlush : BOOL; (*rising edge*)
bOsrSystemReady : BOOL; (*rising edge*)
bAllConditionsOk : BOOL; (*external- and internal conditions ok*)
aOneShots : ARRAY [0..3] OF BOOL; (*bits for one shot signals*)
END_VAR
Logic
// -----------------------------------------------------------------------------
// init
// -----------------------------------------------------------------------------
io.bError := FALSE;
fbAbort.Enable := FALSE;
fbEnable.Enable := FALSE;
fbHold.Enable := FALSE;
fbReset.Enable := FALSE;
fbRestart.Enable := FALSE;
fbStop.Enable := FALSE;
fbSetGlobalParameter.Enable := FALSE;
fbIdletime.IN := FALSE;
// -----------------------------------------------------------------------------
// common
// -----------------------------------------------------------------------------
// rising edge signals
bOsrStart := io.bStart AND NOT aOneShots[0];
aOneShots[0] := io.bStart;
bOsrStop := io.bStop AND NOT aOneShots[1];
aOneShots[1] := io.bStop;
bOsrFlush:= io.bFlush AND NOT aOneShots[2];
aOneShots[2] := io.bFlush;
bOsrSystemReady:= io.bSystemReady AND NOT aOneShots[3];
aOneShots[3] := io.bSystemReady;
bAllConditionsOk :=
io.bExternalConditionsOk AND
MLX.Signals.MLXGatewayConnected AND
MLX.Signals.RemoteMode AND NOT
MLX.Signals.EStop1Pressed AND NOT
MLX.Signals.EStop2Pressed AND NOT
MLX.Signals.EStop3Pressed AND NOT
MLX.Signals.GuardCircuitOpen;
// -----------------------------------------------------------------------------
// State machine: system start/stop
// -----------------------------------------------------------------------------
CASE io.nSmStartStop OF
// -------------------------------------
// idle, not ready for start
// -------------------------------------
0:
IF bAllConditionsOk AND NOT io.bStop AND NOT io.bFlush THEN
io.nSmStartStop := 1;
END_IF;
// -------------------------------------
// ready for start
// -------------------------------------
1:
IF bAllConditionsOk THEN
// start
IF bOsrStart THEN
io.nErrorCode := 0;
io.nSmStartStop := 10;
END_IF;
// abort if system still enabled
// (e.g. caused by pendant operations in PLAY mode)
IF (MLX.SystemState = 3) OR (MLX.SystemState = 4) THEN
io.nErrorCode := 0;
io.nSmStartStop := 70;
END_IF;
END_IF;
IF NOT bAllConditionsOk OR io.bStop OR io.bFlush THEN
io.nSmStartStop := 0;
END_IF;
// -------------------------------------
// reset system with MLxReset
// -------------------------------------
10:
fbReset.Enable := TRUE;
IF fbReset.Sts_EN AND fbReset.Sts_DN THEN
IF fbReset.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmStartStop;
io.nSmStartStop := 70;
ELSE
io.nSmStartStop := 20;
END_IF;
END_IF;
// -------------------------------------
// enable system with MLxEnable
// -------------------------------------
20:
fbEnable.Enable := TRUE;
IF fbEnable.Sts_EN AND fbEnable.Sts_DN AND (MLX.SystemState <> 1)
AND (MLX.SystemState <> 2) THEN
IF fbEnable.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmStartStop;
io.nSmStartStop := 70;
ELSE
io.nSmStartStop := 30;
END_IF;
END_IF;
// -------------------------------------
// system ready for processing motion commands
// -------------------------------------
30:
// Hold initiated by start button
IF bOsrStart AND (MLX.SystemState = 4) THEN
io.nSmStartStop := 35;
END_IF;
// Hold initiated by pendant button
IF (MLX.SystemState = 6) THEN
io.nSmStartStop := 40;
END_IF;
// Flush
IF bOsrFlush THEN
io.nSmStartStop := 50;
END_IF;
IF bOsrStop OR NOT bAllConditionsOk THEN
io.nSmStartStop := 60;
END_IF;
// -------------------------------------
// hold motion with MLxHold
// -------------------------------------
35:
fbHold.Enable := TRUE;
IF fbHold.Sts_EN AND fbHold.Sts_DN AND (MLX.SystemState <> 5) THEN
IF fbHold.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmStartStop;
io.nSmStartStop := 70;
ELSE
io.nSmStartStop := 40;
END_IF;
END_IF;
// -------------------------------------
// system held (restart with start button)
// -------------------------------------
40:
// Restart initiated by start button
IF bOsrStart THEN
io.nSmStartStop := 45;
END_IF;
// Flush
IF bOsrFlush THEN
io.nSmStartStop := 50;
END_IF;
IF bOsrStop OR NOT bAllConditionsOk THEN
io.nSmStartStop := 60;
END_IF;
// -------------------------------------
// restart motion with MLxRestart
// -------------------------------------
45:
fbRestart.Enable := TRUE;
IF fbRestart.Sts_EN AND fbRestart.Sts_DN THEN
IF fbRestart.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmStartStop;
io.nSmStartStop := 70;
ELSE
io.nSmStartStop := 30;
END_IF;
END_IF;
// -------------------------------------
// stop and flush buffered motions with MLxStop
// -------------------------------------
50:
fbStop.Enable := TRUE;
IF fbStop.Sts_EN AND fbStop.Sts_DN AND (MLX.SystemState <> 9)
AND (MLX.SystemState <> 10) AND (MLX.SystemState <> 11) THEN
IF fbStop.Sts_ER THEN
io.nErrorCode := 1000 + io.nSmStartStop;
io.nSmStartStop := 70;
ELSE
io.nSmStartStop := 45;
END_IF;
END_IF;
// -------------------------------------
// finish buffered motions
// (for future)
// -------------------------------------
60:
io.nSmStartStop := 70;
// -------------------------------------
// abort motion and disable system with MLxAbort
// -------------------------------------
70:
fbAbort.Enable := TRUE;
IF fbAbort.Sts_EN AND fbAbort.Sts_DN AND (MLX.SystemState <> 7) THEN
IF fbAbort.Sts_ER OR (io.nErrorCode > 0) THEN
IF (io.nErrorCode = 0) THEN
io.nErrorCode := 1000 + io.nSmStartStop;
END_IF;
io.nSmStartStop := 99;
ELSE
io.nSmStartStop := 0;
END_IF;
END_IF;
// -------------------------------------
// state machine error
// -------------------------------------
99:
io.bError := TRUE;
io.nSmStartStop := 0;
ELSE
io.nSmStartStop := 0;
END_CASE;
// -----------------------------------------------------------------------------
// outputs
// -----------------------------------------------------------------------------
io.bSystemReady :=
(io.nSmStartStop = 30) OR
(io.nSmStartStop = 35) OR
(io.nSmStartStop = 40) OR
(io.nSmStartStop = 45) OR
(io.nSmStartStop = 60);
// stop indicator
CASE io.nSmStartStop OF
0,
1:
io.bStopIndicator := TRUE;
60:
io.bStartIndicator := blinkSignals.bSlow;
70:
io.bStopIndicator := blinkSignals.bFast;
ELSE
io.bStopIndicator := FALSE;
END_CASE;
// start indicator
CASE io.nSmStartStop OF
1:
io.bStartIndicator := blinkSignals.bDoubleFlash;
10,
20,
35,
45,
50:
io.bStartIndicator := blinkSignals.bFast;
30:
io.bStartIndicator := TRUE;
40:
io.bStartIndicator := blinkSignals.bSlow;
ELSE
io.bStartIndicator := FALSE;
END_CASE;
// -----------------------------------------------------------------------------
// State machine: speed override
// -----------------------------------------------------------------------------
CASE io.nSmSpeedOverride OF
// -------------------------------------
// idle
// -------------------------------------
0:
fbIdletime.IN := TRUE;
IF fbIdletime.Q AND io.bSystemReady
AND (io.fSpeedOverride <> fSpeedOverrideStored) THEN
fSpeedOverrideStored := io.fSpeedOverride;
io.nErrorCode := 0;
io.nSmSpeedOverride := 10;
END_IF;
// -------------------------------------
// send speed override
// -------------------------------------
10:
fbSetGlobalParameter.Enable := TRUE;
IF fbSetGlobalParameter.Sts_EN AND fbSetGlobalParameter.Sts_DN THEN
IF fbSetGlobalParameter.Sts_ER THEN
io.nErrorCode := 2000 + io.nSmSpeedOverride;
io.nSmSpeedOverride := 99;
ELSE
io.nSmSpeedOverride := 0;
END_IF;
END_IF;
// -------------------------------------
// state machine error
// -------------------------------------
99:
io.bError := TRUE;
io.nSmSpeedOverride := 0;
END_CASE;
// send speed override at every rising edge of system ready
IF bOsrSystemReady THEN
fSpeedOverrideStored := -1;
END_IF;
// -----------------------------------------------------------------------------
// FB calls
// -----------------------------------------------------------------------------
fbAbort(MLX := MLX);
fbEnable(MLX := MLX);
fbHold(MLX := MLX);
fbReset(MLX := MLX);
fbRestart(MLX := MLX);
fbStop(MLX := MLX);
fbSetGlobalParameter(
ParameterType := 0,
ParameterValue := LIMIT(0.0, io.fSpeedOverride, 150.0),
MLX := MLX);
fbIdletime(PT := T#10MS);
Implementation
fbStartStop : ARRAY[0..0] OF MceStartStop;
fbStartStop[0]( io := dummy, blinkSignals := dummy, MLX := dummy );