DUTs

E_HomeState

TYPE E_HomeState :
(
    H_READY,
    H_INIT,
    H_RESET_LL,
    H_RESET_HL,
    H_ENABLE,
    H_MOVING,
    H_KEEP_MOVING,
    H_CHECK,
    H_RESET,
    H_SET_POS,
    H_ERROR,
    H_WRITE_LL,
    H_WRITE_HL,
    H_DONE

) UDINT;
END_TYPE
Related:

ENUM_Si_B4C_Coating_States

{attribute 'qualified only'}
TYPE ENUM_Si_B4C_Coating_States :
(
    Unknown := 0,
    Si := 1,
    B4C := 2
);
END_TYPE

GVLs

GVL_COM_Buffers

VAR_GLOBAL
    // M1K4
    Serial_RXBuffer_M1K4 : ComBuffer;
    Serial_TXBuffer_M1K4 : ComBuffer;
END_VAR

GVL_M1K4

{attribute 'qualified_only'}
VAR_GLOBAL
    // Pitch Mechanism:
    {attribute 'TcLinkTo' := '.diEncCnt:=TIIB[EL5042_M1K4_PitchBender]^FB Inputs Channel 1^Position'}
    M1K4_Pitch : HOMS_PitchMechanism := (ReqPosLimHi := 275,
                                         ReqPosLimLo := -25,
                                         diEncPosLimHi := 10149192,
                                         diEncPosLimLo := 10047105);

END_VAR

GVL_M1K4_Constants

{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
    // Encoder reference values in counts = nm
    nYUP_ENC_REF : ULINT := 15000270;
    nYDWN_ENC_REF : ULINT := 15454300;
    nXUP_ENC_REF : ULINT := 24000300;
    nXDWN_ENC_REF : ULINT := 23999400;
END_VAR

GVL_M2K4_Constants

{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
    // Encoder reference values in counts = nm
    nM2K4X_ENC_REF : ULINT := 5973570;
    nM2K4Y_ENC_REF : ULINT := 6099450;
    nM2K4rY_ENC_REF : ULINT := 39050722;
END_VAR

GVL_M2K4_RTD

{attribute 'qualified_only'}
VAR_GLOBAL
    // M2K4 BENDER RTDs

    // M2K4 US RTDs
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 1^Value'}
    nM2K4US_RTD_1 AT %I* : INT;
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M2K4US3_M2K4DS1]^RTD Inputs Channel 1^Value'}
    nM2K4US_RTD_3 AT %I* : INT;

    // M2K4 DS RTDs
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M2K4US3_M2K4DS1]^RTD Inputs Channel 2^Value'}
    nM2K4DS_RTD_1 AT %I* : INT;
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 2^Value'}
    nM2K4DS_RTD_3 AT %I* : INT;
END_VAR

GVL_M3K4_Constants

{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
    // Encoder reference values in counts = nm
    nM3K4X_ENC_REF : ULINT := 6404509;
    nM3K4Y_ENC_REF : ULINT := 6047240;
    nM3K4rX_ENC_REF : ULINT := 48388188;
END_VAR

GVL_M3K4_RTD

{attribute 'qualified_only'}
VAR_GLOBAL
    // M3K4 BENDER RTDs

    // M3K4 US RTDs
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 1^Value'}
    nM3K4US_RTD_1 AT %I* : INT;

    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M3K4US3_M3K4DS1]^RTD Inputs Channel 1^Value'}
    nM3K4US_RTD_3 AT %I* : INT;

    // M2K4 DS RTDs
    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M3K4US3_M3K4DS1]^RTD Inputs Channel 2^Value'}
    nM3K4DS_RTD_1 AT %I* : INT;

    {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 2^Value'}
    nM3K4DS_RTD_3 AT %I* : INT;


END_VAR

GVL_M4K4_RTD

{attribute 'qualified_only'}
VAR_GLOBAL
    // M4K4 RTDs
    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M4K4]^RTD Inputs Channel 1^Value;
                              .bUnderrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 1^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 1^Status^Overrange;
                              .bError := TIIB[EL3204_M4K4]^RTD Inputs Channel 1^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR4K4:KBO:RTD:CHIN:L
        field: EGU C
        io: i
    '}
    nM4K4_Chin_Left_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M4K4]^RTD Inputs Channel 2^Value;
                              .bUnderrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 2^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 2^Status^Overrange;
                              .bError := TIIB[EL3204_M4K4]^RTD Inputs Channel 2^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR4K4:KBO:RTD:CHIN:R
        field: EGU C
        io: i
    '}
    nM4K4_Chin_Right_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M4K4]^RTD Inputs Channel 3^Value;
                              .bUnderrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 3^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M4K4]^RTD Inputs Channel 3^Status^Overrange;
                              .bError := TIIB[EL3204_M4K4]^RTD Inputs Channel 3^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR4K4:KBO:RTD:TAIL
        field: EGU C
        io: i
    '}
    nM4K4_Chin_Tail_RTD : FB_TempSensor;
END_VAR

GVL_M5K4_RTD

{attribute 'qualified_only'}
VAR_GLOBAL
    // M5K4 RTDs
    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M5K4]^RTD Inputs Channel 1^Value;
                              .bUnderrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 1^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 1^Status^Overrange;
                              .bError := TIIB[EL3204_M5K4]^RTD Inputs Channel 1^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR5K4:KBO:RTD:CHIN:L
        field: EGU C
        io: i
    '}
    nM5K4_Chin_Left_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M5K4]^RTD Inputs Channel 2^Value;
                              .bUnderrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 2^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 2^Status^Overrange;
                              .bError := TIIB[EL3204_M5K4]^RTD Inputs Channel 2^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR5K4:KBO:RTD:CHIN:R
        field: EGU C
        io: i
    '}
    nM5K4_Chin_Right_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3204_M5K4]^RTD Inputs Channel 3^Value;
                              .bUnderrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 3^Status^Underrange;
                              .bOverrange := TIIB[EL3204_M5K4]^RTD Inputs Channel 3^Status^Overrange;
                              .bError := TIIB[EL3204_M5K4]^RTD Inputs Channel 3^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR5K4:KBO:RTD:TAIL
        field: EGU C
        io: i
    '}
    nM5K4_Chin_Tail_RTD : FB_TempSensor;
END_VAR

GVL_PMPS

{attribute 'qualified_only'}
VAR_GLOBAL
    // FFO for devices upstream of ST1K4 (M1K4)
    {attribute 'pytmc' := '
        pv: PLC:TMO:OPTICS:FFO:01
    '}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 1^Output'}
    g_FastFaultOutput1 : FB_HardwareFFOutput := (bAutoReset:=TRUE, i_sNetID:='172.21.92.73.1.1');
    // FFO for devices downstream of ST1K4 (TMO hutch optics)
    {attribute 'pytmc' := '
        pv: PLC:TMO:OPTICS:FFO:02
    '}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 2^Output'}
    g_FastFaultOutput2 : FB_HardwareFFOutput := (bAutoReset:=TRUE, i_sNetID:='172.21.92.73.1.1');

    // Arbiter for devices upstream of ST1K4 (M1K4)
    {attribute 'pytmc' := '
        pv: PLC:TMO:OPTICS:ARB:01
    '}
    g_fbArbiter1 : FB_Arbiter(1);
    // Arbiter for devices downstream of ST1K4 (TMO hutch optics)
    {attribute 'pytmc' := '
        pv: PLC:TMO:OPTICS:ARB:02
    '}
    g_fbArbiter2 : FB_Arbiter(2);
END_VAR

GVL_SerialIO

VAR_GLOBAL
    //Better have your inputs and outputs!
    // M1K4
    Serial_stComIn_M1K4   AT %I*    :       EL6inData22B (*KL6inData22B*);
    Serial_stComOut_M1K4  AT %Q*    :       EL6outData22B (*KL6outData22B*);
END_VAR

POUs

FB_KBO_Coating_States

FUNCTION_BLOCK FB_KBO_Coating_States EXTENDS FB_PositionStateBase_WithPMPS
VAR_INPUT
    {attribute 'pytmc' := '
      pv: SET
      io: io
    '}
    enumSet : ENUM_Si_B4C_Coating_States;

    stCoating1 : DUT_PositionState;
    stCoating2 : DUT_PositionState;

    bVerticalCoating : BOOL := TRUE;

    sCoating1Name : STRING;
    sCoating2Name : STRING;

END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
      pv: GET;
      io: i;
    '}
    enumGet : ENUM_Si_B4C_Coating_States;
  END_VAR
VAR
    fbStateDefaults: FB_PositionState_Defaults;
    bCoatingInit : BOOL;
    fCoatingAccel : LREAL := fYAccel;
    fCoatingDecel : LREAL := fYDecel;

END_VAR
VAR CONSTANT
    // These are the default values
    // Set values on states prior to passing in for non-default values
    // Units in Millimeters
    fDelta: LREAL := 0.1;
    fVelocity: LREAL := 0.150;
    fYAccel: LREAL := 10;
    fYDecel: LREAL := 10;
    fXAccel: LREAL := 100;
    fXDecel: LREAL := 100;
END_VAR
if NOT bCoatingInit THEN
    bCoatingInit := TRUE;
    if NOT bVerticalCoating THEN
        fCoatingAccel := fXAccel;
        fCoatingDecel := fXDecel;
    END_IF

    //Coating 1
    stCoating1.sName := sCoating1Name;
    stCoating1.bValid := TRUE;
    stCoating1.bMoveOk := TRUE;
    stCoating1.bUseRawCounts := TRUE;
    fbStateDefaults(
        stPositionState:=stCoating1,
        fVeloDefault:=fVelocity,
        fDeltaDefault:=fDelta,
        fAccelDefault:=fCoatingAccel,
        fDecelDefault:=fCoatingDecel
    );

    //Coating 2
    stCoating2.sName := sCoating2Name;
    stCoating2.bValid := TRUE;
    stCoating2.bMoveOk := TRUE;
    stCoating2.bUseRawCounts := TRUE;
    fbStateDefaults(
        stPositionState:=stCoating2,
        fVeloDefault:=fVelocity,
        fDeltaDefault:=fDelta,
        fAccelDefault:=fCoatingAccel,
        fDecelDefault:=fCoatingDecel
    );

    arrStates[1] := stCoating1;
    arrStates[2] := stCoating2;
END_IF

setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK
Related:

FB_Offset_Coating_States

FUNCTION_BLOCK FB_Offset_Coating_States EXTENDS FB_PositionStateBase_WithPMPS
VAR_INPUT
    {attribute 'pytmc' := '
      pv: SET
      io: io
    '}
    enumSet : ENUM_Si_B4C_Coating_States;

    stCoating1 : DUT_PositionState;
    stCoating2 : DUT_PositionState;

    sCoating1Name : STRING;
    sCoating2Name : STRING;

END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
      pv: GET;
      io: i;
    '}
    enumGet : ENUM_Si_B4C_Coating_States;
  END_VAR
VAR
    fbStateDefaults: FB_PositionState_Defaults;
    bCoatingInit : BOOL;
END_VAR
VAR CONSTANT
    // These are the default values
    // Set values on states prior to passing in for non-default values
    // Units in Mircons
    fDelta: LREAL := 100;
    fVelocity: LREAL := 150;
    fAccel: LREAL := 200;
    fDecel: LREAL := 200;
END_VAR
if NOT bCoatingInit THEN
    bCoatingInit := TRUE;

    //Coating 1
    stCoating1.sName := sCoating1Name;
    stCoating1.bValid := TRUE;
    stCoating1.bMoveOk := TRUE;
    stCoating1.bUseRawCounts := TRUE;
    fbStateDefaults(
        stPositionState:=stCoating1,
        fVeloDefault:=fVelocity,
        fDeltaDefault:=fDelta,
        fAccelDefault:=fAccel,
        fDecelDefault:=fDecel
    );

    //Coating 2
    stCoating2.sName := sCoating2Name;
    stCoating2.bValid := TRUE;
    stCoating2.bMoveOk := TRUE;
    stCoating2.bUseRawCounts := TRUE;
    fbStateDefaults(
        stPositionState:=stCoating2,
        fVeloDefault:=fVelocity,
        fDeltaDefault:=fDelta,
        fAccelDefault:=fAccel,
        fDecelDefault:=fDecel
    );

    arrStates[1] := stCoating1;
    arrStates[2] := stCoating2;
END_IF

setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK
Related:

FB_SLITS

FUNCTION_BLOCK FB_SLITS
VAR_IN_OUT
    stTopBlade: ST_MotionStage;
    stBottomBlade: ST_MotionStage;
    stNorthBlade: ST_MotionStage;
    stSouthBlade: ST_MotionStage;
    bExecuteMotion:BOOL ;
    io_fbFFHWO    :    FB_HardwareFFOutput;
    fbArbiter: FB_Arbiter();
END_VAR

VAR_INPUT

    {attribute 'pytmc' := '
    pv: PMPS_OK;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bMoveOk:BOOL := TRUE;

        (*Offsets*)
    {attribute 'pytmc' := '
    pv: Offset_Top;
    io: io;
    '}
    rEncoderOffsetTop: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_Bottom;
    io: io;
    '}
    rEncoderOffsetBottom: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_North;
    io: io;
    '}
    rEncoderOffsetNorth: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_South;
    io: io;
    '}
    rEncoderOffsetSouth: REAL;
    i_DevName : STRING; //device name for FFO and PMPS diagnostics
     {attribute 'pytmc' := '
    pv: Home;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bHome:BOOL:=FALSE;
END_VAR

VAR
    fbTopBlade: FB_MotionStage;
    fbBottomBlade: FB_MotionStage;
    fbNorthBlade: FB_MotionStage;
    fbSouthBlade: FB_MotionStage;
    fPosTopBlade: LREAL;
    fPosBottomBlade: LREAL;
    fPosNorthBlade: LREAL;
    fPosSouthBlade: LREAL;

    (*Motion Parameters*)
    fSmallDelta: LREAL := 0.01;
    fBigDelta: LREAL := 10;
    fMaxVelocity: LREAL := 0.2;
    fHighAccel: LREAL := 0.8;
    fLowAccel: LREAL := 0.1;

    stTop: DUT_PositionState;
    stBOTTOM: DUT_PositionState;
    stNorth: DUT_PositionState;
    stSouth: DUT_PositionState;

    {attribute 'pytmc' := 'pv: TOP'}
    fbTop: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: BOTTOM'}
    fbBottom: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: NORTH'}
    fbNorth: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: SOUTH'}
    fbSouth: FB_StatePTPMove;

    (*EPICS pvs*)
    {attribute 'pytmc' := '
    pv: XWID_REQ;
    io: io;
    '}
    rReqApertureSizeX : REAL;
    {attribute 'pytmc' := '
    pv: YWID_REQ;
    io: io;
    '}
    rReqApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: XCEN_REQ;
    io: io;
    '}
    rReqCenterX: REAL;
    {attribute 'pytmc' := '
    pv: YCEN_REQ;
    io: io;
    '}
    rReqCenterY: REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_XWIDTH;
    io: io;
    '}
    rActApertureSizeX : REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_YWIDTH;
    io: io;
    '}
    rActApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_XCENTER;
    io: io;
    '}
    rActCenterX: REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_YCENTER;
    io: io;
    '}
    rActCenterY: REAL;

    {attribute 'pytmc' := '
    pv: XCEN_SETZERO;
    io: io;
    '}
    rSetCenterX: BOOL;
    {attribute 'pytmc' := '
    pv: YCEN_SETZERO;
    io: io;
    '}
    rSetCenterY: BOOL;


    {attribute 'pytmc' := '
    pv: OPEN;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bOpen: BOOL;

    {attribute 'pytmc' := '
    pv: CLOSE;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bClose: BOOL;

    {attribute 'pytmc' := '
    pv: BLOCK;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bBlock: BOOL;


     {attribute 'pytmc' := '
    pv: HOME_READY;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bHomeReady:BOOL:=FALSE;


        //Local variables
    bInit: BOOL :=true;
    rTrig_Block: R_TRIG;
    rTrig_Open: R_TRIG;
    rTrig_Close: R_TRIG;

    //old values
    rOldReqApertureSizeX : REAL;
    rOldReqApertureSizeY : REAL;
    rOldReqCenterX: REAL;
    rOldReqCenterY: REAL;

    bExecuteMotionX: BOOL;
    bExecuteMotionY: BOOL;


    fPosBlock: LREAL;
    fPosClose: LREAL;
    fPosOpen: LREAL;

    stSetPositionOptions:ST_SetPositionOptions;
    fbSetPosition_TOP: MC_SetPosition;
    fbSetPosition_Bottom: MC_SetPosition;
    fbSetPosition_North: MC_SetPosition;
    fbSetPosition_South: MC_SetPosition;

    // For logging
    fbLogger : FB_LogMessage := (eSubsystem:=E_SubSystem.MOTION);
    tErrorPresent : R_TRIG;
    tAction : R_TRIG;
    tOverrideActivated : R_TRIG;

    FFO    :    FB_FastFault :=(
        i_DevName := 'Slits',
        i_Desc := 'Fault occurs when center is greated than that requested',
        i_TypeCode := 16#1010);


    bTest: BOOL;

    AptArrayStatus AT %Q* : ST_PMPS_Aperture_IO;
    AptArrayReq AT %I* : ST_PMPS_Aperture_IO;

    rApertureOffsetX        : REAL :=  5;
    rApertureOffsetY        : REAL :=  5;
    rCenterOffsetX  : REAL := -1;
    rCenterOffsetY  : REAL := -1;
END_VAR
ACT_init();

// Instantiate Function block for all the blades
ACT_Motion();
//SET and GET the requested and Actual values
ACT_CalculatePositions();
//ACT_BLOCK();

END_FUNCTION_BLOCK

ACTION ACT_BLOCK:
rTrig_Block (CLK:= bBlock);
rTrig_Open (CLK:= bOpen);
rTrig_Close (CLK:= bClose);

if (rTrig_Block.Q) THEN
    //BLOCK

    bBlock := false;
END_IF

if (rTrig_Open.Q) THEN


    bOpen := false;
END_IF

if (rTrig_Close.Q) THEN


    bClose := false;
END_IF
END_ACTION

ACTION ACT_CalculatePositions:
//check if requested center or gap has changed
//check that the requested values are within acceptable motion range
IF (rOldReqApertureSizeX <> rReqApertureSizeX) THEN
        rOldReqApertureSizeX := rReqApertureSizeX;
        bExecuteMotionX := TRUE;
        fbLogger(sMsg:='Requested new X gap.', eSevr:=TcEventSeverity.Verbose);
END_IF

IF (rOldReqCenterX <> rReqCenterX) THEN
    rOldReqCenterX := rReqCenterX;
    bExecuteMotionX := TRUE;
    fbLogger(sMsg:='Requested new X center', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterX := rActCenterX;
END_IF

IF (rOldReqApertureSizeY <> rReqApertureSizeY) THEN
        rOldReqApertureSizeY := rReqApertureSizeY;
        bExecuteMotionY := TRUE;
        fbLogger(sMsg:='Requested new Y gap.', eSevr:=TcEventSeverity.Verbose);

END_IF

IF (rOldReqCenterY <> rReqCenterY) THEN
    rOldReqCenterY := rReqCenterY;
    bExecuteMotionY := TRUE;
    fbLogger(sMsg:='Requested new Y center.', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterY := rActCenterY;
END_IF


//Calculate requested target positions from requested gap and center
fPosTopBlade := ((rReqApertureSizeY-rApertureOffsetY)/2) + ((rReqCenterY-rCenterOffsetY) + rEncoderOffsetTop) ;
fPosBottomBlade := (-1*(rReqApertureSizeY-rApertureOffsetY)/2) + ((rReqCenterY-rCenterOffsetY)+rEncoderOffsetBottom);

fPosNorthBlade := ((rReqApertureSizeX-rApertureOffsetX)/2) + ((rReqCenterX-rCenterOffsetX) + rEncoderOffsetNorth);
fPosSouthBlade := (-1*(rReqApertureSizeX-rApertureOffsetX)/2) + ((rReqCenterX-rCenterOffsetX) + rEncoderOffsetSouth);


//Calculate actual gap and center from actual stages positions
rActApertureSizeX := rApertureOffsetX + LREAL_TO_REAL((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth) - (stSouthBlade.stAxisStatus.fActPosition- rEncoderOffsetSouth));

rActApertureSizeY := rApertureOffsetY + LREAL_TO_REAL((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) - (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom));

rActCenterX := rCenterOffsetX + LREAL_TO_REAL((((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth)  + (stSouthBlade.stAxisStatus.fActPosition - rEncoderOffsetSouth ))/2));

rActCenterY := rCenterOffsetY + LREAL_TO_REAL((((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) + (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom))/2));



//Update PMPS Arbiter with the Actual Size and Center of the Aperture
END_ACTION

ACTION ACT_Home:

END_ACTION

ACTION ACT_Init:
//  init the motion stages parameters
IF ( bInit) THEN
    stTopBlade.bHardwareEnable := TRUE;
    stBottomBlade.bHardwareEnable := TRUE;
    stNorthBlade.bHardwareEnable := TRUE;
    stSouthBlade.bHardwareEnable := TRUE;
    stTopBlade.bPowerSelf :=TRUE;
    stBottomBlade.bPowerSelf :=TRUE;
    stNorthBlade.bPowerSelf :=TRUE;
    stSouthBlade.bPowerSelf :=TRUE;
    stTopBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stBottomBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stNorthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stSouthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    FFO.i_DevName := i_DevName;
END_IF
END_ACTION

ACTION ACT_Motion:
// Instantiate Function block for all the blades
fbTopBlade(stMotionStage:=stTopBlade);
fbBottomBlade(stMotionStage:=stBottomBlade);
fbNorthBlade(stMotionStage:=stNorthBlade);
fbSouthBlade(stMotionStage:=stSouthBlade);

// PTP Motion for each blade
stTop.sName := 'Top';
stTop.fPosition := fPosTopBlade;
stTop.fDelta := fSmallDelta;
stTop.fVelocity := fMaxVelocity;
stTop.fAccel := fHighAccel;
stTop.fDecel := fHighAccel;

stBOTTOM.sName := 'Bottom';
stBOTTOM.fPosition := fPosBottomBlade;
stBOTTOM.fDelta := fSmallDelta;
stBOTTOM.fVelocity := fMaxVelocity;
stBOTTOM.fAccel := fHighAccel;
stBOTTOM.fDecel := fHighAccel;

stNorth.sName := 'North';
stNorth.fPosition := fPosNorthBlade;
stNorth.fDelta := fSmallDelta;
stNorth.fVelocity := fMaxVelocity;
stNorth.fAccel := fHighAccel;
stNorth.fDecel := fHighAccel;

stSouth.sName := 'South';
stSouth.fPosition := fPosSouthBlade;
stSouth.fDelta := fSmallDelta;
stSouth.fVelocity := fMaxVelocity;
stSouth.fAccel := fHighAccel;
stSouth.fDecel := fHighAccel;

IF (bExecuteMotionY) THEN
    fbTop.bExecute := fbBottom.bExecute := bExecuteMotionY;
    bExecuteMotionY:= FALSE;
END_IF

IF (bExecuteMotionX) THEN
    fbNorth.bExecute := fbSouth.bExecute := bExecuteMotionX;
    bExecuteMotionX:= FALSE;
END_IF


fbTop(
    stPositionState:=stTop,
    bMoveOk:=bMoveOk,
    stMotionStage:=stTopBlade);

fbBottom(
    stPositionState:=stBOTTOM,
    bMoveOk:=bMoveOk,
    stMotionStage:=stBottomBlade);

fbNorth(
    stPositionState:=stNorth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stNorthBlade);

fbSouth(
    stPositionState:=stSouth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stSouthBlade);
END_ACTION

ACTION ACT_Zero:
//ZERO BIAS

// Set Y center to zero

// Set X center to zero
(*
if (rSetCenterY)THEN
        rSetCenterY := false;
        // Set Current Position
        fbSetPosition_TOP.Position :=  stTopBlade.stAxisStatus.fActPosition - rActCenterY ;
        fbSetPosition_TOP.Execute := TRUE;
        fbSetPosition_Bottom.Position := stBottomBlade.stAxisStatus.fActPosition - rActCenterY;
        fbSetPosition_Bottom.Execute := TRUE;
END_IF

if (rSetCenterX)THEN
        rSetCenterX := false;
        // Set Current Position
        fbSetPosition_North.Position := stNorthBlade.stAxisStatus.fActPosition - rActCenterX ;
        fbSetPosition_North.Execute := TRUE;
        fbSetPosition_South.Position := stSouthBlade.stAxisStatus.fActPosition - rActCenterX ; ;
        fbSetPosition_South.Execute := TRUE;
END_IF


//Reset
if (fbSetPosition_TOP.Done ) THEN
    fbSetPosition_TOP.Execute := FALSE;
END_IF
if (fbSetPosition_Bottom.Done ) THEN
    fbSetPosition_Bottom.Execute := FALSE;
END_IF
if (fbSetPosition_North.Done ) THEN
    fbSetPosition_North.Execute := FALSE;
END_IF
if (fbSetPosition_South.Done ) THEN
    fbSetPosition_South.Execute := FALSE;
END_IF

// Set Encoder Position
//Clear position lag error
stSetPositionOptions.ClearPositionLag := TRUE;
fbSetPosition_TOP(
    Axis:=  stTopBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_Bottom(
    Axis:= stBottomBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_North(
    Axis:= stNorthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_South(
    Axis:= stSouthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

    *)
END_ACTION

METHOD M_CheckPMPS : BOOL
VAR_INPUT
     index: int;
END_VAR
(*
IF(rActApertureSizeX < (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Width)+0.001)
    OR (rActApertureSizeY < (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Height)+0.001) THEN
        FFO.i_xOK := FALSE;
    ELSE
        FFO.i_xOK := TRUE;
END_IF

(*FAST FAULT*)
FFO(i_xOK := ,
    i_xReset := ,
    i_xAutoReset :=TRUE,
    io_fbFFHWO := this^.io_fbFFHWO);
*)
END_METHOD

METHOD M_HomeBlade : BOOL
VAR_IN_OUT
      stBlade: ST_MotionStage;
END_VAR
VAR
    fPosBlade: LREAL;
    HomeState: E_HomeState;
    rHomingDistance: REAL:=0.2;
    rHomingVelocity: REAL:=0.1;
    Axis: AXIS_REF;
    fbSetPosition: MC_SetPosition;
    fbWriteParameter: MC_WriteBoolParameter;
END_VAR
CASE HomeState OF
    H_READY:
        fbWriteParameter.Execute := FALSE;
        IF (bHome) THEN
            HomeState := H_INIT;
            bHomeReady := FALSE;
        END_IF


    H_INIT:
    HomeState:=H_RESET_LL;


    H_RESET_LL:
        // disable soft limits in order to be able to move the drive
        fbWriteParameter.ParameterNumber := MC_AxisParameter.EnableLimitNeg;
        fbWriteParameter.Value := FALSE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_RESET_HL;
        END_IF

    H_RESET_HL:
        // disable soft limits in order to be able to move the drive
        fbWriteParameter.ParameterNumber := MC_AxisParameter.EnableLimitPos;
        fbWriteParameter.Value := FALSE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_ENABLE;
        END_IF

    H_ENABLE:
        // Make Sure there are no errors
        IF stBlade.bError THEN
            HomeState := H_ERROR;
            ELSE
             stBlade.fPosition := stBlade.fPosition - rHomingDistance;
             HomeState:= H_MOVING;
        END_IF



    H_MOVING:
        stBlade.bExecute :=TRUE;
        IF stBlade.bBusy  THEN
            (* axis is executing job but is not yet finished *)
            stBlade.bExecute:= FALSE;
            (* leave this state and buffer a second command *)
            HomeState := H_KEEP_MOVING;
        ElSIF stBlade.bDone THEN
            stBlade.bExecute:= FALSE;
            stBlade.fPosition := stBlade.fPosition - rHomingDistance;
            HomeState := H_KEEP_MOVING;
        ELSIF stBlade.bError THEN
            stBlade.bExecute:= FALSE;
            HomeState := H_CHECK;
        END_IF

    H_KEEP_MOVING:
        IF stBlade.bError THEN
            HomeState := H_CHECK;
        END_IF
        IF  stBlade.bDone THEN
            HomeState := H_MOVING;
            stBlade.fPosition := stBlade.fPosition + rHomingDistance;
            stBlade.bExecute  := TRUE;
        END_IF

    H_CHECK:
        //Check the mpositive limit switch is reached or erro losing positive limit
        IF (stBlade.bError) AND NOT (stBlade.bLimitForwardEnable) THEN
            HomeState := H_RESET;
            stBlade.bReset := TRUE;
        ELSE
            HomeState := H_ERROR;
        END_IF

    H_RESET:
        IF NOT(stBlade.bError) THEN
            HomeState := H_SET_POS;
        END_IF

    H_SET_POS:
     // Set Current Position
        fbSetPosition.Position := 0;
        fbSetPosition.Execute := TRUE;
        IF ( fbSetPosition.Done ) THEN
            fbSetPosition.Execute := FALSE;
            HomeState:= H_WRITE_LL;
        ELSIF (fbSetPosition.Error) THEN
            HomeState := H_ERROR;
        END_IF


    H_WRITE_LL:
    // Re Enable the Soft limits
        fbWriteParameter.ParameterNumber := MC_AxisParameter.AxisEnMinSoftPosLimit;//AxisEnMaxSoftPosLimit;// .AxisEnMinSoftPosLimit;
        fbWriteParameter.Value := TRUE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_WRITE_HL;
        END_IF

    H_WRITE_HL:
    // Re Enable the Soft limits
        fbWriteParameter.ParameterNumber := MC_AxisParameter.AxisEnMaxSoftPosLimit;
        fbWriteParameter.Value := TRUE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_DONE;
        END_IF


    H_ERROR:
        //What to do?  User reset through epics??
        IF NOT (stBlade.bError) (*AND (bHome)*) THEN
            HomeState := H_INIT;
        END_IF

    H_DONE:
        HomeState := H_INIT;
        bHomeReady := TRUE;

END_CASE



// Set Encoder Position
fbSetPosition(
    Axis:= stBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE, //Absolute
    Options:= ,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

// Write Parameters
fbWriteParameter(
    Axis:= stBlade.Axis ,
    Execute:= ,
    ParameterNumber:= ,
    Value:= ,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

If ( fbWriteParameter.Error) OR (fbSetPosition.Error) THEN
    HomeState:= H_ERROR;
END_IF
END_METHOD

METHOD M_UpdatePMPS : BOOL
VAR_INPUT
    index: int;
END_VAR
(*
//Keep updating the status of the apertures PMPS
This^.AptArrayStatus.Height := This^.rActApertureSizeY;
This^.AptArrayStatus.Width := This^.rActApertureSizeX;
This^.AptArrayStatus.xOK := NOT (This^.stTopBlade.bError) AND NOT (This^.stBottomBlade.bError)
                                 AND NOT (This^.stNorthBlade.bError) AND NOT (This^.stNorthBlade.bError);

//Evaluate that the current center on the X and the y direction didn't exceed limits
//Fast fault when it does.
IF(rActCenterX > (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Width/2))
    OR (rActCenterY > (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Height/2)) THEN
        FFO.i_xOK := FALSE;
    ELSE
        FFO.i_xOK := TRUE;
END_IF

//Evaluate that the requested gaps on the X and the y direction is not larger than the current gap
// narrow  the gap if the requested is larger
IF(bTest) THEN
    IF (This^.rActApertureSizeX > AptArrayReq.Width) THEN
        rReqApertureSizeX := AptArrayReq.Width;
    END_IF
    IF (This^.rActApertureSizeY > AptArrayReq.Height) THEN
         rReqApertureSizeY := AptArrayReq.Height;
    END_IF
END_IF


(*FAST FAULT*)
FFO(i_xOK := ,
    i_xReset := ,
    i_xAutoReset :=TRUE,
    io_fbFFHWO := io_fbFFHWO);
*)
END_METHOD
Related:

Main

PROGRAM Main
VAR
// M1K4
    // Motors
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_Yup]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_Yup]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:YUP
        '}
        //PMPS State Stage; bPowerSelf:=False
        M1 : ST_MotionStage := (sName:='MR1K4-Coatings', fVelocity:=200.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=FALSE); // M1K4 Yup
        fbMotionStage_m1 : FB_MotionStage;

        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_Ydwn]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_Ydwn]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:YDWN
        '}
        M2 : ST_MotionStage := (fVelocity:=200.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE); // M1K4 Ydwn
        fbMotionStage_m2 : FB_MotionStage;

        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_Xup]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_Xup]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:XUP
        '}
        M3 : ST_MotionStage := (fVelocity:=1000.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE); // M1K4 Xup
        fbMotionStage_m3 : FB_MotionStage;

        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_Xdwn]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_Xdwn]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:XDWN
        '}
        M4 : ST_MotionStage := (fVelocity:=1000.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE); // M1K4 Xdwn
        fbMotionStage_m4 : FB_MotionStage;

        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_PitchCoarse]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_PitchCoarse]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:PITCH
        '}
        M5 : ST_MotionStage := (fVelocity := 150.0, bPowerSelf:=TRUE, nEnableMode:=ENUM_StageEnableMode.ALWAYS); // M1K4 Pitch Stepper
        fbMotionStage_m5 : FB_MotionStage;

(*        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-1000_M1K4_Bender]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-1000_M1K4_Bender]^STM Status^Status^Digital input 2'}
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:MMS:BENDER
        '}
        M6 : ST_MotionStage := (fVelocity := 150.0, bPowerSelf:=TRUE); // M1K4 Bender
        fbMotionStage_m6 : FB_MotionStage;
*)

    {attribute 'TcLinkTo' := '.fbRunHOMS.bSTOEnable1:=TIIB[EL1004_M1K4_STO]^Channel 1^Input;
                              .fbRunHOMS.bSTOEnable2:=TIIB[EL1004_M1K4_STO]^Channel 2^Input;
                              .fbRunHOMS.stYupEnc.Count:=TIIB[EL5042_M1K4_Yupdwn]^FB Inputs Channel 1^Position;
                              .fbRunHOMS.stYdwnEnc.Count:=TIIB[EL5042_M1K4_Yupdwn]^FB Inputs Channel 2^Position;
                              .fbRunHOMS.stXupEnc.Count:=TIIB[EL5042_M1K4_Xupdwn]^FB Inputs Channel 1^Position;
                              .fbRunHOMS.stXdwnEnc.Count:=TIIB[EL5042_M1K4_Xupdwn]^FB Inputs Channel 2^Position'}
    {attribute 'pytmc' := '
        pv: MR1K4:SOMS
    '}
    M1K4 : DUT_HOMS;

    // Encoder Arrays/RMS Watch:
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:Y
        '}
        fbYRMSErrorM1K4 : FB_RMSWatch;
        fMaxYRMSErrorM1K4 : LREAL;
        fMinYRMSErrorM1K4 : LREAL;

        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:X
        '}
        fbXRMSErrorM1K4 : FB_RMSWatch;
        fMaxXRMSErrorM1K4 : LREAL;
        fMinXRMSErrorM1K4 : LREAL;

        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:PITCH
        '}
        fbPitchRMSErrorM1K4 : FB_RMSWatch;
        fMaxPitchRMSErrorM1K4 : LREAL;
        fMinPitchRMSErrorM1K4 : LREAL;

        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:BENDER
        '}
        fbBenderRMSErrorM1K4 : FB_RMSWatch;
        fMaxBenderRMSErrorM1K4 : LREAL;
        fMinBenderRMSErrorM1K4 : LREAL;

    // Piezo Pitch Control
        //fbM1K4PitchControl : FB_PitchControl;
        //bM1K4PitchDone : BOOL;
        //bM1K4PitchBusy : BOOL;

    // Bender Control
        fbBenderM1K4 : FB_Bender;

    // Raw Encoder Counts
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:YUP:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntYupM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:YDWN:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntYdwnM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:XUP:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntXupM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:XDWN:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntXdwnM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:PITCH:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntPitchM1K4 : UDINT;

    // Encoder Reference Values
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:YUP:REF
            field: EGU cnt
            io: i
        '}
        nEncRefYupM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:YDWN:REF
            field: EGU cnt
            io: i
        '}
        nEncRefYdwnM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:XUP:REF
            field: EGU cnt
            io: i
        '}
        nEncRefXupM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:XDWN:REF
            field: EGU cnt
            io: i
        '}
        nEncRefXdwnM1K4 : UDINT;
        {attribute 'pytmc' := '
            pv: MR1K4:SOMS:ENC:PITCH:REF
            field: EGU cnt
            io: i
        '}
        nEncRefPitchM1K4 : UDINT;
        mcReadParameterPitchM1K4 : MC_ReadParameter;
        fEncRefPitchM1K4_urad : LREAL; // Current Pitch encoder offset in urad

    // Common
    fEncLeverArm_mm : LREAL := 513.0;

// LAMP KB Motors
    //MR2K4 X
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M2K4X]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M2K4X]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4X_M2K4Y]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
        pv: MR2K4:KBO:MMS:X
        '}
        M7 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStage_m7 : FB_MotionStage;
    //MR2K4 Y
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M2K4Y]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M2K4Y]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4X_M2K4Y]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
        pv: MR2K4:KBO:MMS:Y
        '}
        //PMPS State Stage; bPowerSelf:=False
        M8 : ST_MotionStage := (sName:='MR2K4-Coatings', nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=FALSE);
        fbMotionStage_m8 : FB_MotionStage;
    //MR2K4 rY
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M2K4rY]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M2K4rY]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4rY_M3K4X]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
        pv: MR2K4:KBO:MMS:PITCH
        '}
        M9 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStage_m9 : FB_MotionStage;
    //MR2K4 US BEND
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M2K4_BEND_US]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041_M2K4_BEND_US]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4_BEND_USDS]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
        pv: MR2K4:KBO:MMS:BEND:US
        '}
        M10 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        fbMotionStage_m10 : FB_MotionStage;
    //MR2K4 DS BEND
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M2K4_BEND_DS]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041_M2K4_BEND_DS]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4_BEND_USDS]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
        pv: MR2K4:KBO:MMS:BEND:DS
        '}
        M11 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        fbMotionStage_m11 : FB_MotionStage;
    //MR3K4 X
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M3K4X]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M3K4X]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4rY_M3K4X]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
        pv: MR3K4:KBO:MMS:X
        '}
        //PMPS State Stage; bPowerSelf:=False
        M12 : ST_MotionStage := (sName:='MR3K4-Coatings', nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=FALSE);
        fbMotionStage_m12 : FB_MotionStage;
    //MR3K4 Y
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M3K4Y]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M3K4Y]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M3K4Y_M3K4rX]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
        pv: MR3K4:KBO:MMS:Y
        '}
        M13 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStage_m13 : FB_MotionStage;
    //MR3K4 rX
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041-0052_M3K4rX]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041-0052_M3K4rX]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M3K4Y_M3K4rX]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
        pv: MR3K4:KBO:MMS:PITCH
        '}
        M14 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStage_m14 : FB_MotionStage;
    //MR3K4 US BEND
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M3K4_BEND_US]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041_M3K4_BEND_US]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M3K4_BEND_USDS]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
        pv: MR3K4:KBO:MMS:BEND:US
        '}
        M15 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        fbMotionStage_m15 : FB_MotionStage;
        //////////////////////////////////
    //MR3K4 DS BEND
        {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M3K4_BEND_DS]^STM Status^Status^Digital input 1;
                                  .bLimitBackwardEnable:=TIIB[EL7041_M3K4_BEND_DS]^STM Status^Status^Digital input 2;
                                  .nRawEncoderULINT    := TIIB[EL5042_M2K4_BEND_USDS]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
        pv: MR3K4:KBO:MMS:BEND:DS
        '}
        M16 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        fbMotionStage_m16 : FB_MotionStage;
    //M4K4 X
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M4K4X]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M4K4X]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M4K4X_M4K4Y]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:MMS:X
        '}
        M17 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM17 : FB_MotionStage;
    //M4K4 Y
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M4K4Y]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M4K4Y]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M4K4X_M4K4Y]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:MMS:Y
        '}
        M18 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM18 : FB_MotionStage;
    //M4K4 Z
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M4K4Z]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M4K4Z]^STM Status^Status^Digital input 1;
                              .nRawEncoderULINT:=TIIB[EL5042_M4K4Z_M4K4rX]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:MMS:Z
        '}
        M19 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM19 : FB_MotionStage;

    //M4K4 rX
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M4K4rX]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M4K4rX]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M4K4Z_M4K4rX]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:MMS:PITCH
        '}
        M20 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM20 : FB_MotionStage;
    //M5K4 X
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M5K4X]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M5K4X]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M5K4X_M5K4Y]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:MMS:X
        '}
        M21 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM21 : FB_MotionStage;
    //M5K4 Y
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M5K4Y]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M5K4Y]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M5K4X_M5K4Y]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:MMS:Y
        '}
        M22 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM22 : FB_MotionStage;
    //M5K4 Z
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M5K4Z]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M5K4Z]^STM Status^Status^Digital input 1;
                              .nRawEncoderULINT:=TIIB[EL5042_M5K4Z_M5K4rY]^FB Inputs Channel 1^Position'}
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:MMS:Z
        '}
        M23 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM23 : FB_MotionStage;
    //M5K4 rY
        {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7041-0052_M5K4rY]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable:=TIIB[EL7041-0052_M5K4rY]^STM Status^Status^Digital input 2;
                              .nRawEncoderULINT:=TIIB[EL5042_M5K4Z_M5K4rY]^FB Inputs Channel 2^Position'}
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:MMS:PITCH
        '}
        M24 : ST_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE);
        fbMotionStageM24 : FB_MotionStage;

        // SL2K4-SCATTER: 4 Axes
        // In order to get LVDT linked to NC motion, you have to first link the IO in the NC to the stepper interface, then clear link  Axis->Inputs->In->nDataIn1->nDataIn1[0], then rebuild
        {attribute 'pytmc' := 'pv: SL2K4:SCATTER:MMS:TOP'}
        {attribute 'TcLinkTo' := '.nRawEncoderDINT      := TIIB[SL2K4-EL5072-E1]^IND Inputs Channel 1^Position'}
        M25: ST_MotionStage := (sName := 'SL2K4:SCATTER:MMS:TOP', nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        {attribute 'pytmc' := 'pv: SL2K4:SCATTER:MMS:BOTTOM'}
        {attribute 'TcLinkTo' := '.nRawEncoderDINT      := TIIB[SL2K4-EL5072-E1]^IND Inputs Channel 2^Position'}
        M26: ST_MotionStage := (sName := 'SL2K4:SCATTER:MMS:BOTTOM', nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        {attribute 'pytmc' := 'pv: SL2K4:SCATTER:MMS:NORTH'}
        {attribute 'TcLinkTo' := '.nRawEncoderDINT      := TIIB[SL2K4-EL5072-E2]^IND Inputs Channel 1^Position'}
        M27: ST_MotionStage := (sName := 'SL2K4:SCATTER:MMS:NORTH', nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);
        {attribute 'pytmc' := 'pv: SL2K4:SCATTER:MMS:SOUTH'}
        {attribute 'TcLinkTo' := '.nRawEncoderDINT      := TIIB[SL2K4-EL5072-E2]^IND Inputs Channel 2^Position'}
        M28: ST_MotionStage := (sName := 'SL2K4:SCATTER:MMS:SOUTH', nEnableMode:=ENUM_StageEnableMode.DURING_MOTION, bPowerSelf:=TRUE);

        fbMotionStage_m25: FB_MotionStage;
        fbMotionStage_m26: FB_MotionStage;
        fbMotionStage_m27: FB_MotionStage;
        fbMotionStage_m28: FB_MotionStage;

        {attribute 'TcLinkTo' := 'TINC^NC-Task 1 SAF^Axes^SL2K4_TOP^Enc^Inputs^In^nDataIn1'}
        nM25Position AT %Q*: UDINT;
        {attribute 'TcLinkTo' := 'TINC^NC-Task 1 SAF^Axes^SL2K4_BOTTOM^Enc^Inputs^In^nDataIn1'}
        nM26Position AT %Q*: UDINT;
        {attribute 'TcLinkTo' := 'TINC^NC-Task 1 SAF^Axes^SL2K4_NORTH^Enc^Inputs^In^nDataIn1'}
        nM27Position AT %Q*: UDINT;
        {attribute 'TcLinkTo' := 'TINC^NC-Task 1 SAF^Axes^SL2K4_SOUTH^Enc^Inputs^In^nDataIn1'}
        nM28Position AT %Q*: UDINT;

    //MR4K4 MR5K4 STO button
    {attribute 'TcLinkTo' := 'TIIB[Term 109 (EL1004)]^Channel 1^Input'}
    bDreamEnable1 AT %I* : BOOL;
        {attribute 'TcLinkTo' := 'TIIB[Term 109 (EL1004)]^Channel 2^Input'}
    bDreamEnable2 AT %I* : BOOL;
    // Encoder Arrays/RMS Watch:
        //MR2K4 X ENC RMS
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:X
        '}
        fbXRMSErrorM2K4 : FB_RMSWatch;
        fMaxXRMSErrorM2K4 : LREAL;
        fMinXRMSErrorM2K4 : LREAL;
        //MR2K4 Y ENC RMS
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:Y
        '}
        fbYRMSErrorM2K4 : FB_RMSWatch;
        fMaxYRMSErrorM2K4 : LREAL;
        fMinYRMSErrorM2K4 : LREAL;
        //MR2K4 rY ENC RMS
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:PITCH
        '}
        fbrYRMSErrorM2K4 : FB_RMSWatch;
        fMaxrYRMSErrorM2K4 : LREAL;
        fMinrYRMSErrorM2K4 : LREAL;
        //MR2K4 US BENDER ENC RMS
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:BEND:US
        '}
        fbBendUSRMSErrorM2K4 : FB_RMSWatch;
        fMaxBendUSRMSErrorM2K4 : LREAL;
        fMinBendUSRMSErrorM2K4 : LREAL;
        //MR2K4 DS BENDER ENC RMS
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:BEND:DS
        '}
        fbBendDSRMSErrorM2K4 : FB_RMSWatch;
        fMaxBendDSRMSErrorM2K4 : LREAL;
        fMinBendDSRMSErrorM2K4 : LREAL;
        //MR3K4 X ENC RMS
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:X
        '}
        fbXRMSErrorM3K4 : FB_RMSWatch;
        fMaxXRMSErrorM3K4 : LREAL;
        fMinXRMSErrorM3K4 : LREAL;
        //MR3K4 Y ENC RMS
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:Y
        '}
        fbYRMSErrorM3K4 : FB_RMSWatch;
        fMaxYRMSErrorM3K4 : LREAL;
        fMinYRMSErrorM3K4 : LREAL;
        //MR3K4 rX ENC RMS
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:PITCH
        '}
        fbrXRMSErrorM3K4 : FB_RMSWatch;
        fMaxrXRMSErrorM3K4 : LREAL;
        fMinrXRMSErrorM3K4 : LREAL;
        //MR3K4 US BENDER ENC RMS
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:BEND:US
        '}
        fbBendUSRMSErrorM3K4 : FB_RMSWatch;
        fMaxBendUSRMSErrorM3K4 : LREAL;
        fMinBendUSRMSErrorM3K4 : LREAL;
        //MR3K4 DS BENDER ENC RMS
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:BEND:DS
        '}
        fbBendDSRMSErrorM3K4 : FB_RMSWatch;
        fMaxBendDSRMSErrorM3K4 : LREAL;
        fMinBendDSRMSErrorM3K4 : LREAL;
        //MR4K4 X ENC RMS
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:ENC:X
        '}
        fbXRMSErrorM4K4 : FB_RMSWatch;
        fMaxXRMSErrorM4K4 : LREAL;
        fMinXRMSErrorM4K4 : LREAL;

        //MR4K4 Y ENC RMS
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:ENC:Y
        '}
        fbYRMSErrorM4K4 : FB_RMSWatch;
        fMaxYRMSErrorM4K4 : LREAL;
        fMinYRMSErrorM4K4 : LREAL;

        //MR4K4 Z ENC RMS
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:ENC:Z
        '}
        fbZRMSErrorM4K4 : FB_RMSWatch;
        fMaxZRMSErrorM4K4 : LREAL;
        fMinZRMSErrorM4K4 : LREAL;
        //MR4K4 rX ENC RMS
        {attribute 'pytmc' := '
            pv: MR4K4:KBO:ENC:PITCH
        '}
        fbPRMSErrorM4K4 : FB_RMSWatch;
        fMaxPRMSErrorM4K4 : LREAL;
        fMinPRMSErrorM4K4 : LREAL;

        //MR5K4 X ENC RMS
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:ENC:X
        '}
        fbXRMSErrorM5K4 : FB_RMSWatch;
        fMaxXRMSErrorM5K4 : LREAL;
        fMinXRMSErrorM5K4 : LREAL;

        //MR5K4 Y ENC RMS
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:ENC:Y
        '}
        fbYRMSErrorM5K4 : FB_RMSWatch;
        fMaxYRMSErrorM5K4 : LREAL;
        fMinYRMSErrorM5K4 : LREAL;

        //MR5K4 Z ENC RMS
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:ENC:Z
        '}
        fbZRMSErrorM5K4 : FB_RMSWatch;
        fMaxZRMSErrorM5K4 : LREAL;
        fMinZRMSErrorM5K4 : LREAL;
        //MR5K4 rX ENC RMS
        {attribute 'pytmc' := '
            pv: MR5K4:KBO:ENC:PITCH
        '}
        fbPRMSErrorM5K4 : FB_RMSWatch;
        fMaxPRMSErrorM5K4 : LREAL;
        fMinPRMSErrorM5K4 : LREAL;


    // Encoder Reference Values
        //MR2K4 X ENC REF
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:X:REF
            field: EGU cnt
            io: i
        '}
        nEncRefXM2K4 : UDINT;
        //MR2K4 Y ENC REF
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:Y:REF
            field: EGU cnt
            io: i
        '}
        nEncRefYM2K4 : UDINT;
        //MR2K4 rY ENC REF
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:PITCH:REF
            field: EGU cnt
            io: i
        '}
        nEncRefrYM2K4 : UDINT;
        //MR3K4 X ENC REF
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:X:REF
            field: EGU cnt
            io: i
        '}
        nEncRefXM3K4 : UDINT;
        //MR3K4 Y ENC REF
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:Y:REF
            field: EGU cnt
            io: i
        '}
        nEncRefYM3K4 : UDINT;
        //MR3K4 rX ENC REF
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:PITCH:REF
            field: EGU cnt
            io: i
        '}
        nEncRefrXM3K4 : UDINT;

    // Encoder raw counts
        //MR2K4 X ENC CNT
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:X:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntXM2K4 : UDINT;
        //MR2K4 Y ENC CNT
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:Y:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntYM2K4 : UDINT;
        //MR2K4 rY ENC CNT
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:ENC:PITCH:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntrYM2K4 : UDINT;
        //MR3K4 X ENC CNT
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:X:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntXM3K4 : UDINT;
        //MR3K4 Y ENC CNT
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:Y:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntYM3K4 : UDINT;
        //MR3K4 rX ENC CNT
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:ENC:PITCH:CNT
            field: EGU cnt
            io: i
        '}
        nEncCntrXM3K4 : UDINT;

    //Emergency Stop for LAMP KBs (M2K4 and M3K4)
        LAMPbSTOEnable1 AT %I* : BOOL;
        LAMPbSTOEnable2 AT %I* : BOOL;

    // LAMP KB BENDER RTDs
    // M2K4 US RTDs
            {attribute 'pytmc' := '
                pv: MR2K4:KBO:RTD:BEND:US:1
                field: ASLO 0.1
                field: EGU C
                io: i
            '}
            fM2K4US_RTD_1 : REAL;
            {attribute 'pytmc' := '
                pv: MR2K4:KBO:RTD:BEND:US:3
                field: ASLO 0.1
                field: EGU C
                io: i
            '}
            fM2K4US_RTD_3 : REAL;

    // M2K4 DS RTDs
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:RTD:BEND:DS:1
            field: ASLO 0.1
            field: EGU C
            io: i
        '}
        fM2K4DS_RTD_1 : REAL;
        {attribute 'pytmc' := '
            pv: MR2K4:KBO:RTD:BEND:DS:3
            field: ASLO 0.1
            field: EGU C
            io: i
        '}
        fM2K4DS_RTD_3 : REAL;
    // M3K4 US RTDs
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:RTD:BEND:US:1
            field: ASLO 0.1
            field: EGU C
            io: i
        '}
        fM3K4US_RTD_1 : REAL;
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:RTD:BEND:US:3
            field: ASLO 0.1
            field: EGU C
            io: i
        '}
        fM3K4US_RTD_3 : REAL;
    // M3K4 DS RTDs
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:RTD:BEND:DS:1
            field: ASLO 0.1
            field: EGU C
            io: i
        '}
        fM3K4DS_RTD_1 : REAL;
        {attribute 'pytmc' := '
            pv: MR3K4:KBO:RTD:BEND:DS:3
            field: ASLO 0.1
            field: EGU cnt
            io: i
        '}
        fM3K4DS_RTD_3 AT %I* : REAL;

    // RTD error bit
        bM2K4US_RTD_1_Err AT %I*: BOOL;
        bM2K4US_RTD_2_Err AT %I*: BOOL;
        bM2K4US_RTD_3_Err AT %I*: BOOL;
        bM2K4DS_RTD_1_Err AT %I*: BOOL;
        bM2K4DS_RTD_2_Err AT %I*: BOOL;
        bM2K4DS_RTD_3_Err AT %I*: BOOL;
        bM3K4US_RTD_1_Err AT %I*: BOOL;
        bM3K4US_RTD_2_Err AT %I*: BOOL;
        bM3K4US_RTD_3_Err AT %I*: BOOL;
        bM3K4DS_RTD_1_Err AT %I*: BOOL;
        bM3K4DS_RTD_2_Err AT %I*: BOOL;
        bM3K4DS_RTD_3_Err AT %I*: BOOL;

// Logging
fbLogHandler : FB_LogHandler;


END_VAR
// M1K4
    M1K4.fbRunHOMS(stYup:=M1,
                   stYdwn:=M2,
                   stXup:=M3,
                   stXdwn:=M4,
                   stPitch:=M5,
                   nYupEncRef:=GVL_M1K4_Constants.nYUP_ENC_REF,
                   nYdwnEncRef:=GVL_M1K4_Constants.nYDWN_ENC_REF,
                   nXupEncRef:=GVL_M1K4_Constants.nXUP_ENC_REF,
                   nXdwnEncRef:=GVL_M1K4_Constants.nXDWN_ENC_REF,
                   bExecuteCoupleY:=M1K4.bExecuteCoupleY,
                   bExecuteCoupleX:=M1K4.bExecuteCoupleX,
                   bExecuteDecoupleY:=M1K4.bExecuteDecoupleY,
                   bExecuteDecoupleX:=M1K4.bExecuteDecoupleX,
                   bGantryAlreadyCoupledY=>M1K4.bGantryAlreadyCoupledY,
                   bGantryAlreadyCoupledX=>M1K4.bGantryAlreadyCoupledX,
                   nCurrGantryY=>M1K4.nCurrGantryY,
                   nCurrGantryX=>M1K4.nCurrGantryX);
(*    fbBenderM1K4(stBender:=M6,
                 bSTOEnable1:=M1K4.fbRunHOMS.bSTOEnable1,
                 bSTOEnable2:=M1K4.fbRunHOMS.bSTOEnable2);
*)
    // No slave motion through Epics
    M2.bExecute := FALSE; // M1K4-Ydwn
    M4.bExecute := FALSE; // M1K4-Xdwn

    // Convert nCurrGantry to um (smaller number) to read out in epics
        M1K4.fCurrGantryY_um := LINT_TO_REAL(M1K4.nCurrGantryY) / 1000.0;
        M1K4.fCurrGantryX_um := LINT_TO_REAL(M1K4.nCurrGantryX) / 1000.0;

    // FB_MotionStage's for non-piezo axes
        fbMotionStage_m1(stMotionStage:=M1);
        fbMotionStage_m2(stMotionStage:=M2);
        fbMotionStage_m3(stMotionStage:=M3);
        fbMotionStage_m4(stMotionStage:=M4);
        fbMotionStage_m5(stMotionStage:=M5);
//        fbMotionStage_m6(stMotionStage:=M6);

    // Calculate Pitch RMS Error:
        fbYRMSErrorM1K4(stMotionStage:=M1,
                        fMaxRMSError=>fMaxYRMSErrorM1K4,
                        fMinRMSError=>fMinYRMSErrorM1K4);

        fbXRMSErrorM1K4(stMotionStage:=M3,
                        fMaxRMSError=>fMaxXRMSErrorM1K4,
                        fMinRMSError=>fMinXRMSErrorM1K4);

        fbPitchRMSErrorM1K4(stMotionStage:=M5,
                            fMaxRMSError=>fMaxPitchRMSErrorM1K4,
                            fMinRMSError=>fMinPitchRMSErrorM1K4);

(*        fbBenderRMSErrorM1K4(stMotionStage:=M6,
                             fMaxRMSError=>fMaxBenderRMSErrorM1K4,
                             fMinRMSError=>fMinBenderRMSErrorM1K4);
*)
    // Pitch Control
        //fbM1K4PitchControl(Pitch:=GVL_M1K4.M1K4_Pitch,
                           //Stepper:=M5,
                           //lrCurrentSetpoint:=M5.fPosition,
                          //q_bDone=>bM1K4PitchDone,
                           //q_bBusy=>bM1K4PitchBusy);
    // When STO hit, need to reset SP
        //IF NOT M5.bHardwareEnable THEN
            //M5.fPosition := M5.stAxisStatus.fActPosition;
        //END_IF

    // Raw Encoder Counts For Epics
        nEncCntYupM1K4 := ULINT_TO_UDINT(M1K4.fbRunHOMS.stYupEnc.Count);
        nEncCntYdwnM1K4 := ULINT_TO_UDINT(M1K4.fbRunHOMS.stYdwnEnc.Count);
        nEncCntXupM1K4 := ULINT_TO_UDINT(M1K4.fbRunHOMS.stXupEnc.Count);
        nEncCntXdwnM1K4 := ULINT_TO_UDINT(M1K4.fbRunHOMS.stXdwnEnc.Count);
        nEncCntPitchM1K4 := LINT_TO_UDINT(GVL_M1K4.M1K4_Pitch.diEncCnt);

    // Encoder Reference Values For Epics
        nEncRefYupM1K4 := ULINT_TO_UDINT(GVL_M1K4_Constants.nYUP_ENC_REF);
        nEncRefYdwnM1K4 := ULINT_TO_UDINT(GVL_M1K4_Constants.nYDWN_ENC_REF);
        nEncRefXupM1K4 := ULINT_TO_UDINT(GVL_M1K4_Constants.nXUP_ENC_REF);
        nEncRefXdwnM1K4 := ULINT_TO_UDINT(GVL_M1K4_Constants.nXDWN_ENC_REF);
        mcReadParameterPitchM1K4(Axis:=M5.Axis,
                                 Enable:=TRUE,
                                 ParameterNumber:=MC_AxisParameter.AxisEncoderOffset,
                                 ReadMode:=READMODE_CYCLIC,
                                 Value=>fEncRefPitchM1K4_urad);

        nEncRefPitchM1K4 := LREAL_TO_UDINT(ABS(fEncRefPitchM1K4_urad) * fEncLeverArm_mm);
//////////////////////////////////////////////////////////
//M2K4 and M3K4
    //FB_Motion stages for LAMP KBs
        //MR2K4
            fbMotionStage_m7(stMotionStage:=M7);
            fbMotionStage_m8(stMotionStage:=M8);
            fbMotionStage_m9(stMotionStage:=M9);
        //MR2K4 BEND
            fbMotionStage_m10(stMotionStage:=M10);
            fbMotionStage_m11(stMotionStage:=M11);
        //MR3K4
            fbMotionStage_m12(stMotionStage:=M12);
            fbMotionStage_m13(stMotionStage:=M13);
            fbMotionStage_m14(stMotionStage:=M14);
        //MR3K4 BEND
            fbMotionStage_m15(stMotionStage:=M15);
            fbMotionStage_m16(stMotionStage:=M16);

//MR4K4 and MR5K4
            M17.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M18.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M19.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M20.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M21.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M22.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M23.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
            M24.bHardwareEnable := bDREAMEnable1 and bDREAMenable2;
        //MR4K4
            fbMotionStageM17(stMotionStage:=M17);
            fbMotionStageM18(stMotionStage:=M18);
            fbMotionStageM19(stMotionStage:=M19);
            fbMotionStageM20(stMotionStage:=M20);
        //MR5K4
            fbMotionStageM21(stMotionStage:=M21);
            fbMotionStageM22(stMotionStage:=M22);
            fbMotionStageM23(stMotionStage:=M23);
            fbMotionStageM24(stMotionStage:=M24);


    // Calculate Pitch RMS Error for LAMP KBs:
        //MR2K4 X ENC RMS
        fbXRMSErrorM2K4(stMotionStage:=M7,
                        fMaxRMSError=>fMaxXRMSErrorM2K4,
                        fMinRMSError=>fMinXRMSErrorM2K4);
        //MR2K4 Y ENC RMS
        fbYRMSErrorM2K4(stMotionStage:=M8,
                        fMaxRMSError=>fMaxYRMSErrorM2K4,
                        fMinRMSError=>fMinYRMSErrorM2K4);
        //MR2K4 rY ENC RMS
        fbrYRMSErrorM2K4(stMotionStage:=M9,
                        fMaxRMSError=>fMaxrYRMSErrorM2K4,
                        fMinRMSError=>fMinrYRMSErrorM2K4);
        //MR2K4 US BENDER ENC RMS
        fbBendUSRMSErrorM2K4(stMotionStage:=M10,
                             fMaxRMSError=>fMaxBendUSRMSErrorM2K4,
                             fMinRMSError=>fMinBendUSRMSErrorM2K4);
        //MR2K4 DS BENDER ENC RMS
        fbBendDSRMSErrorM2K4(stMotionStage:=M11,
                             fMaxRMSError=>fMaxBendDSRMSErrorM2K4,
                             fMinRMSError=>fMinBendDSRMSErrorM2K4);
        //MR3K4 X ENC RMS
        fbXRMSErrorM3K4(stMotionStage:=M12,
                        fMaxRMSError=>fMaxXRMSErrorM3K4,
                        fMinRMSError=>fMinXRMSErrorM3K4);
        //MR3K4 Y ENC RMS
        fbYRMSErrorM3K4(stMotionStage:=M13,
                        fMaxRMSError=>fMaxYRMSErrorM3K4,
                        fMinRMSError=>fMinYRMSErrorM3K4);
        //MR3K4 rX ENC RMS
        fbrXRMSErrorM3K4(stMotionStage:=M14,
                        fMaxRMSError=>fMaxrXRMSErrorM3K4,
                        fMinRMSError=>fMinrXRMSErrorM3K4);
        //MR3K4 US BENDER ENC RMS
        fbBendUSRMSErrorM3K4(stMotionStage:=M15,
                             fMaxRMSError=>fMaxBendUSRMSErrorM3K4,
                             fMinRMSError=>fMinBendUSRMSErrorM3K4);
        //MR3K4 DS BENDER ENC RMS
        fbBendDSRMSErrorM3K4(stMotionStage:=M16,
                             fMaxRMSError=>fMaxBendDSRMSErrorM3K4,
                             fMinRMSError=>fMinBendDSRMSErrorM3K4);
    // Calculate Pitch RMS Error for DREAM KBs:
        //MR4K4 X ENC RMS
        fbXRMSErrorM4K4(stMotionStage:=M17,
                        fMaxRMSError=>fMaxXRMSErrorM4K4,
                        fMinRMSError=>fMinXRMSErrorM4K4);
        //MR4K4 Y ENC RMS
        fbYRMSErrorM4K4(stMotionStage:=M18,
                        fMaxRMSError=>fMaxYRMSErrorM4K4,
                        fMinRMSError=>fMinYRMSErrorM4K4);
        //MR4K4 Z ENC RMS
        fbZRMSErrorM4K4(stMotionStage:=M19,
                        fMaxRMSError=>fMaxZRMSErrorM4K4,
                        fMinRMSError=>fMinZRMSErrorM4K4);
        //MR4K4 rX ENC RMS
        fbPRMSErrorM4K4(stMotionStage:=M20,
                        fMaxRMSError=>fMaxPRMSErrorM4K4,
                        fMinRMSError=>fMinPRMSErrorM4K4);
        //MR5K4 X ENC RMS
        fbXRMSErrorM5K4(stMotionStage:=M21,
                        fMaxRMSError=>fMaxXRMSErrorM5K4,
                        fMinRMSError=>fMinXRMSErrorM5K4);
        //MR5K4 Y ENC RMS
        fbYRMSErrorM5K4(stMotionStage:=M22,
                        fMaxRMSError=>fMaxYRMSErrorM5K4,
                        fMinRMSError=>fMinYRMSErrorM5K4);
        //MR5K4 Z ENC RMS
        fbZRMSErrorM5K4(stMotionStage:=M23,
                        fMaxRMSError=>fMaxZRMSErrorM5K4,
                        fMinRMSError=>fMinZRMSErrorM5K4);
        //MR5K4 rY ENC RMS
        fbPRMSErrorM5K4(stMotionStage:=M24,
                        fMaxRMSError=>fMaxPRMSErrorM5K4,
                        fMinRMSError=>fMinPRMSErrorM5K4);


    //STO for LAMP KBs
        //MR2K4
        M7.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M8.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M9.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        //MR2K4 BEND
        M10.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M11.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        //MR3K4
        M12.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M13.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M14.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        //MR3K4 BEND
        M15.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;
        M16.bHardwareEnable := LAMPbSTOEnable1 AND LAMPbSTOEnable2;

    // LAMP KB Encoder Reference Values For Epics
        nEncRefXM2K4  := ULINT_TO_UDINT(GVL_M2K4_Constants.nM2K4X_ENC_REF);
        nEncRefYM2K4  := ULINT_TO_UDINT(GVL_M2K4_Constants.nM2K4Y_ENC_REF);
        nEncRefrYM2K4 := ULINT_TO_UDINT(GVL_M2K4_Constants.nM2K4rY_ENC_REF);
        nEncRefXM3K4  := ULINT_TO_UDINT(GVL_M3K4_Constants.nM3K4X_ENC_REF);
        nEncRefYM3K4  := ULINT_TO_UDINT(GVL_M3K4_Constants.nM3K4Y_ENC_REF);
        nEncRefrXM3K4 := ULINT_TO_UDINT(GVL_M3K4_Constants.nM3K4rX_ENC_REF);

    // LAMP KB Encoder Count Values For Epics
        nEncCntXM2K4  := ULINT_TO_UDINT(M7.nRawEncoderULINT);
        nEncCntYM2K4  := ULINT_TO_UDINT(M8.nRawEncoderULINT);
        nEncCntrYM2K4 := ULINT_TO_UDINT(M9.nRawEncoderULINT);
        nEncCntXM3K4  := ULINT_TO_UDINT(M12.nRawEncoderULINT);
        nEncCntYM3K4  := ULINT_TO_UDINT(M13.nRawEncoderULINT);
        nEncCntrXM3K4 := ULINT_TO_UDINT(M14.nRawEncoderULINT);

;

    // LAMP KB Bender RTDs
        fM2K4US_RTD_1 := INT_TO_REAL(GVL_M2K4_RTD.nM2K4US_RTD_1);
        fM2K4US_RTD_3 := INT_TO_REAL(GVL_M2K4_RTD.nM2K4US_RTD_3);

        fM2K4DS_RTD_1 := INT_TO_REAL(GVL_M2K4_RTD.nM2K4DS_RTD_1);
        fM2K4DS_RTD_3 := INT_TO_REAL(GVL_M2K4_RTD.nM2K4DS_RTD_3);

        fM3K4US_RTD_1 := INT_TO_REAL(GVL_M3K4_RTD.nM3K4US_RTD_1);
        fM3K4US_RTD_3 := INT_TO_REAL(GVL_M3K4_RTD.nM3K4US_RTD_3);

        fM3K4DS_RTD_1 := INT_TO_REAL(GVL_M3K4_RTD.nM3K4DS_RTD_1);
        fM3K4DS_RTD_3 := INT_TO_REAL(GVL_M3K4_RTD.nM3K4DS_RTD_3);




    // RTD not connected if T=0
        bM2K4US_RTD_1_Err := fM2K4US_RTD_1 = 0;
        bM2K4US_RTD_3_Err := fM2K4US_RTD_3 = 0;
        bM2K4DS_RTD_1_Err := fM2K4DS_RTD_1 = 0;
        bM2K4DS_RTD_3_Err := fM2K4DS_RTD_3 = 0;

        bM3K4US_RTD_1_Err := fM3K4US_RTD_1 = 0;
        bM3K4US_RTD_3_Err := fM3K4US_RTD_3 = 0;
        bM3K4DS_RTD_1_Err := fM3K4DS_RTD_1 = 0;
        bM3K4DS_RTD_3_Err := fM3K4DS_RTD_3 = 0;

    // LAMP KB Bender RTD interlocks
        M10.bHardwareEnable R= fM2K4US_RTD_1 > 1000 OR bM2K4US_RTD_1_Err;
        M11.bHardwareEnable R= fM2K4DS_RTD_1 > 1000 OR bM2K4DS_RTD_1_Err;
        M15.bHardwareEnable R= fM3K4US_RTD_1 > 1000 OR bM3K4US_RTD_1_Err;
        M16.bHardwareEnable R= fM3K4DS_RTD_1 > 1000 OR bM3K4DS_RTD_1_Err;

    // SL2K4
    nM25Position := DINT_TO_UDINT(Main.M25.nRawEncoderDINT);

    Main.M25.bLimitBackwardEnable := TRUE;
    Main.M25.bLimitForwardEnable := TRUE;
    Main.M25.bHardwareEnable := TRUE;

    fbMotionStage_m25(stMotionStage:=Main.M25);

    nM26Position := DINT_TO_UDINT(Main.M26.nRawEncoderDINT);

    Main.M26.bLimitBackwardEnable := TRUE;
    Main.M26.bLimitForwardEnable := TRUE;
    Main.M26.bHardwareEnable := TRUE;

    fbMotionStage_m26(stMotionStage:=Main.M26);

    nM27Position := DINT_TO_UDINT(Main.M27.nRawEncoderDINT);

    Main.M27.bLimitBackwardEnable := TRUE;
    Main.M27.bLimitForwardEnable := TRUE;
    Main.M27.bHardwareEnable := TRUE;

    fbMotionStage_m27(stMotionStage:=Main.M27);

    nM28Position := DINT_TO_UDINT(Main.M28.nRawEncoderDINT);

    Main.M28.bLimitBackwardEnable := TRUE;
    Main.M28.bLimitForwardEnable := TRUE;
    Main.M28.bHardwareEnable := TRUE;

    fbMotionStage_m28(stMotionStage:=Main.M28);

// Environment
    PRG_Environment();
// States
    PRG_States();
// PMPS
    PRG_PMPS();
////////////////////////////////

// Logging
fbLogHandler();

END_PROGRAM
Related:

P_Serial_Com

PROGRAM P_Serial_Com
VAR
    fbSerialLineControl_EL6001_M1K4: SerialLineControl;
END_VAR
//These are the global IOs...don't forget to copy your data into them

(* EL6001 Serial port 0 com function *)
fbSerialLineControl_EL6001_M1K4(Mode:= SERIALLINEMODE_EL6_22B (*SERIALLINEMODE_KL6_22B_STANDARD*),
                                pComIn:= ADR(Serial_stComIn_M1K4),
                                   pComOut:=ADR(Serial_stComOut_M1K4),
                                SizeComIn:= SIZEOF(Serial_stComIn_M1K4),
                                TxBuffer:= Serial_TXBuffer_M1K4,
                                RxBuffer:= Serial_RXBuffer_M1K4,
                                Error=> ,
                                ErrorID=> );

END_PROGRAM

P_StripeProtections

PROGRAM P_StripeProtections
VAR
(*
MR1K4 (RBV = MR1K4:SOMS:ENC:YUP:CNT_RBV)
B4C coating: RBV <= 15998960: 1111_1111_1111_1000 (allow everything between 350eV and 2.3keV)
Transition: 15998960 < RBV < 19998960: 0000_0000_0000_0000
Silicon surface: RBV >= 19998960: 0000_0000_0001_1110 (allow everything between 250eV and 450eV)
From M. Seaberg
*)
    fbStripProtMR1K4 : FB_MirrorTwoCoatingProtection := (
        sDevName := 'MR1K4:SOMS',
        nUpperCoatingBoundary := 19998960,
        sUpperCoatingType := 'SILICON',
        nLowerCoatingBoundary := 15998960,
        sLowerCoatingType := 'B4C');

(*
MR2K4 (RBV = MR2K4:KBO:ENC:Y:CNT_RBV)
B4C coating: RBV <= 6976835: 1111_1111_1111_1000 (allow everything between 350eV and 2.3keV)
Transition: 6976835 < RBV < 7776781: 0000_0000_0000_0000
Silicon surface: RBV >= 7776781: 0000_0000_0001_1110 (allow everything below 250eV and 450eV)
*)
    // MR2K4 Mirror Chin Guard RTDs
    {attribute 'TcLinkTo' := '.ffUpperCoatingLTemp.iRaw := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Value;
                              .ffUpperCoatingLTemp.bUnderrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .ffUpperCoatingLTemp.bOverrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .ffUpperCoatingLTemp.bError := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Error;

                              .ffUpperCoatingRTemp.iRaw := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Value;
                              .ffUpperCoatingRTemp.bUnderrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .ffUpperCoatingRTemp.bOverrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .ffUpperCoatingRTemp.bError := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Error;

                              .ffLowerCoatingLTemp.iRaw := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Value;
                              .ffLowerCoatingLTemp.bUnderrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .ffLowerCoatingLTemp.bOverrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .ffLowerCoatingLTemp.bError := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Error;

                              .ffLowerCoatingRTemp.iRaw := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Value;
                              .ffLowerCoatingRTemp.bUnderrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .ffLowerCoatingRTemp.bOverrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .ffLowerCoatingRTemp.bError := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Error
    '}
    {attribute 'pytmc' := '
        pv: MR2K4:KBO
    '}
     fbStripProtMR2K4 : FB_MirrorTwoCoatingProtection := (
        sDevName := 'MR2K4:KBO',
        nUpperCoatingBoundary := 7776781,
        sUpperCoatingType := 'SILICON',
        nLowerCoatingBoundary := 6976835,
        sLowerCoatingType := 'B4C');

(*
MR3K4 (RBV = MR3K4:KBO:ENC:X:CNT_RBV)
B4C coating: RBV >= 5620000: 1111_1111_1111_1000 (allow everything between 350eV and 2.3keV)
Transition: 4820000 < ENC < 5620000: 0000_0000_0000_0000
Silicon surface: RBV <= 4820000: 0000_0000_0001_1110 (allow everything between 250eV and 450 eV)
*)
    // MR3K4 Mirror Chin Guard RTDs
    {attribute 'TcLinkTo' := '.ffUpperCoatingLTemp.iRaw := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Value;
                              .ffUpperCoatingLTemp.bUnderrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .ffUpperCoatingLTemp.bOverrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .ffUpperCoatingLTemp.bError := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Error;


                              .ffUpperCoatingRTemp.iRaw := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Value;
                              .ffUpperCoatingRTemp.bUnderrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .ffUpperCoatingRTemp.bOverrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .ffUpperCoatingRTemp.bError := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Error;

                              .ffLowerCoatingLTemp.iRaw := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Value;
                              .ffLowerCoatingLTemp.bUnderrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .ffLowerCoatingLTemp.bOverrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .ffLowerCoatingLTemp.bError := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Error;

                              .ffLowerCoatingRTemp.iRaw := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Value;
                              .ffLowerCoatingRTemp.bUnderrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .ffLowerCoatingRTemp.bOverrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .ffLowerCoatingRTemp.bError := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Error
    '}
    {attribute 'pytmc' := '
        pv: MR3K4:KBO
    '}
    fbStripProtMR3K4 : FB_MirrorTwoCoatingProtection := (
        sDevName := 'MR3K4:KBO',
        nUpperCoatingBoundary := 5620000,
        sUpperCoatingType := 'B4C',
        nLowerCoatingBoundary := 4820000,
        sLowerCoatingType := 'SILICON');
END_VAR
fbStripProtMR1K4(FFO:=GVL_PMPS.g_FastFaultOutput1,
                nCurrentEncoderCount := MAIN.nEncCntYupM1K4,
                neVRange:=PMPS_GVL.stCurrentBeamParameters.neVRange,
                bReadPmpsDb:= MOTION_GVL.fbStandardPMPSDB.bReadPmpsDb,
                bUsePmpsDb := TRUE,
                );

fbStripProtMR2K4(FFO:=GVL_PMPS.g_FastFaultOutput2,
                nCurrentEncoderCount := MAIN.nEncCntYM2K4,
                neVRange:=PMPS_GVL.stCurrentBeamParameters.neVRange,
                bReadPmpsDb := MOTION_GVL.fbStandardPMPSDB.bReadPmpsDb,
                bUsePmpsDb := TRUE,
                bMirrorTempFaults := TRUE,
                );

fbStripProtMR3K4(FFO:=GVL_PMPS.g_FastFaultOutput2,
                nCurrentEncoderCount := MAIN.nEncCntXM3K4,
                neVRange:=PMPS_GVL.stCurrentBeamParameters.neVRange,
                bReadPmpsDb := MOTION_GVL.fbStandardPMPSDB.bReadPmpsDb,
                bUsePmpsDb := TRUE,
                bMirrorTempFaults := TRUE,
                );

END_PROGRAM
Related:

PiezoSerial

PROGRAM PiezoSerial
VAR
    //PI Serial
    fbE621SerialDriver_M1K4 : FB_PI_E621_SerialDriver;
    rtInitParams_M1K4       :       R_TRIG;
    tonTimeoutRst_M1K4      : TON := (PT:=T#2S); //For timeout reset
END_VAR
//Piezo E-621
///////////////////////
fbE621SerialDriver_M1K4.i_xExecute := TRUE;
fbE621SerialDriver_M1K4.i_xExecute R= fbE621SerialDriver_M1K4.q_xDone;
fbE621SerialDriver_M1K4(iq_stPiezoAxis:= GVL_M1K4.M1K4_Pitch.Piezo,
                        iq_stSerialRXBuffer:= Serial_RXBuffer_M1K4,
                        iq_stSerialTXBuffer:= Serial_TXBuffer_M1K4);

END_PROGRAM
Related:

PRG_1_PlcTask

PROGRAM PRG_1_PlcTask
VAR
END_VAR
PRG_MR1K4_SOMS();
PRG_MR2K4_KBO();
PRG_MR3K4_KBO();
PRG_MR4K4_KBO();
PRG_MR5K4_KBO();
PRG_SL2K4_SCATTER();

END_PROGRAM
Related:

PRG_Environment

PROGRAM PRG_Environment
VAR
END_VAR
// DREAM KB Internal RTDs
    GVL_M4K4_RTD.nM4K4_Chin_Left_RTD();
    GVL_M4K4_RTD.nM4K4_Chin_Right_RTD();
    GVL_M4K4_RTD.nM4K4_Chin_Tail_RTD();

    GVL_M5K4_RTD.nM5K4_Chin_Left_RTD();
    GVL_M5K4_RTD.nM5K4_Chin_Right_RTD();
    GVL_M5K4_RTD.nM5K4_Chin_Tail_RTD();

END_PROGRAM
Related:

PRG_MR1K4_SOMS

PROGRAM PRG_MR1K4_SOMS
VAR
    // M1K4 Flow Press Sensors
    {attribute 'TcLinkTo' := '.fbFlow_1.iRaw := TIIB[EL3054_M1K4_FWM_PRSM]^AI Standard Channel 1^Value;
                                 .fbFlow_2.iRaw := TIIB[EL3054_M1K4_FWM_PRSM]^AI Standard Channel 2^Value;
                              .fbPress_1.iRaw := TIIB[EL3054_M1K4_FWM_PRSM]^AI Standard Channel 3^Value
    '}
    {attribute 'pytmc' := '
        pv: MR1K4:SOMS
    '}
    fbCoolingPanel : FB_Axilon_Cooling_2f1p;
    {attribute 'TcLinkTo' := 'TIIB[EP2008-0001_M1K4_VCV]^Channel 1^Output'}
    {attribute 'pytmc' := '
        pv: MR1K4:SOMS:VCV
        io: io
        field: ZNAM OFF
        field: ONAM ON
    '}
    bActivateVarCool AT %Q* : BOOL;
END_VAR
fbCoolingPanel();

END_PROGRAM

PRG_MR2K4_KBO

PROGRAM PRG_MR2K4_KBO
VAR

    // M2K4 Flow Press Sensors
    {attribute 'TcLinkTo' := '.fbFlow_1.iRaw := TIIB[EL3054_FWM_PRSM]^AI Standard Channel 1^Value;
                              .fbPress_1.iRaw := TIIB[EL3054_FWM_PRSM]^AI Standard Channel 3^Value
    '}
    {attribute 'pytmc' := '
        pv: MR2K4:KBO
    '}
    fbCoolingPanel : FB_Axilon_Cooling_1f1p;
    // M2K4 Mirror RTDs
    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Value;
                              .bUnderrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .bOverrange := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .bError := TIIB[EL3202-0010_M2K4US1_M2K4US2]^RTD Inputs Channel 2^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR2K4:KBO:RTD:CHIN:L
        field: EGU C
        io: i
    '}
    fbM2K4_Chin_Left_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Value;
                              .bUnderrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .bOverrange := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .bError := TIIB[EL3202-0010_M2K4DS2_M2K4DS3]^RTD Inputs Channel 1^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR2K4:KBO:RTD:CHIN:R
        field: EGU C
        io: i
    '}
    fbM2K4_Chin_Right_RTD : FB_TempSensor;

END_VAR
fbCoolingPanel();
fbM2K4_Chin_Left_RTD();
fbM2K4_Chin_Right_RTD();

END_PROGRAM

PRG_MR3K4_KBO

PROGRAM PRG_MR3K4_KBO
VAR
    // M3K4 Flow Press Sensors
    {attribute 'TcLinkTo' := '.fbFlow_1.iRaw := TIIB[EL3054_FWM_PRSM]^AI Standard Channel 2^Value;
                              .fbPress_1.iRaw := TIIB[EL3054_FWM_PRSM]^AI Standard Channel 3^Value
    '}
    {attribute 'pytmc' := '
        pv: MR3K4:KBO
    '}
    fbCoolingPanel : FB_Axilon_Cooling_1f1p;

    // M3K4 Mirror RTDs
    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Value;
                              .bUnderrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Underrange;
                              .bOverrange := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Overrange;
                              .bError := TIIB[EL3202-0010_M3K4US1_M3K4US2]^RTD Inputs Channel 2^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR3K4:KBO:RTD:CHIN:L
        field: EGU C
        io: i
    '}
    fbM3K4_Chin_Left_RTD : FB_TempSensor;

    {attribute 'TcLinkTo' := '.iRaw := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Value;
                              .bUnderrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Underrange;
                              .bOverrange := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Overrange;
                              .bError := TIIB[EL3202-0010_M3K4DS2_M3K4DS3]^RTD Inputs Channel 1^Status^Error'}
    {attribute 'pytmc' := '
        pv: MR3K4:KBO:RTD:CHIN:R
        field: EGU C
        io: i
    '}
    fbM3K4_Chin_Right_RTD : FB_TempSensor;
END_VAR
fbCoolingPanel();
fbM3K4_Chin_Left_RTD();
fbM3K4_Chin_Right_RTD();

END_PROGRAM

PRG_MR4K4_KBO

PROGRAM PRG_MR4K4_KBO
VAR
        // MR4K4 Flow Press Sensors
    {attribute 'TcLinkTo' := '.fbFlow_1.iRaw := TIIB[EL3054_FWM_PRSM_MR45K4]^AI Standard Channel 1^Value;
                              .fbPress_1.iRaw := TIIB[EL3054_FWM_PRSM_MR45K4]^AI Standard Channel 2^Value
    '}
    {attribute 'pytmc' := '
        pv: MR4K4:KBO
    '}
    fbCoolingPanel : FB_Axilon_Cooling_1f1p;
END_VAR
fbCoolingPanel();

END_PROGRAM

PRG_MR5K4_KBO

PROGRAM PRG_MR5K4_KBO
VAR
    // MR5K4 Flow Press Sensors
    {attribute 'TcLinkTo' := '.fbFlow_1.iRaw := TIIB[EL3054_FWM_PRSM_MR45K4]^AI Standard Channel 3^Value;
                              .fbPress_1.iRaw := TIIB[EL3054_FWM_PRSM_MR45K4]^AI Standard Channel 2^Value
    '}
    {attribute 'pytmc' := '
        pv: MR5K4:KBO
    '}
    fbCoolingPanel : FB_Axilon_Cooling_1f1p;
END_VAR
fbCoolingPanel();

END_PROGRAM

PRG_PMPS

PROGRAM PRG_PMPS
VAR
    fb_vetoArbiter : FB_VetoArbiter;

    fbArbiterIO : FB_SubSysToArbiter_IO;

    ffFFO2ToFFO1 : FB_FastFault := (
        i_xAutoReset := TRUE,
        i_DevName := 'PMPS FFO2',
        i_Desc := 'Subordinate fast fault group, will clear on its own otherwise something is misconfigured in the diagnostic',
        i_TypeCode := 16#D);

    //fbOutputStates : FB_StateParams;

    bMR1K1_IN : BOOL;
    bST3K4_IN : BOOL;
    bMR1K3_IN : BOOL;
    bST1K4_IN : BOOL;
END_VAR
MOTION_GVL.fbStandardPMPSDB(
    io_fbFFHWO:= GVL_PMPS.g_FastFaultOutput1,
    bEnable:=TRUE,
    sPLCName:='plc-tmo-optics'
);

P_StripeProtections();

bMR1K1_IN := PMPS.PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K1_IN]
            AND NOT PMPS.PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K1_OUT];

bST3K4_IN := PMPS.PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.ST3K4];
bST1K4_IN := PMPS.PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.ST1K4];

bMR1K3_IN := PMPS.PMPS_GVL.stCurrentBeamParameters.aVetodevices[PMPS.K_Stopper.MR1K3_IN]
    AND NOT PMPS.PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K3_OUT];

fbArbiterIO(i_bVeto:= bMR1K1_IN OR bMR1K3_IN, Arbiter := GVL_PMPS.g_fbArbiter1, fbFFHWO := GVL_PMPS.g_FastFaultOutput1);

ffFFO2ToFFO1(i_xOK := GVL_PMPS.g_FastFaultOutput2.q_xFastFaultOut, io_fbFFHWO := GVL_PMPS.g_FastFaultOutput1);

GVL_PMPS.g_FastFaultOutput2.Execute(i_xVeto:= bMR1K1_IN OR bMR1K3_IN OR bST3K4_IN OR bST1K4_IN);

GVL_PMPS.g_FastFaultOutput1.Execute(i_xVeto:= bMR1K1_IN OR bMR1K3_IN);

fb_vetoArbiter(bVeto := GVL_PMPS.g_FastFaultOutput2.i_xVeto, HigherAuthority := GVL_PMPS.g_fbArbiter1, LowerAuthority:= GVL_PMPS.g_fbArbiter2,
    FFO:= GVL_PMPS.g_FastFaultOutput1);

END_PROGRAM
Related:

PRG_SL2K4_SCATTER

PROGRAM PRG_SL2K4_SCATTER
VAR
    {attribute 'pytmc' := '
    pv: SL2K4:SCATTER
    io: io'}
    fbSL2K4: FB_SLITS;

    {attribute 'pytmc' := '
    pv: SL2K4:SCATTER:GO;
    io: io;
    field: ZNAM False;
    field: ONAM True;
    '}
    bExecuteMotion :BOOL :=TRUE;
END_VAR
fbSL2K4(stTopBlade:= Main.M25,
        stBottomBlade:=Main.M26,
        stNorthBlade:= Main.M27,
        stSouthBlade:= Main.M28,
        bExecuteMotion:=bExecuteMotion,
        io_fbFFHWO := GVL_PMPS.g_FastFaultOutput2,
        fbArbiter := GVL_PMPS.g_fbArbiter2);

END_PROGRAM
Related:

PRG_States

PROGRAM PRG_States
VAR
    {attribute 'pytmc' := '
     pv: MR1K4:SOMS:COATING:STATE;
     io: io;
    '}
    fbMR1K4_Coating_States: FB_Offset_Coating_States := (bBPOkAutoReset:= TRUE);

    {attribute 'pytmc' := '
     pv: MR2K4:KBO:COATING:STATE;
     io: io;
    '}
    fbMR2K4_Coating_States: FB_KBO_Coating_States := (bBPOkAutoReset:= TRUE);

    {attribute 'pytmc' := '
     pv: MR3K4:KBO:COATING:STATE;
     io: io;
    '}
    fbMR3K4_Coating_States: FB_KBO_Coating_States := (bBPOkAutoReset:= TRUE);
END_VAR
//MR1K4 Coating States with PMPS
fbMR1K4_Coating_States.stCoating1.stPMPS.sPmpsState := 'MR1K4:SOMS-SILICON';
fbMR1K4_Coating_States.stCoating1.nEncoderCount := 22000532;

fbMR1K4_Coating_States.stCoating2.stPMPS.sPmpsState := 'MR1K4:SOMS-B4C';
fbMR1K4_Coating_States.stCoating2.nEncoderCount := 5000141;

fbMR2K4_Coating_States.stCoating1.stPMPS.sPmpsState := 'MR2K4:KBO-SILICON';
fbMR2K4_Coating_States.stCoating1.nEncoderCount := 8701960;

fbMR2K4_Coating_States.stCoating2.stPMPS.sPmpsState := 'MR2K4:KBO-B4C';
fbMR2K4_Coating_States.stCoating2.nEncoderCount := 6636177;

fbMR3K4_Coating_States.stCoating1.stPMPS.sPmpsState := 'MR3K4:KBO-SILICON';
fbMR3K4_Coating_States.stCoating1.nEncoderCount := 4719890;

fbMR3K4_Coating_States.stCoating2.stPMPS.sPmpsState := 'MR3K4:KBO-B4C';
fbMR3K4_Coating_States.stCoating2.nEncoderCount := 8220029;

fbMR1K4_Coating_States(
    bEnable := TRUE,
    stMotionStage:=Main.M1,
    sCoating1Name:='Si',
    sCoating2Name:='B4C',
    fbArbiter:=GVL_PMPS.g_fbArbiter1,
    fbFFHWO:=GVL_PMPS.g_FastFaultOutput1,
    sPmpsDeviceName:='MR1K4:SOMS',
    sTransitionKey:= 'MR1K4:SOMS-TRANSITION');

// MR2K4 Coating States with PMPS
fbMR2K4_Coating_States(
    bEnable := TRUE,
    stMotionStage:=Main.M8,
    sCoating1Name:='Si',
    sCoating2Name:='B4C',
    fbArbiter:=GVL_PMPS.g_fbArbiter2,
    fbFFHWO:=GVL_PMPS.g_FastFaultOutput2,
    sPmpsDeviceName:='MR2K4:KBO',
    sTransitionKey:= 'MR2K4:KBO-TRANSITION'
);

// MR3K4 Coating States with PMPS
fbMR3K4_Coating_States(
    bEnable := TRUE,
    stMotionStage:=Main.M12,
    bVerticalCoating:=FALSE,
    sCoating1Name:='Si',
    sCoating2Name:='B4C',
    fbArbiter:=GVL_PMPS.g_fbArbiter2,
    fbFFHWO:=GVL_PMPS.g_FastFaultOutput2,
    sPmpsDeviceName:='MR3K4:KBO',
    sTransitionKey:= 'MR3K4:KBO-TRANSITION'
);

END_PROGRAM
Related: