|
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.
|