Redundant Serial Link
Output CL Code

 

The purpose of these pages are to show how G&L Engineering can engineer your project.
A CL sequence will task break after executing 240 CLBACK statements. If more than 10 write statements are commanded within one sequence cycle IOL overruns are likely to occur. A pulsed digital output requires two writes, one to turn the pulse ON and one to turn the pulse OFF. This doubles the sequence overhead and should be avoided unless absolutely necessary. These points must be considered when designing the serial link and building the array points. If a task break is undesirable or more than ten writes per sequence cycle are required parallel sequences should be considered, if the quantity of data makes this impractical bit packing should be considered.

This example of controlling a redundant serial link has been made as generic as practical, only array and tagging information needs to be entered. This code must be read in conjunction with the input sequence, output sequence and watch dog timer requirements. To see how these components work together view the overview page.

This code is entirely original, developed by G&L Engineering.

-- **************************************************************
-- SEQUENCE SL_OUTPUT (SERIAL LINK OUTPUT SEQUENCE)
-- **************************************************************
-- ©2000 G&L Engineering Ltd.

-- CUSTOMER:

-- PROJECT:

-- BASED ON:

-- LOCATION:

-- CODED BY:
--
--
--
-- This sequence transfers data from array M_ARRAY_O to the primary or
-- redundant serial links.
-- The primary or redundant link is selected by sequence SLMASTER.
-- The selected link is indicated by Flag INSERVICE_P (primary) or
-- INSERVICE_R (redundant)
-- An internal WDT ensures this sequence is running. If this sequence is
-- stopped, HOLD_FLAG is set ON to stop all other sequences associated with
-- this serial link.
--
-- This program forms part of the overall Serial Interface.
-- The HPM/CL sequences including this one are;
-- SLMASTER.cl - Controls the Primary and Redundant Serial Links.
-- SLINPUT.cl - transfers Input information from the serial link.
-- SLOUTPUT.cl - transfers Output information to the serial link.
--
-- All associated logic and calculations are controlled by sequence
-- SLMASTER.
--
-- THE LAST TWO FLAGS OF DO_ARRAY1 CONTAIN LINK STATUS INFORMATION FOR
-- THE SLAVE DEVICE TO USE AS REQUIRED. WHEN CONFIGURING THE DO ARRAY
-- CALCULATE THE REQUIRED NUMBER OF FLAGS PLUS TWO!
-- IF THESE FLAGS ARE REQUIRED IN A DIFFERENT ARRAY UPDATE LINES COMMENTED
-- LINK STATUS


-- **************************************************************
Sequence SLOUTPUT (HPM; POINT SL_OUTPUT)
-- xxxxxxxx.NO
-- **************************************************************
-- The suffix P array points contain information from the primary serial link.
-- The suffix R array points contain information from the redundant serial link.
-- **************************************************************

EXTERNAL AO_ARRAY1_P, DO_ARRAY1_P
EXTERNAL AO_ARRAY1_R, DO_ARRAY1_R
EXTERNAL M_ARRAY_O
EXTERNAL INSERVICE_P -- PRIMARY LINK SELECTED
EXTERNAL INSERVICE_R -- REDUNDANT LINK SELECTED
EXTERNAL HOLD_FLAG, HOLD_FLAG_REQ -- SEQUENCE COMMAND HOLD
EXTERNAL DO_WRITES_P -- PRIMARY LINK DIGITAL WRITES PER SCAN
EXTERNAL DO_WRITES_R -- REDUNDANT LINK DIGITAL WRITES PER SCAN
EXTERNAL AO_WRITES_P -- PRIMARY LINK ANALOGUE WRITES PER SCAN
EXTERNAL AO_WRITES_R -- REDUNDANT LINK ANALOGUE WRITES PER SCAN
EXTERNAL T_WDT_OUTPUT -- WDT FOR THIS SEQUENCE

LOCAL DOUT_P AT NN(01) -- INTERNAL PRIMARY DO REGISTER
LOCAL DOUT_R AT NN(02) -- INTERNAL REDUNDANT DO REGISTER
LOCAL AOUT_P AT NN(03) -- INTERNAL PRIMARY AO REGISTER
LOCAL AOUT_R AT NN(04) -- INTERNAL REDUNDANT AO REGISTER
LOCAL WDT AT NN(10) -- WDT SP NORMALLY 4 SECONDS
LOCAL S_CALL: LOGICAL AT FL(01) -- SUBROUTINE POSITION MARKER


PHASE INITIAL
-------------

-- **************************************************************
-- Phase INITIAL, executes when this sequence is initially initiated. This phase
-- reads which serial link is in service from flags INSERVICE_P and INSERVICE_R
-- and selects the correct arrays points to write the output data.
-- **************************************************************

STEP STARTUP
-- -----------

SET INSERVICE_P.PVFL, INSERVICE_R.PVFL = OFF

-- THIS SEQUENCE WILL NOT PROCEED IF MASTER IS NOT RUNNING

-- Set up Watch Dog Timer
A10: SET T_WDT_OUTPUT.COMMAND = STOP
SET T_WDT_OUTPUT.COMMAND = RESET
SET T_WDT_OUTPUT.TIMEBASE = SECONDS
IF WDT < 2 THEN SET WDT = 4 IF WDT > 8 THEN SET WDT = 4
SET T_WDT_OUTPUT.SP = WDT
SET T_WDT_OUTPUT.COMMAND = RESTSTRT

-- RESET SCAN REGISTR
SET DO_WRITES_P.PV, DO_WRITES_R.PV = 0
SET AO_WRITES_P.PV, AO_WRITES_R.PV = 0

-- Check which link is in-service
IF INSERVICE_P.PVFL = ON AND INSERVICE_R.PVFL = OFF THEN
& GOTO PHASE PRI_LINK

IF INSERVICE_R.PVFL = ON AND INSERVICE_P.PVFL = OFF THEN
& GOTO PHASE RED_LINK
GOTO A10



PHASE PRI_LINK (HOLD LINKFAIL)
-- ------------------------------

-- **************************************************************
-- Phase PRI_LINK, writes Digital and Analogue Output data from the common
-- output array to the Primary Output arrays.
-- **************************************************************

STEP MONITOR
-- ------------

IF DO_ARRAY1_P.BADPVFL OR AO_ARRAY1_P.BADPVFL THEN
& GOTO PHASE INITIAL
IF INSERVICE_P.PVFL = OFF THEN GOTO PHASE INITIAL

-- Set up Watch Dog Timer every programme cycle
SET T_WDT_OUTPUT.COMMAND = STOP
SET T_WDT_OUTPUT.COMMAND = RESET
SET T_WDT_OUTPUT.TIMEBASE = SECONDS
IF WDT < 2 THEN SET WDT = 4
IF WDT > 8 THEN SET WDT = 4
SET T_WDT_OUTPUT.SP = WDT
SET T_WDT_OUTPUT.COMMAND = RESTSTRT

SET S_CALL = ON

-- Reset write registers
SET DO_WRITES_R.PV, AO_WRITES_R.PV = 0
SET DOUT_P, DOUT_R, AOUT_R = 0

-- Update link status to Master Array
SET M_ARRAY_O.FL(DO_ARRAY1_P.NFLAG - 1) = INSERVICE_P.PVFL
SET M_ARRAY_O.FL(DO_ARRAY1_P.NFLAG) = INSERVICE_R.PVFL

-- Update primary link with link status
-- Next two bits must be written together
A1: LOOP FOR D IN DO_ARRAY1_P.NFLAG - 1 .. DO_ARRAY1_P.NFLAG
IF DO_ARRAY1_P.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_P.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_P = DOUT_P + 1; SET DO_WRITES_P.PV = DOUT_P)
REPEAT A1

-- update redundant link with link status
-- Do not write to the Redundant link if it is bad.
IF DO_ARRAY1_R.BADPVFL = ON THEN GOTO A11
SET DOUT_R = 0

-- Next two bits must be written together
A2: LOOP FOR D IN DO_ARRAY1_P.NFLAG - 1 .. DO_ARRAY1_P.NFLAG
IF DO_ARRAY1_R.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_R.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_R = DOUT_R + 1;
SET DO_WRITES_R.PV = DOUT_R)
REPEAT A2

-- WRITE DIGITAL OUTPUT DATA
A11: LOOP FOR D IN 1 .. DO_ARRAY1_P.NFLAG
-- **************************************************************
-- If Array is not packed use this statement to jump large gaps
-- IF D = xx THEN SET D = xx
-- IF D > DO_ARRAY1_P.NFLAG THEN SET D = DO_ARRAY1.NFLAG
-- **************************************************************
IF DO_ARRAY1_P.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_P.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_P = DOUT_P + 1)
IF DOUT_P >= 8 THEN CALL AOPRI
REPEAT A11

-- **************************************************************
-- REPEAT ABOVE FOR EACH DIGITAL OUTPUT ARRAY.
-- IN STATEMENT "SET DO_ARRAYx_P.FL(D) = M_ARRAY_O.FL(D)" ADD OFFSET EQUAL
-- TO THE PREVIOUS ARRAY SIZE.
-- ie. "SET DO_ARRAYx_P.FL(D) = M_ARRAY_O.FL(D + DO_ARRAY1_P.NFLAG)"
-- **************************************************************

-- **************************************************************
-- IF OVERRUNS OCCUR INSERT THESE LINES AFTER A REPEAT STATEMENT AND
-- BEFORE THE NEXT LOOP STATEMENT.
-- WAIT 1 SECS
-- Set up Watch Dog Timer every programme cycle
-- SET T_WDT_OUTPUT.COMMAND = STOP
-- SET T_WDT_OUTPUT.COMMAND = RESET
-- SET T_WDT_OUTPUT.TIMEBASE = SECONDS
-- IF WDT < 2 THEN SET WDT = 4
-- IF WDT > 8 THEN SET WDT = 4
-- SET T_WDT_OUTPUT.SP = WDT
-- SET T_WDT_OUTPUT.COMMAND = RESTSTRT
-- **************************************************************

A10: SET S_CALL = OFF
CALL AOPRI
GOTO STEP MONITOR


PHASE RED_LINK (HOLD LINKFAIL)
-- ------------------------------

-- **************************************************************
-- Phase RED_LINK, writes Digital and Analogue Output data from the common
-- output array to the Redundant Output arrays.
-- **************************************************************

STEP MONITOR
-- ----------

IF DO_ARRAY1_R.BADPVFL OR AO_ARRAY1_R.BADPVFL THEN
& GOTO PHASE INITIAL
IF INSERVICE_R.PVFL = OFF THEN GOTO PHASE INITIAL

SET T_WDT_OUTPUT.COMMAND = STOP
SET T_WDT_OUTPUT.COMMAND = RESET
SET T_WDT_OUTPUT.TIMEBASE = SECONDS
IF WDT < 2 THEN SET WDT = 4 IF WDT > 8 THEN SET WDT = 4
SET T_WDT_OUTPUT.SP = WDT
SET T_WDT_OUTPUT.COMMAND = RESTSTRT

SET S_CALL = ON

-- Reset write registers
SET DO_WRITES_P.PV, AO_WRITES_P.PV = 0
SET DOUT_R, DOUT_P, AOUT_P = 0

-- Update link status to Master Array
SET M_ARRAY_O.FL(DO_ARRAY1_P.NFLAG - 1) = INSERVICE_P.PVFL
SET M_ARRAY_O.FL(DO_ARRAY1_P.NFLAG) = INSERVICE_R.PVFL

-- Update redundant link with link status
-- Next two bits must be written together
A1: LOOP FOR D IN DO_ARRAY1_P.NFLAG - 1 .. DO_ARRAY1_P.NFLAG
IF DO_ARRAY1_R.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_R.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_R = DOUT_R + 1)
REPEAT A1

-- update primary link with link status
-- Do not write to the Redundant link if it is bad.
IF DO_ARRAY1_P.BADPVFL = ON THEN GOTO A11
SET DOUT_P = 0

-- Next two bits must be written together
A2: LOOP FOR D IN DO_ARRAY1_P.NFLAG - 1 .. DO_ARRAY1_P.NFLAG
IF DO_ARRAY1_P.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_P.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_P = DOUT_P + 1)
REPEAT A2

-- WRITE DIGITAL OUTPUT DATA
A11: LOOP FOR D IN 1 .. DO_ARRAY1_R.NFLAG

-- **************************************************************
-- If Array is not packed use this statement to jump large gaps
-- IF D = xx THEN SET D = xx
-- IF D > DO_ARRAY1_R.NFLAG THEN SET D = DO_ARRAY1_R.NFLAG
-- **************************************************************

IF DO_ARRAY1_R.FL(D) <> M_ARRAY_O.FL(D) THEN
& (SET DO_ARRAY1_R.FL(D) = M_ARRAY_O.FL(D);
& SET DOUT_R = DOUT_R + 1)
IF DOUT_R >= 8 THEN CALL AORED
REPEAT A11

-- **************************************************************
-- REPEAT ABOVE FOR EACH DIGITAL OUTPUT ARRAY.
-- IN STATEMENT "SET DO_ARRAYx_R.FL(D) = M_ARRAY_O.FL(D)" ADD OFFSET
-- EQUAL TO THE PREVIOUS ARRAY SIZE.
-- ie. "SET DO_ARRAYx_R.FL(D) = M_ARRAY_O.FL(D + DO_ARRAY1_R.NFLAG)"
-- **************************************************************

-- **************************************************************
-- IF OVERRUNS OCCUR INSERT THESE LINES AFTER A REPEAT STATEMENT AND
-- BEFORE THE NEXT LOOP STATEMENT.
-- WAIT 1 SECS
-- Set up Watch Dog Timer every programme cycle
-- SET T_WDT_OUTPUT.COMMAND = STOP
-- SET T_WDT_OUTPUT.COMMAND = RESET
-- SET T_WDT_OUTPUT.TIMEBASE = SECONDS
-- IF WDT < 2 THEN SET WDT = 4
-- IF WDT > 8 THEN SET WDT = 4
-- SET T_WDT_OUTPUT.SP = WDT
-- SET T_WDT_OUTPUT.COMMAND = RESTSTRT
-- **************************************************************

A10: SET S_CALL = OFF
CALL AORED
GOTO STEP MONITOR


END SLOUTPUT

 

-- **************************************************************
-- LINKFAIL is activated from phase PRI_LINK or phase RED_LINK when the serial
-- link currently in service fails. The Hold Handler will wait until a usable
-- serial link is selected by sequence SL_C802_CONTROL
-- **************************************************************
-- **************************************************************
HOLD HANDLER LINKFAIL (WHEN ((AO_ARRAY1_P.BADPVFL = ON OR
& DO_ARRAY1_P.BADPVFL = ON) AND INSERVICE_P.PVFL = ON)
& OR ((AO_ARRAY1_R.BADPVFL = ON OR
& DO_ARRAY1_R.BADPVFL = ON) AND INSERVICE_R.PVFL = ON)
& OR & HOLD_FLAG.PVFL = ON)
-- **************************************************************
SET HOLD_FLAG_REQ.PVFL = ON
-- HOLD ALL SEQUENCES SET INSERVICE_P.PVFL, INSERVICE_R.PVFL = OFF
-- LINK NOT IN SERVICE

