DUTs
DUT_MotionStage_Extras
TYPE DUT_MotionStage_Extras :
STRUCT
fVisuStep: LREAL;
bVisuLowLim: BOOL;
bVisuHighLim: BOOL;
END_STRUCT
END_TYPE
- Related:
ENUM_SXR_SATT_Position
{attribute 'qualified_only'}
TYPE ENUM_SXR_SATT_Position :
(
UNKNOWN := 0, // UNKNOWN must be in slot 0 or the FB breaks
OUT := 1, // OUT at slot 1 is a convention
FILTER1 := 2,
FILTER2 := 3,
FILTER3 := 4,
FILTER4 := 5
);
END_TYPE
GVLs
Main
{attribute 'qualified_only'}
VAR_GLOBAL
(*
Only includes motor definitions for the IOC
These are hard-coded to be Main.M#,
but are very convenient to store in a GVL,
hence the confusing namespace here
This should be refactored once the IOC
supports arbitrary ads paths for motors
*)
(*
Four identical systems:
Instr. Area ID# Z (m)
TMO FEE AT1K4-SOLID 748
NEH 2.2 H2.2 AT1K2-SOLID 784
NEH 2.2 H2.2 AT2K2-SOLID 788.8
TXI H1.1 AT1K3-SOLID ~763
*)
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:01'}
{attribute 'TcLinkTo' := '
.bLimitForwardEnable := TIIB[AT1K4-EL7047-01]^STM Status^Status^Digital input 1;
.bLimitBackwardEnable := TIIB[AT1K4-EL7047-01]^STM Status^Status^Digital input 2;
.nRawEncoderULINT := TIIB[AT1K4-EL5042-01]^FB Inputs Channel 1^Position;
'}
M1: DUT_MotionStage := (sName := 'AT1K4:L2SI:MMS:01');
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:02'}
{attribute 'TcLinkTo' := '
.bLimitForwardEnable := TIIB[AT1K4-EL7047-02]^STM Status^Status^Digital input 1;
.bLimitBackwardEnable := TIIB[AT1K4-EL7047-02]^STM Status^Status^Digital input 2;
.nRawEncoderULINT := TIIB[AT1K4-EL5042-01]^FB Inputs Channel 2^Position;
'}
M2: DUT_MotionStage := (sName := 'AT1K4:L2SI:MMS:02');
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:03'}
{attribute 'TcLinkTo' := '
.bLimitForwardEnable := TIIB[AT1K4-EL7047-03]^STM Status^Status^Digital input 1;
.bLimitBackwardEnable := TIIB[AT1K4-EL7047-03]^STM Status^Status^Digital input 2;
.nRawEncoderULINT := TIIB[AT1K4-EL5042-02]^FB Inputs Channel 1^Position;
'}
M3: DUT_MotionStage := (sName := 'AT1K4:L2SI:MMS:03');
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:04'}
{attribute 'TcLinkTo' := '
.bLimitForwardEnable := TIIB[AT1K4-EL7047-04]^STM Status^Status^Digital input 1;
.bLimitBackwardEnable := TIIB[AT1K4-EL7047-04]^STM Status^Status^Digital input 2;
.nRawEncoderULINT := TIIB[AT1K4-EL5042-02]^FB Inputs Channel 2^Position;
'}
M4: DUT_MotionStage := (sName := 'AT1K4:L2SI:MMS:04');
END_VAR
POUs
FB_SXR_SATT_PositionState
FUNCTION_BLOCK FB_SXR_SATT_PositionState EXTENDS FB_PositionStateBase
VAR_INPUT
// The enum position to move to
{attribute 'pytmc' := '
pv: SET
io: io
'}
enumSet: ENUM_SXR_SATT_Position;
// NOTE: Do not pragma these, let it happen in the manager.
// Information about the OUT position
stOut : DUT_PositionState;
stFilter1 : DUT_PositionState;
stFilter2 : DUT_PositionState;
stFilter3 : DUT_PositionState;
stFilter4 : DUT_PositionState;
END_VAR
VAR_OUTPUT
// The enum state readback
{attribute 'pytmc' := '
pv: GET
io: i
'}
enumGet: ENUM_SXR_SATT_Position;
END_VAR
VAR
bInitialized: BOOL := FALSE;
END_VAR
IF NOT bInitialized THEN
bInitialized := TRUE;
arrStates[1] := stOut;
arrStates[2] := stFilter1;
arrStates[3] := stFilter2;
arrStates[4] := stFilter3;
arrStates[5] := stFilter4;
END_IF
setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;
END_FUNCTION_BLOCK
- Related:
FB_SXR_SATT_Stage
FUNCTION_BLOCK FB_SXR_SATT_Stage
VAR_IN_OUT
stAxis : DUT_MotionStage;
END_VAR
VAR_INPUT
nEnableMode : ENUM_StageEnableMode;
stOut : DUT_PositionState;
stFilter1 : DUT_PositionState;
stFilter2 : DUT_PositionState;
stFilter3 : DUT_PositionState;
stFilter4 : DUT_PositionState;
END_VAR
VAR_OUTPUT
stExtra : DUT_MotionStage_Extras;
fTemp1 : LREAL;
fTemp2 : LREAL;
END_VAR
VAR
// TODO: debug
// fbMotion: FB_MotionStage;
fbMotion: FB_MotionStageSim;
{attribute 'pytmc' := '
pv: STATE
'}
fbState : FB_SXR_SATT_PositionState;
bInitialized: BOOL := FALSE;
(* EL3202-0020: 0.01 °C per digit *)
{attribute 'pytmc' := 'pv: RTD:1'}
fbRTD_1: FB_TempSensor := ( fResolution:=0.01 );
{attribute 'pytmc' := 'pv: RTD:2'}
fbRTD_2: FB_TempSensor := ( fResolution:=0.01 );
END_VAR
IF NOT bInitialized THEN
bInitialized := TRUE;
(* Defaults for DUT_MotionStage *)
stAxis.bHardwareEnable := TRUE;
stAxis.bLimitBackwardEnable := TRUE;
stAxis.bLimitForwardEnable := TRUE;
stAxis.bPowerSelf := TRUE;
stAxis.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
stAxis.nHomingMode := ENUM_EpicsHomeCmd.NONE;
(* Defaults for visualization *)
stExtra.fVisuStep := 0.1;
END_IF
fbRTD_1();
fTemp1 := fbRTD_1.fTemp;
fbRTD_2();
fTemp2 := fbRTD_2.fTemp;
stAxis.nEnableMode := nEnableMode;
fbMotion(stMotionStage:=stAxis);
fbState(
bEnable:=TRUE,
bReset:=FALSE,
stMotionStage:=stAxis,
stOut:=stOut,
stFilter1:=stFilter1,
stFilter2:=stFilter2,
stFilter3:=stFilter3,
stFilter4:=stFilter4
);
stExtra.bVisuHighLim := NOT stAxis.bAllForwardEnable;
stExtra.bVisuLowLim := NOT stAxis.bAllBackwardEnable;
END_FUNCTION_BLOCK
PRG_1_PlcTask
PROGRAM PRG_1_PlcTask
VAR
fbLogHandler: FB_LogHandler;
END_VAR
fbLogHandler();
PRG_2_AT1K4();
END_PROGRAM
- Related:
PRG_2_AT1K4
PROGRAM PRG_2_AT1K4
VAR
(* TODO: use FALSE for simulation and production *)
(* TODO: use TRUE when relying on visualization + actual hardware *)
bDebug : BOOL := FALSE;
nEnableMode : ENUM_StageEnableMode;
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:01'}
{attribute 'TcLinkTo' := '
.fbRTD_1.iRaw := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 1^Value;
.fbRTD_1.bError := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 1^Status^Error;
.fbRTD_1.bUnderrange := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 1^Status^Underrange;
.fbRTD_1.bOverrange := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 1^Status^Overrange;
.fbRTD_2.iRaw := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 2^Value;
.fbRTD_2.bError := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 2^Status^Error;
.fbRTD_2.bUnderrange := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 2^Status^Underrange;
.fbRTD_2.bOverrange := TIIB[AT1K4-EL3202-01]^RTD Inputs Channel 2^Status^Overrange;
'}
fbStage1: FB_SXR_SATT_Stage;
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:02'}
{attribute 'TcLinkTo' := '
.fbRTD_1.iRaw := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 1^Value;
.fbRTD_1.bError := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 1^Status^Error;
.fbRTD_1.bUnderrange := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 1^Status^Underrange;
.fbRTD_1.bOverrange := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 1^Status^Overrange;
.fbRTD_2.iRaw := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 2^Value;
.fbRTD_2.bError := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 2^Status^Error;
.fbRTD_2.bUnderrange := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 2^Status^Underrange;
.fbRTD_2.bOverrange := TIIB[AT1K4-EL3202-02]^RTD Inputs Channel 2^Status^Overrange;
'}
fbStage2: FB_SXR_SATT_Stage;
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:03'}
{attribute 'TcLinkTo' := '
.fbRTD_1.iRaw := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 1^Value;
.fbRTD_1.bError := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 1^Status^Error;
.fbRTD_1.bUnderrange := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 1^Status^Underrange;
.fbRTD_1.bOverrange := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 1^Status^Overrange;
.fbRTD_2.iRaw := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 2^Value;
.fbRTD_2.bError := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 2^Status^Error;
.fbRTD_2.bUnderrange := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 2^Status^Underrange;
.fbRTD_2.bOverrange := TIIB[AT1K4-EL3202-03]^RTD Inputs Channel 2^Status^Overrange;
'}
fbStage3: FB_SXR_SATT_Stage;
{attribute 'pytmc' := 'pv: AT1K4:L2SI:MMS:04'}
{attribute 'TcLinkTo' := '
.fbRTD_1.iRaw := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 1^Value;
.fbRTD_1.bError := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 1^Status^Error;
.fbRTD_1.bUnderrange := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 1^Status^Underrange;
.fbRTD_1.bOverrange := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 1^Status^Overrange;
.fbRTD_2.iRaw := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 2^Value;
.fbRTD_2.bError := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 2^Status^Error;
.fbRTD_2.bUnderrange := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 2^Status^Underrange;
.fbRTD_2.bOverrange := TIIB[AT1K4-EL3202-04]^RTD Inputs Channel 2^Status^Overrange;
'}
fbStage4: FB_SXR_SATT_Stage;
END_VAR
IF bDebug THEN
// NEVER: checkouts with the TwinCAT NC GUI.
nEnableMode := ENUM_StageEnableMode.NEVER;
ELSE
// ALWAYS: want active position correction at all times
nEnableMode := ENUM_StageEnableMode.ALWAYS;
END_IF
(* State setup - stage 1 *)
fbStage1.stOut.sName := 'Out';
fbStage1.stOut.fPosition := 50;
fbStage1.stOut.fDelta := 100;
fbStage1.stOut.fVelocity := 10;
fbStage1.stOut.bValid := TRUE;
fbStage1.stOut.bMoveOk := TRUE;
fbStage1.stFilter1.sName := 'Filter 1';
fbStage1.stFilter1.fPosition := 500;
fbStage1.stFilter1.fDelta := 0;
fbStage1.stFilter1.fVelocity := 10;
fbStage1.stFilter1.bValid := FALSE;
fbStage1.stFilter1.bMoveOk := FALSE;
fbStage1.stFilter2.sName := 'Filter 2';
fbStage1.stFilter2.fPosition := 500;
fbStage1.stFilter2.fDelta := 0;
fbStage1.stFilter2.fVelocity := 10;
fbStage1.stFilter2.bValid := FALSE;
fbStage1.stFilter2.bMoveOk := FALSE;
fbStage1.stFilter3.sName := 'Filter 3';
fbStage1.stFilter3.fPosition := 500;
fbStage1.stFilter3.fDelta := 0;
fbStage1.stFilter3.fVelocity := 10;
fbStage1.stFilter3.bValid := FALSE;
fbStage1.stFilter3.bMoveOk := FALSE;
fbStage1.stFilter4.sName := 'Filter 4';
fbStage1.stFilter4.fPosition := 500;
fbStage1.stFilter4.fDelta := 0;
fbStage1.stFilter4.fVelocity := 10;
fbStage1.stFilter4.bValid := FALSE;
fbStage1.stFilter4.bMoveOk := FALSE;
fbStage1(stAxis:=Main.M1, nEnableMode:=nEnableMode);
(* State setup - stage 2 *)
fbStage2.stOut.sName := 'Out';
fbStage2.stOut.fPosition := 50;
fbStage2.stOut.fDelta := 100;
fbStage2.stOut.fVelocity := 10;
fbStage2.stOut.bValid := TRUE;
fbStage2.stOut.bMoveOk := TRUE;
fbStage2.stFilter1.sName := 'Filter 1';
fbStage2.stFilter1.fPosition := 500;
fbStage2.stFilter1.fDelta := 0;
fbStage2.stFilter1.fVelocity := 10;
fbStage2.stFilter1.bValid := FALSE;
fbStage2.stFilter1.bMoveOk := FALSE;
fbStage2.stFilter2.sName := 'Filter 2';
fbStage2.stFilter2.fPosition := 500;
fbStage2.stFilter2.fDelta := 0;
fbStage2.stFilter2.fVelocity := 10;
fbStage2.stFilter2.bValid := FALSE;
fbStage2.stFilter2.bMoveOk := FALSE;
fbStage2.stFilter3.sName := 'Filter 3';
fbStage2.stFilter3.fPosition := 500;
fbStage2.stFilter3.fDelta := 0;
fbStage2.stFilter3.fVelocity := 10;
fbStage2.stFilter3.bValid := FALSE;
fbStage2.stFilter3.bMoveOk := FALSE;
fbStage2.stFilter4.sName := 'Filter 4';
fbStage2.stFilter4.fPosition := 500;
fbStage2.stFilter4.fDelta := 0;
fbStage2.stFilter4.fVelocity := 10;
fbStage2.stFilter4.bValid := FALSE;
fbStage2.stFilter4.bMoveOk := FALSE;
fbStage2(stAxis:=Main.M2, nEnableMode:=nEnableMode);
(* State setup - stage 3 *)
fbStage3.stOut.sName := 'Out';
fbStage3.stOut.fPosition := 50;
fbStage3.stOut.fDelta := 100;
fbStage3.stOut.fVelocity := 10;
fbStage3.stOut.bValid := TRUE;
fbStage3.stOut.bMoveOk := TRUE;
fbStage3.stFilter1.sName := 'Filter 1';
fbStage3.stFilter1.fPosition := 500;
fbStage3.stFilter1.fDelta := 0;
fbStage3.stFilter1.fVelocity := 10;
fbStage3.stFilter1.bValid := FALSE;
fbStage3.stFilter1.bMoveOk := FALSE;
fbStage3.stFilter2.sName := 'Filter 2';
fbStage3.stFilter2.fPosition := 500;
fbStage3.stFilter2.fDelta := 0;
fbStage3.stFilter2.fVelocity := 10;
fbStage3.stFilter2.bValid := FALSE;
fbStage3.stFilter2.bMoveOk := FALSE;
fbStage3.stFilter3.sName := 'Filter 3';
fbStage3.stFilter3.fPosition := 500;
fbStage3.stFilter3.fDelta := 0;
fbStage3.stFilter3.fVelocity := 10;
fbStage3.stFilter3.bValid := FALSE;
fbStage3.stFilter3.bMoveOk := FALSE;
fbStage3.stFilter4.sName := 'Filter 4';
fbStage3.stFilter4.fPosition := 500;
fbStage3.stFilter4.fDelta := 0;
fbStage3.stFilter4.fVelocity := 10;
fbStage3.stFilter4.bValid := FALSE;
fbStage3.stFilter4.bMoveOk := FALSE;
fbStage3(stAxis:=Main.M3, nEnableMode:=nEnableMode);
(* State setup - stage 4 *)
fbStage4.stOut.sName := 'Out';
fbStage4.stOut.fPosition := 50;
fbStage4.stOut.fDelta := 100;
fbStage4.stOut.fVelocity := 10;
fbStage4.stOut.bValid := TRUE;
fbStage4.stOut.bMoveOk := TRUE;
fbStage4.stFilter1.sName := 'Filter 1';
fbStage4.stFilter1.fPosition := 500;
fbStage4.stFilter1.fDelta := 0;
fbStage4.stFilter1.fVelocity := 10;
fbStage4.stFilter1.bValid := FALSE;
fbStage4.stFilter1.bMoveOk := FALSE;
fbStage4.stFilter2.sName := 'Filter 2';
fbStage4.stFilter2.fPosition := 500;
fbStage4.stFilter2.fDelta := 0;
fbStage4.stFilter2.fVelocity := 10;
fbStage4.stFilter2.bValid := FALSE;
fbStage4.stFilter2.bMoveOk := FALSE;
fbStage4.stFilter3.sName := 'Filter 3';
fbStage4.stFilter3.fPosition := 500;
fbStage4.stFilter3.fDelta := 0;
fbStage4.stFilter3.fVelocity := 10;
fbStage4.stFilter3.bValid := FALSE;
fbStage4.stFilter3.bMoveOk := FALSE;
fbStage4.stFilter4.sName := 'Filter 4';
fbStage4.stFilter4.fPosition := 500;
fbStage4.stFilter4.fDelta := 0;
fbStage4.stFilter4.fVelocity := 10;
fbStage4.stFilter4.bValid := FALSE;
fbStage4.stFilter4.bMoveOk := FALSE;
fbStage4(stAxis:=Main.M4, nEnableMode:=nEnableMode);
END_PROGRAM
- Related: