MceStartStop

0.2.0

Start/stop logic for a MotoLogix system. This also implements a robot controller speed override.

For these purposes it uses two states machines:

Usage

Each MotoLogix system needs its own 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
Using a global constant to set the array size makes life easier.

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

  deGroot

Changes

Changed:
  • FB names according style guide
  • don’t brutally force the state machine to 0 on lost connection
show full history

0.1.0

  deGroot

Changes

Added:
  • initial version

Overview

kindnametypedefaultcomment
in_outioMceStartStopIOinterface data
in_outblinkSignalsMceBlinkSignalsIOsignals for blinking indicator lights
in_outMLXMLxDataMotoLogix 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

Snippet of the function call:
fbStartStop : ARRAY[0..0] OF MceStartStop;

fbStartStop[0]( io := dummy,  blinkSignals := dummy,  MLX := dummy );

Pages built with Hugo - 23 Apr 2024 11:54 CEST