-- Set up Watch Dog Timer every programme cycle
A10: SET T_WDT_OUTPUT.COMMAND = STOP
SET T_WDT_OUTPUT.COMMAND = RESET
SET T_WDT_OUTPUT.TIMEBASE = SECONDS
IF WDT < 2 THEN SET WDT = 4 IF WDT > 8 THEN SET WDT = 4
SET T_WDT_OUTPUT.SP = WDT
SET T_WDT_OUTPUT.COMMAND = RESTSTRT

SET DO_WRITES_P.PV, AO_WRITES_P.PV = 0
SET DO_WRITES_R.PV, AO_WRITES_R.PV = 0

IF HOLD_FLAG.PVFL = ON THEN GOTO A10
IF INSERVICE_P.PVFL = OFF AND INSERVICE_R.PVFL = OFF THEN GOTO A10

RESTART
-- -------

IF INSERVICE_P.PVFL = ON AND INSERVICE_R.PVFL = OFF THEN
& RESUME PHASE PRI_LINK

IF INSERVICE_R.PVFL = ON AND INSERVICE_P.PVFL = OFF THEN
& RESUME PHASE RED_LINK

SET T_WDT_OUTPUT.COMMAND = RESTSTRT

RESUME PHASE INITIAL


END LINKFAIL


-- **************************************************************
-- SUBROUTINES
-- **************************************************************
SUBROUTINE AOPRI
-- ----------------
SET DO_WRITES_P.PV = DOUT_P
SET AO_WRITES_P.PV = 0

IF AOUT_P < 1 OR AOUT_P > AO_ARRAY1_P.NNUMERIC THEN SET AOUT_P = 1
SET AO_ARRAY1_P.NN(AOUT_P) = M_ARRAY_O.NN(AOUT_P)
SET AOUT_P = AOUT_P + 1
SET AO_WRITES_P.PV = AO_WRITES_P.PV + 1

IF AOUT_P < 1 OR AOUT_P > AO_ARRAY1_P.NNUMERIC THEN SET AOUT_P = 1
SET AO_ARRAY1_P.NN(AOUT_P) = M_ARRAY_O.NN(AOUT_P)
SET AOUT_P = AOUT_P + 1
SET AO_WRITES_P.PV = AO_WRITES_P.PV + 1
SET DOUT_P = 0

IF S_CALL = OFF THEN GOTO A10
WAIT 1 SECS

-- THIS IS NOT A PREFETCH ENTRY OR EXIT SUBROUTINE
A10: SET S_CALL = ON

EXIT

END AOPRI


SUBROUTINE AORED
-- ----------------

SET DO_WRITES_R.PV = DOUT_R
SET AO_WRITES_R.PV = 0

IF AOUT_R < 1 OR AOUT_R > AO_ARRAY1_R.NNUMERIC THEN SET AOUT_R = 1
SET AO_ARRAY1_R.NN(AOUT_R) = M_ARRAY_O.NN(AOUT_R)
SET AOUT_R = AOUT_R + 1
SET AO_WRITES_R.PV = AO_WRITES_R.PV + 1

IF AOUT_R < 1 OR AOUT_R > AO_ARRAY1_R.NNUMERIC THEN SET AOUT_R = 1
SET AO_ARRAY1_R.NN(AOUT_R) = M_ARRAY_O.NN(AOUT_R)
SET AOUT_R = AOUT_R + 1
SET AO_WRITES_R.PV = AO_WRITES_R.PV + 1
SET DOUT_R = 0

IF S_CALL = OFF THEN GOTO A10
WAIT 1 SECS

-- THIS IS NOT A PREFETCH ENTRY OR EXIT SUBROUTINE
A10: SET S_CALL = ON

EXIT


END AORED

 

-- End of File

 

Goto our examples page to see implementation examples.

 

This code is entirely original, developed by G&L Engineering.
© 2000 G&L Engineering Ltd.

 

 

Goto Top Of Page

For information or comments contact: Sales@GandLengineering.co.uk

If you directly addressed this page click here to enter this site and activate the menus.