DUTs ---- DUT_MotionStage_Extras ^^^^^^^^^^^^^^^^^^^^^^ :: TYPE DUT_MotionStage_Extras : STRUCT fVisuStep: LREAL; bVisuLowLim: BOOL; bVisuHighLim: BOOL; END_STRUCT END_TYPE Related: * `DUT_MotionStage_Extras`_ 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: * `ENUM_SXR_SATT_Position`_ 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 Related: * `DUT_MotionStage_Extras`_ * `FB_SXR_SATT_PositionState`_ PRG_1_PlcTask ^^^^^^^^^^^^^ :: PROGRAM PRG_1_PlcTask VAR fbLogHandler: FB_LogHandler; END_VAR fbLogHandler(); PRG_2_AT1K4(); END_PROGRAM Related: * `PRG_2_AT1K4`_ 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: * `FB_SXR_SATT_Stage`_ * `Main`_