DUTs ---- GVLs ---- GVL_COM_Buffers ^^^^^^^^^^^^^^^ :: VAR_GLOBAL // M1K2 Serial_RXBuffer_M1K2 : ComBuffer; Serial_TXBuffer_M1K2 : ComBuffer; END_VAR GVL_M1K1 ^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL // Pitch Mechanism:\ // Currently unused {attribute 'TcLinkTo' := '.diEncCnt:=TIIB[EL5042_M1K2_Pitch]^FB Inputs Channel 1^Position'} M1K1_Pitch : HOMS_PitchMechanism := (ReqPosLimHi := 24681, ReqPosLimLo := 24321, diEncPosLimHi := 10139808, diEncPosLimLo := 9950984); // Set to 50 urad before hard limits tripped during SAT END_VAR GVL_M1K1_BENDER_Constants ^^^^^^^^^^^^^^^^^^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL CONSTANT // Encoder reference values in counts = nm nM1K1bendUS_ENC_REF : ULINT := 21458400; nM1K1bendDS_ENC_REF : ULINT := 21225900; END_VAR GVL_M1K1_BENDER_RTD ^^^^^^^^^^^^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL // M1K1 US RTDs {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1US1_M1K1US2]^RTD Inputs Channel 1^Value'} nM1K1US_RTD_1 AT %I* : INT; {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1US1_M1K1US2]^RTD Inputs Channel 2^Value'} nM1K1US_RTD_2 AT %I* : INT; {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1US3_M1K1DS1]^RTD Inputs Channel 1^Value'} nM1K1US_RTD_3 AT %I* : INT; // M1K1 DS RTDs {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1US3_M1K1DS1]^RTD Inputs Channel 2^Value'} nM1K1DS_RTD_1 AT %I* : INT; {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1DS2_M1K1DS3]^RTD Inputs Channel 1^Value'} nM1K1DS_RTD_2 AT %I* : INT; {attribute 'TcLinkTo' := 'TIIB[EL3202-0010_M1K1DS2_M1K1DS3]^RTD Inputs Channel 2^Value'} nM1K1DS_RTD_3 AT %I* : INT; END_VAR GVL_M1K1_Constants ^^^^^^^^^^^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL CONSTANT // Encoder reference values in counts = nm // Enc reference values from Axilon FAT nYUP_ENC_REF : ULINT := 13008545; nYDWN_ENC_REF : ULINT := 11158257; nXUP_ENC_REF : ULINT := 19649910; nXDWN_ENC_REF : ULINT := 19609100; END_VAR GVL_M1K2 ^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL // Pitch Mechanism: // Currently Unused {attribute 'TcLinkTo' := '.diEncCnt:=TIIB[EL5042_M1K2_Pitch]^FB Inputs Channel 1^Position'} M1K2_Pitch : HOMS_PitchMechanism := (ReqPosLimHi := 200, ReqPosLimLo := -30, diEncPosLimHi := 10121210, diEncPosLimLo := 10004610); // Set to 50 urad before hard limits tripped during SAT END_VAR GVL_M1K2_Constants ^^^^^^^^^^^^^^^^^^ :: {attribute 'qualified_only'} VAR_GLOBAL CONSTANT // Encoder reference values in counts = nm // Enc reference values after alignment 3-13-20 nYLEFT_ENC_REF : ULINT := 96270560; nYRIGHT_ENC_REF : ULINT := 98728200; nXUP_ENC_REF : ULINT := 19847200; nXDWN_ENC_REF : ULINT := 21007520; // Lever arm for Yright/Yleft -> Roll about Z-axis fRollLeverArm_um : REAL := 717000; // lever arm for Yright/Yleft axes in um END_VAR GVL_SerialIO ^^^^^^^^^^^^ :: VAR_GLOBAL //Better have your inputs and outputs! // M1K2 Serial_stComIn_M1K2 AT %I* : EL6inData22B (*KL6inData22B*); Serial_stComOut_M1K2 AT %Q* : EL6outData22B (*KL6outData22B*); END_VAR Main ^^^^ :: 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 *) (*MR1K2*) // Motors {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K2_Yleft]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K2_Yleft]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH:MMS:YLEFT '} M1 : DUT_MotionStage := (fVelocity:=100.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K2 Yleft fbMotionStage_m1 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K2_Yright]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K2_Yright]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH:MMS:YRIGHT '} M2 : DUT_MotionStage := (fVelocity:=100.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K2 Yright fbMotionStage_m2 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K2_Xup]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K2_Xup]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH:MMS:XUP '} M3 : DUT_MotionStage := (fVelocity:=150.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K2 Xup fbMotionStage_m3 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K2_Xdwn]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K2_Xdwn]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH:MMS:XDWN '} M4 : DUT_MotionStage := (fVelocity:=150.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K2 Xdwn fbMotionStage_m4 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K2_PitchCoarse]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K2_PitchCoarse]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH:MMS:PITCH '} M5 : DUT_MotionStage := (fVelocity:=30.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K2 Pitch Stepper (*SP1K1-Mono*) {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:M_PI '} {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[m_pi_m]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[m_pi_m]^STM Status^Status^Digital input 2'} M6: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=200.0, bPowerSelf:=True); // M_PI, urad {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:G_PI '} {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[g_pi_m]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[g_pi_m]^STM Status^Status^Digital input 2'} M7: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=200.0, bPowerSelf:=True); // G_PI, urad {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:M_H '} {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[m_h_m]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[m_h_m]^STM Status^Status^Digital input 2'} M8: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=500.0, bPowerSelf:=True); // M_H, um {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:G_H '} {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[g_h_m]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[g_h_m]^STM Status^Status^Digital input 2'} M9: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=1000.0, bPowerSelf:=True); // G_H, um {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:SD_V '} {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[s_io_m]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[s_io_m]^STM Status^Status^Digital input 2'} M10: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=500.0, bPowerSelf:=True); // SD_V, um {attribute 'pytmc' := ' pv: SP1K1:MONO:MMS:SD_ROT '} // no limits on this motion M11: DUT_MotionStage:=(nEnableMode:=ENUM_StageEnableMode.ALWAYS, fVelocity:=500.0, bPowerSelf:=True); // SD_R, urad (*MR1K1*) // Should move before MR1K2 and re-number each motor, lots of work // need to fix Axis IDs for IOC to work // For now just want functional PLC project // Motors {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K1_Yup]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K1_Ydwn]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:YUP '} M12 : DUT_MotionStage := (fVelocity:=100.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K1 Yup fbMotionStage_m12 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K1_Ydwn]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K1_Ydwn]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:YDWN '} M13 : DUT_MotionStage := (fVelocity:=100.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K1 Ydwn fbMotionStage_m13 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K1_Xup]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K1_Xup]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:XUP '} M14 : DUT_MotionStage := (fVelocity:=150.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K1 Xup fbMotionStage_m14 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K1_Xdwn]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K1_Xdwn]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:XDWN '} M15 : DUT_MotionStage := (fVelocity:=150.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K1 Xdwn fbMotionStage_m15 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable:=TIIB[EL7047_M1K1_PitchCoarse]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7047_M1K1_PitchCoarse]^STM Status^Status^Digital input 2'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:PITCH '} M16 : DUT_MotionStage := (fVelocity:=30.0, nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=True); // M1K1 Pitch Stepper {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M1K1_BEND_US]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7041_M1K1_BEND_US]^STM Status^Status^Digital input 2; .nRawEncoderULINT := TIIB[EL5042_M1K1_BEND_USDS]^FB Inputs Channel 1^Position'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:US '} M17 : DUT_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE); //MR1K1 US BEND fbMotionStage_m17 : FB_MotionStage; {attribute 'TcLinkTo' := '.bLimitForwardEnable :=TIIB[EL7041_M1K1_BEND_DS]^STM Status^Status^Digital input 1; .bLimitBackwardEnable:=TIIB[EL7041_M1K1_BEND_DS]^STM Status^Status^Digital input 2; .nRawEncoderULINT := TIIB[EL5042_M1K1_BEND_USDS]^FB Inputs Channel 2^Position'} {attribute 'pytmc' := ' pv: MR1K1:BEND:MMS:DS '} M18 : DUT_MotionStage := (nEnableMode:=ENUM_StageEnableMode.ALWAYS, bPowerSelf:=TRUE); //MR1K1 DS BEND fbMotionStage_m18 : FB_MotionStage; END_VAR POUs ---- P_Serial_Com ^^^^^^^^^^^^ :: PROGRAM P_Serial_Com VAR fbSerialLineControl_EL6001_M1K2: 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_M1K2(Mode:= SERIALLINEMODE_EL6_22B (*SERIALLINEMODE_KL6_22B_STANDARD*), pComIn:= ADR(Serial_stComIn_M1K2), pComOut:=ADR(Serial_stComOut_M1K2), SizeComIn:= SIZEOF(Serial_stComIn_M1K2), TxBuffer:= Serial_TXBuffer_M1K2, RxBuffer:= Serial_RXBuffer_M1K2, Error=> , ErrorID=> ); END_PROGRAM PiezoSerial ^^^^^^^^^^^ :: PROGRAM PiezoSerial VAR //PI Serial fbE621SerialDriver_M1K2 : FB_PI_E621_SerialDriver; rtInitParams_M1K2 : R_TRIG; tonTimeoutRst_M1K2 : TON := (PT:=T#2S); //For timeout reset END_VAR //Piezo E-621 /////////////////////// fbE621SerialDriver_M1K2.i_xExecute := TRUE; fbE621SerialDriver_M1K2.i_xExecute R= fbE621SerialDriver_M1K2.q_xDone; fbE621SerialDriver_M1K2(iq_stPiezoAxis:= GVL_M1K2.M1K2_Pitch.Piezo, iq_stSerialRXBuffer:= Serial_RXBuffer_M1K2, iq_stSerialTXBuffer:= Serial_TXBuffer_M1K2); END_PROGRAM PRG_1_PlcTask ^^^^^^^^^^^^^ :: PROGRAM PRG_1_PlcTask VAR END_VAR PRG_MR1K1_BEND(); PRG_MR1K1_BEND_BENDER(); PRG_MR1K2_SWITCH(); PRG_SP1K1_MONO(); END_PROGRAM PRG_MR1K1_BEND ^^^^^^^^^^^^^^ :: PROGRAM PRG_MR1K1_BEND VAR {attribute 'TcLinkTo' := '.fbRunHOMS.bSTOEnable1:=TIIB[EL1004_M1K1_STO]^Channel 1^Input; .fbRunHOMS.bSTOEnable2:=TIIB[EL1004_M1K1_STO]^Channel 2^Input; .fbRunHOMS.stYupEnc.Count:=TIIB[EL5042_M1K1_Yupdwn]^FB Inputs Channel 1^Position; .fbRunHOMS.stYdwnEnc.Count:=TIIB[EL5042_M1K1_Yupdwn]^FB Inputs Channel 2^Position; .fbRunHOMS.stXupEnc.Count:=TIIB[EL5042_M1K1_Xupdwn]^FB Inputs Channel 1^Position; .fbRunHOMS.stXdwnEnc.Count:=TIIB[EL5042_M1K1_Xupdwn]^FB Inputs Channel 2^Position'} {attribute 'pytmc' := ' pv: MR1K1:BEND '} M1K1 : DUT_HOMS; // Encoder Arrays/RMS Watch: {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:Y '} fbYRMSErrorM1K1 : FB_RMSWatch; fMaxYRMSErrorM1K1 : LREAL; fMinYRMSErrorM1K1 : LREAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:X '} fbXRMSErrorM1K1 : FB_RMSWatch; fMaxXRMSErrorM1K1 : LREAL; fMinXRMSErrorM1K1 : LREAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:PITCH '} fbPitchRMSErrorM1K1 : FB_RMSWatch; fMaxPitchRMSErrorM1K1 : LREAL; fMinPitchRMSErrorM1K1 : LREAL; // Pitch Control fbM1K1PitchControl : FB_PitchControl; bM1K1PitchDone : BOOL; bM1K1PitchBusy : BOOL; // 3-15-20 Having issues with pitch control on new Axilon systems (M1K2) // Should test on this one to see if common to all new systems // Using stepper only for now fbMotionStage_m16 : FB_MotionStage; // Raw Encoder Counts {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:YUP:CNT field: EGU cnt io: i '} nEncCntYupM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:YDWN:CNT field: EGU cnt io: i '} nEncCntYdwnM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:XUP:CNT field: EGU cnt io: i '} nEncCntXupM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:XDWN:CNT field: EGU cnt io: i '} nEncCntXdwnM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:PITCH:CNT field: EGU cnt io: i '} nEncCntPitchM1K1 : UDINT; // Encoder Reference Values {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:YUP:REF field: EGU cnt io: i '} nEncRefYupM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:YDWN:REF field: EGU cnt io: i '} nEncRefYdwnM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:XUP:REF field: EGU cnt io: i '} nEncRefXupM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:XDWN:REF field: EGU cnt io: i '} nEncRefXdwnM1K1 : UDINT; {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:PITCH:REF field: EGU cnt io: i '} nEncRefPitchM1K1 : UDINT; mcReadParameterPitchM1K1 : MC_ReadParameter; fEncRefPitchM1K1_urad : LREAL; // Current Pitch encoder offset in urad // Common fEncLeverArm_mm : LREAL := 410.0; END_VAR // M1K1 M1K1.fbRunHOMS(stYup:=M12, stYdwn:=M13, stXup:=M14, stXdwn:=M15, stPitch:=M16, nYupEncRef:=GVL_M1K1_Constants.nYUP_ENC_REF, nYdwnEncRef:=GVL_M1K1_Constants.nYDWN_ENC_REF, nXupEncRef:=GVL_M1K1_Constants.nXUP_ENC_REF, nXdwnEncRef:=GVL_M1K1_Constants.nXDWN_ENC_REF, bExecuteCoupleY:=M1K1.bExecuteCoupleY, bExecuteCoupleX:=M1K1.bExecuteCoupleX, bExecuteDecoupleY:=M1K1.bExecuteDecoupleY, bExecuteDecoupleX:=M1K1.bExecuteDecoupleX, bGantryAlreadyCoupledY=>M1K1.bGantryAlreadyCoupledY, bGantryAlreadyCoupledX=>M1K1.bGantryAlreadyCoupledX, nCurrGantryY=>M1K1.nCurrGantryY, nCurrGantryX=>M1K1.nCurrGantryX); // No slave motion through Epics M13.bExecute := FALSE; // M1K1-Ydwn M15.bExecute := FALSE; // M1K1-Xdwn // Convert nCurrGantry to um (smaller number) to read out in epics M1K1.fCurrGantryY_um := LINT_TO_REAL(M1K1.nCurrGantryY) / 1000.0; M1K1.fCurrGantryX_um := LINT_TO_REAL(M1K1.nCurrGantryX) / 1000.0; // FB_MotionStage's for non-piezo axes fbMotionStage_m12(stMotionStage:=M12); fbMotionStage_m13(stMotionStage:=M13); fbMotionStage_m14(stMotionStage:=M14); fbMotionStage_m15(stMotionStage:=M15); // Calculate Pitch RMS Error: fbYRMSErrorM1K1(stMotionStage:=M12, fMaxRMSError=>fMaxYRMSErrorM1K1, fMinRMSError=>fMinYRMSErrorM1K1); fbXRMSErrorM1K1(stMotionStage:=M14, fMaxRMSError=>fMaxXRMSErrorM1K1, fMinRMSError=>fMinXRMSErrorM1K1); fbPitchRMSErrorM1K1(stMotionStage:=M16, fMaxRMSError=>fMaxPitchRMSErrorM1K1, fMinRMSError=>fMinPitchRMSErrorM1K1); (* // Pitch Control fbM1K1PitchControl(Pitch:=GVL_M1K1.M1K1_Pitch, Stepper:=M16, lrCurrentSetpoint:=M16.fPosition, q_bDone=>bM1K1PitchDone, q_bBusy=>bM1K1PitchBusy); // When STO hit, need to reset SP IF NOT M16.bHardwareEnable THEN M16.fPosition := M16.stAxisStatus.fActPosition; END_IF *) // 3-15-20: Having issues with pitch control on new Axilon systems, should test here fbMotionStage_m16(stMotionStage:=M16); // Raw Encoder Counts For Epics nEncCntYupM1K1 := ULINT_TO_UDINT(M1K1.fbRunHOMS.stYupEnc.Count); nEncCntYdwnM1K1 := ULINT_TO_UDINT(M1K1.fbRunHOMS.stYdwnEnc.Count); nEncCntXupM1K1 := ULINT_TO_UDINT(M1K1.fbRunHOMS.stXupEnc.Count); nEncCntXdwnM1K1 := ULINT_TO_UDINT(M1K1.fbRunHOMS.stXdwnEnc.Count); nEncCntPitchM1K1 := LINT_TO_UDINT(GVL_M1K1.M1K1_Pitch.diEncCnt); // Encoder Reference Values For Epics nEncRefYupM1K1 := ULINT_TO_UDINT(GVL_M1K1_Constants.nYUP_ENC_REF); nEncRefYdwnM1K1 := ULINT_TO_UDINT(GVL_M1K1_Constants.nYDWN_ENC_REF); nEncRefXupM1K1 := ULINT_TO_UDINT(GVL_M1K1_Constants.nXUP_ENC_REF); nEncRefXdwnM1K1 := ULINT_TO_UDINT(GVL_M1K1_Constants.nXDWN_ENC_REF); mcReadParameterPitchM1K1(Axis:=M16.Axis, Enable:=TRUE, ParameterNumber:=MC_AxisParameter.AxisEncoderOffset, ReadMode:=READMODE_CYCLIC, Value=>fEncRefPitchM1K1_urad); nEncRefPitchM1K1 := LREAL_TO_UDINT(ABS(fEncRefPitchM1K1_urad) * fEncLeverArm_mm); END_PROGRAM PRG_MR1K1_BEND_BENDER ^^^^^^^^^^^^^^^^^^^^^ :: PROGRAM PRG_MR1K1_BEND_BENDER VAR // Encoder Arrays/RMS Watch: //MR1K1 US BENDER ENC RMS {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:US '} fbBendUSRMSErrorM1K1 : FB_RMSWatch; fMaxBendUSRMSErrorM1K1 : LREAL; fMinBendUSRMSErrorM1K1 : LREAL; //MR1K1 DS BENDER ENC RMS {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:DS '} fbBendDSRMSErrorM1K1 : FB_RMSWatch; fMaxBendDSRMSErrorM1K1 : LREAL; fMinBendDSRMSErrorM1K1 : LREAL; // Encoder Reference Values //MR1K1 BEND US ENC REF {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:US:REF field: EGU cnt io: i '} nEncRefBendUSM1K1 : UDINT; //MR1K1 BEND DS ENC REF {attribute 'pytmc' := ' pv: MR1K1:BEND:ENC:DS:REF field: EGU cnt io: i '} nEncRefBendDSM1K1 : UDINT; //Emergency Stop for MR1K1 {attribute 'TcLinkTo' := TIIB[EL1004_M1K1_BENDER_STO]^Channel 1^Input'} M1K1BENDbSTOEnable1 AT %I* : BOOL; {attribute 'TcLinkTo' := TIIB[EL1004_M1K1_BENDER_STO]^Channel 2^Input'} M1K1BENDbSTOEnable2 AT %I* : BOOL; // MR1K1 Bender RTDs // MR1K1 US RTDs {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:US:1 field: ASLO 0.01 field: EGU C io: i '} fM1K1US_RTD_1 : REAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:US:2 field: ASLO 0.01 field: EGU C io: i '} fM1K1US_RTD_2 : REAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:US:3 field: ASLO 0.01 field: EGU C io: i '} fM1K1US_RTD_3 : REAL; // M1K1 DS RTDs {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:DS:1 field: ASLO 0.01 field: EGU C io: i '} fM1K1DS_RTD_1 : REAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:DS:2 field: ASLO 0.01 field: EGU C io: i '} fM1K1DS_RTD_2 : REAL; {attribute 'pytmc' := ' pv: MR1K1:BEND:RTD:DS:3 field: ASLO 0.01 field: EGU C io: i '} fM1K1DS_RTD_3 : REAL; // RTD error bit bM1K1US_RTD_1_Err AT %I*: BOOL; bM1K1US_RTD_2_Err AT %I*: BOOL; bM1K1US_RTD_3_Err AT %I*: BOOL; bM1K1DS_RTD_1_Err AT %I*: BOOL; bM1K1DS_RTD_2_Err AT %I*: BOOL; bM1K1DS_RTD_3_Err AT %I*: BOOL; // Logging fbLogHandler : FB_LogHandler; fbBendUSRMSErrorMR1K1: INT; END_VAR //FB_Motion stages for MR1K1 Benders //MR1K1 BEND fbMotionStage_m17(stMotionStage:=M17); fbMotionStage_m18(stMotionStage:=M18); // Calculate Pitch RMS Error for MR1K1 Benders: //MR1K1 US BENDER ENC RMS fbBendUSRMSErrorM1K1(stMotionStage:=M17, fMaxRMSError=>fMaxBendUSRMSErrorM1K1, fMinRMSError=>fMinBendUSRMSErrorM1K1); //MR1K1 DS BENDER ENC RMS fbBendDSRMSErrorM1K1(stMotionStage:=M18, fMaxRMSError=>fMaxBendDSRMSErrorM1K1, fMinRMSError=>fMinBendDSRMSErrorM1K1); //STO for MR1K1 Benders M17.bHardwareEnable := M1K1BENDbSTOEnable1 AND M1K1BENDbSTOEnable2; M18.bHardwareEnable := M1K1BENDbSTOEnable1 AND M1K1BENDbSTOEnable2; //Encoder reference positions for MR1K1 nEncRefBendUSM1K1 := ULINT_TO_UDINT(GVL_M1K1_BENDER_Constants.nM1K1bendUS_ENC_REF); nEncRefBendDSM1K1 := ULINT_TO_UDINT(GVL_M1K1_BENDER_Constants.nM1K1bendDS_ENC_REF); // MR1K1 Bender RTDs fM1K1US_RTD_1 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1US_RTD_1); fM1K1US_RTD_2 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1US_RTD_2); fM1K1US_RTD_3 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1US_RTD_3); fM1K1DS_RTD_1 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1DS_RTD_1); fM1K1DS_RTD_2 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1DS_RTD_2); fM1K1DS_RTD_3 := INT_TO_REAL(GVL_M1K1_BENDER_RTD.nM1K1DS_RTD_3); // RTD not connected if T=0 bM1K1US_RTD_1_Err := fM1K1US_RTD_1 = 0; bM1K1US_RTD_2_Err := fM1K1DS_RTD_2 = 0; bM1K1US_RTD_3_Err := fM1K1US_RTD_3 = 0; bM1K1DS_RTD_1_Err := fM1K1DS_RTD_1 = 0; bM1K1DS_RTD_2_Err := fM1K1DS_RTD_2 = 0; bM1K1DS_RTD_3_Err := fM1K1DS_RTD_3 = 0; // M1K1 Bender RTD interlocks M17.bHardwareEnable R= fM1K1US_RTD_1 > 10000 OR bM1K1US_RTD_1_Err; M18.bHardwareEnable R= fM1K1DS_RTD_1 > 10000 OR bM1K1DS_RTD_1_Err; END_PROGRAM PRG_MR1K2_SWITCH ^^^^^^^^^^^^^^^^ :: PROGRAM PRG_MR1K2_SWITCH VAR {attribute 'TcLinkTo' := '.fbRunHOMS.bSTOEnable1:=TIIB[EL1004_M1K2_STO]^Channel 1^Input; .fbRunHOMS.bSTOEnable2:=TIIB[EL1004_M1K2_STO]^Channel 2^Input; .fbRunHOMS.stYupEnc.Count:=TIIB[EL5042_M1K2_Yleftright]^FB Inputs Channel 1^Position; .fbRunHOMS.stYdwnEnc.Count:=TIIB[EL5042_M1K2_Yleftright]^FB Inputs Channel 2^Position; .fbRunHOMS.stXupEnc.Count:=TIIB[EL5042_M1K2_Xupdwn]^FB Inputs Channel 1^Position; .fbRunHOMS.stXdwnEnc.Count:=TIIB[EL5042_M1K2_Xupdwn]^FB Inputs Channel 2^Position'} {attribute 'pytmc' := ' pv: MR1K2:SWITCH '} M1K2 : DUT_HOMS; // Encoder Arrays/RMS Watch: {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:Y '} fbYRMSErrorM1K2 : FB_RMSWatch; fMaxYRMSErrorM1K2 : LREAL; fMinYRMSErrorM1K2 : LREAL; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:X '} fbXRMSErrorM1K2 : FB_RMSWatch; fMaxXRMSErrorM1K2 : LREAL; fMinXRMSErrorM1K2 : LREAL; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:PITCH '} fbPitchRMSErrorM1K2 : FB_RMSWatch; fMaxPitchRMSErrorM1K2 : LREAL; fMinPitchRMSErrorM1K2 : LREAL; // Pitch Control fbM1K2PitchControl : FB_PitchControl; bM1K2PitchDone : BOOL; bM1K2PitchBusy : BOOL; // 3-15-20 Having issues with pitch control on new Axilon systems // Using stepper only for now fbMotionStage_m5 : FB_MotionStage; // Roll (Rotation about Z axis) induced from Ygantry: {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:ROLL field: EGU urad io: i '} fYRoll_urad : LREAL; // Roll about Z axis in urad // Raw Encoder Counts {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:YLEFT:CNT field: EGU cnt io: i '} nEncCntYleftM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:YRIGHT:CNT field: EGU cnt io: i '} nEncCntYrightM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:XUP:CNT field: EGU cnt io: i '} nEncCntXupM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:XDWN:CNT field: EGU cnt io: i '} nEncCntXdwnM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:PITCH:CNT field: EGU cnt io: i '} nEncCntPitchM1K2 : UDINT; // Encoder Reference Values {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:YLEFT:REF field: EGU cnt io: i '} nEncRefYleftM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:YRIGHT:REF field: EGU cnt io: i '} nEncRefYrightM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:XUP:REF field: EGU cnt io: i '} nEncRefXupM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:XDWN:REF field: EGU cnt io: i '} nEncRefXdwnM1K2 : UDINT; {attribute 'pytmc' := ' pv: MR1K2:SWITCH:ENC:PITCH:REF field: EGU cnt io: i '} nEncRefPitchM1K2 : UDINT; mcReadParameterPitchM1K2 : MC_ReadParameter; fEncRefPitchM1K2_urad : LREAL; // Current Pitch encoder offset in urad // Common fEncLeverArm_mm : LREAL := 391.0; END_VAR // M1K2 M1K2.fbRunHOMS(stYup:=M1, stYdwn:=M2, stXup:=M3, stXdwn:=M4, stPitch:=M5, nYupEncRef:=GVL_M1K2_Constants.nYLEFT_ENC_REF, nYdwnEncRef:=GVL_M1K2_Constants.nYRIGHT_ENC_REF, nXupEncRef:=GVL_M1K2_Constants.nXUP_ENC_REF, nXdwnEncRef:=GVL_M1K2_Constants.nXDWN_ENC_REF, bExecuteCoupleY:=M1K2.bExecuteCoupleY, bExecuteCoupleX:=M1K2.bExecuteCoupleX, bExecuteDecoupleY:=M1K2.bExecuteDecoupleY, bExecuteDecoupleX:=M1K2.bExecuteDecoupleX, bGantryAlreadyCoupledY=>M1K2.bGantryAlreadyCoupledY, bGantryAlreadyCoupledX=>M1K2.bGantryAlreadyCoupledX, nCurrGantryY=>M1K2.nCurrGantryY, nCurrGantryX=>M1K2.nCurrGantryX); // No slave motion through Epics M2.bExecute := FALSE; // M1K2-Yright M4.bExecute := FALSE; // M1K2-Xdwn // Convert nCurrGantry to um (smaller number) to read out in epics M1K2.fCurrGantryY_um := LINT_TO_REAL(M1K2.nCurrGantryY) / 1000.0; M1K2.fCurrGantryX_um := LINT_TO_REAL(M1K2.nCurrGantryX) / 1000.0; fYRoll_urad := (REAL_TO_LREAL(ATAN(M1K2.fCurrGantryY_um / GVL_M1K2_Constants.fRollLeverArm_um))) * EXPT(10, 6); // FB_MotionStage's for non-piezo axes fbMotionStage_m1(stMotionStage:=M1); fbMotionStage_m2(stMotionStage:=M2); fbMotionStage_m3(stMotionStage:=M3); fbMotionStage_m4(stMotionStage:=M4); // Calculate Pitch RMS Error: fbYRMSErrorM1K2(stMotionStage:=M1, fMaxRMSError=>fMaxYRMSErrorM1K2, fMinRMSError=>fMinYRMSErrorM1K2); fbXRMSErrorM1K2(stMotionStage:=M3, fMaxRMSError=>fMaxXRMSErrorM1K2, fMinRMSError=>fMinXRMSErrorM1K2); fbPitchRMSErrorM1K2(stMotionStage:=M5, fMaxRMSError=>fMaxPitchRMSErrorM1K2, fMinRMSError=>fMinPitchRMSErrorM1K2); (* // Pitch Control fbM1K2PitchControl(Pitch:=GVL_M1K2.M1K2_Pitch, Stepper:=M5, lrCurrentSetpoint:=M5.fPosition, q_bDone=>bM1K2PitchDone, q_bBusy=>bM1K2PitchBusy); // When STO hit, need to reset SP IF NOT M5.bHardwareEnable THEN M5.fPosition := M5.stAxisStatus.fActPosition; END_IF *) // 3-15-20: Having issues with pitch control on new Axilon systems fbMotionStage_m5(stMotionStage:=M5); // Raw Encoder Counts For Epics nEncCntYleftM1K2 := ULINT_TO_UDINT(M1K2.fbRunHOMS.stYupEnc.Count); nEncCntYrightM1K2 := ULINT_TO_UDINT(M1K2.fbRunHOMS.stYdwnEnc.Count); nEncCntXupM1K2 := ULINT_TO_UDINT(M1K2.fbRunHOMS.stXupEnc.Count); nEncCntXdwnM1K2 := ULINT_TO_UDINT(M1K2.fbRunHOMS.stXdwnEnc.Count); nEncCntPitchM1K2 := LINT_TO_UDINT(GVL_M1K2.M1K2_Pitch.diEncCnt); // Encoder Reference Values For Epics nEncRefYleftM1K2 := ULINT_TO_UDINT(GVL_M1K2_Constants.nYLEFT_ENC_REF); nEncRefYrightM1K2 := ULINT_TO_UDINT(GVL_M1K2_Constants.nYRIGHT_ENC_REF); nEncRefXupM1K2 := ULINT_TO_UDINT(GVL_M1K2_Constants.nXUP_ENC_REF); nEncRefXdwnM1K2 := ULINT_TO_UDINT(GVL_M1K2_Constants.nXDWN_ENC_REF); mcReadParameterPitchM1K2(Axis:=M5.Axis, Enable:=TRUE, ParameterNumber:=MC_AxisParameter.AxisEncoderOffset, ReadMode:=READMODE_CYCLIC, Value=>fEncRefPitchM1K2_urad); nEncRefPitchM1K2 := LREAL_TO_UDINT(ABS(fEncRefPitchM1K2_urad) * fEncLeverArm_mm); END_PROGRAM PRG_SP1K1_MONO ^^^^^^^^^^^^^^ :: PROGRAM PRG_SP1K1_MONO VAR // Where is the STO {attribute 'TcLinkTo' := 'TIID^Device 1 (EtherCAT)^Term 4 (EK1200)^di^Channel 1^Input'} sto AT %I*: BOOL; fbMotionStage_m_pi :FB_MotionStage; fbMotionStage_g_pi :FB_MotionStage; fbMotionStage_m_h :FB_MotionStage; fbMotionStage_g_h :FB_MotionStage; fbMotionStage_s_r :FB_MotionStage; fbMotionStage_s_io :FB_MotionStage; {attribute 'TcLinkTo' := '.Count:=TIIB[m_pi_up_dwn_e]^FB Inputs Channel 1^Position'} mpi_upe AT %I*: ST_RenishawAbsEnc:=(ref:=0); {attribute 'TcLinkTo' := '.Count:=TIIB[g_pi_up_dwn_e]^FB Inputs Channel 1^Position'} gpi_upe AT %I*: ST_RenishawAbsEnc:=(ref:=0); {attribute 'pytmc' := ' pv: SP1K1:MONO:ENC:M_PI:02 io: o '} mpi_upeurad: LREAL; {attribute 'pytmc' := ' pv:SP1K1:MONO:ENC:G_PI:02 io: o '} gpi_upeurad: LREAL; (*Flow Switches*) {attribute 'TcLinkTo' := 'TIID^Device 4 (EtherCAT)^GM^Term 16 (EL3054)^AI Standard Channel 1^Value'} flow_1 AT %I*: INT; {attribute 'TcLinkTo' := 'TIID^Device 4 (EtherCAT)^GM^Term 16 (EL3054)^AI Standard Channel 2^Value'} flow_2 AT %I*: INT; {attribute 'TcLinkTo' := 'TIID^Device 4 (EtherCAT)^GM^Term 16 (EL3054)^AI Standard Channel 3^Value'} pres_1 AT %I*: INT; {attribute 'pytmc' := ' pv: SP1K1:MONO:FSW:01 io: o '} FLOW1 : LREAL := 0.00; {attribute 'pytmc' := ' pv: SP1K1:MONO:FSW:02 io: o '} FLOW2 : LREAL := 0.00; {attribute 'pytmc' := ' pv: SP1K1:MONO:P1 io: o '} PRES1 : LREAL := 0.00; (*RTDs*) {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:01 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 1^Value; .bError := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 1^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E13]^RTD Inputs Channel 1^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 1^Status^Overrange'} RTD1 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:02 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 2^Value; .bError := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 2^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E13]^RTD Inputs Channel 2^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E13]^RTD Inputs Channel 2^Status^Overrange'} RTD2 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:03 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 1^Value; .bError := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 1^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E14]^RTD Inputs Channel 1^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 1^Status^Overrange'} RTD3 :FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:04 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 2^Value; .bError := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 2^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E14]^RTD Inputs Channel 2^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E14]^RTD Inputs Channel 2^Status^Overrange'} RTD4 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:05 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 1^Value; .bError := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 1^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E15]^RTD Inputs Channel 1^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 1^Status^Overrange'} RTD5 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:06 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 2^Value; .bError := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 2^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E15]^RTD Inputs Channel 2^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E15]^RTD Inputs Channel 2^Status^Overrange'} RTD6 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:07 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 1^Value; .bError := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 1^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E16]^RTD Inputs Channel 1^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 1^Status^Overrange'} RTD7 : FB_TempSensor; {attribute 'pytmc' := ' pv: SP1K1:MONO:RTD:08 io: o '} {attribute 'TcLinkTo' := '.iRaw := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 2^Value; .bError := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 2^Status^Error; .bUnderrange := TIIBSP1K1-EL3202-E16]^RTD Inputs Channel 2^Status^Underrange; .bOverrange := TIIB[SP1K1-EL3202-E16]^RTD Inputs Channel 2^Status^Overrange'} RTD8 :FB_TempSensor; //////////TODO {attribute 'pytmc' := ' pv: GM:PITCH:fipi_read io: i '} fipi_read: LREAL; {attribute 'pytmc' := ' pv: GM:PITCH:fipi_set io: o '} fipi_set: LREAL; END_VAR // SP1K1-MONO M6.bHardwareEnable := sto; M7.bHardwareEnable := sto; M8.bHardwareEnable := sto; M9.bHardwareEnable := sto; M10.bHardwareEnable := sto; M11.bHardwareEnable := sto; fbMotionStage_m_pi (stMotionStage:=M6); fbMotionStage_g_pi (stMotionStage:=M7); fbMotionStage_m_h (stMotionStage:=M8); fbMotionStage_g_h (stMotionStage:=M9); fbMotionStage_s_io (stMotionStage:=M10); fbMotionStage_s_r (stMotionStage:=M11); //S_R with no hardware limit switched M11.bAllBackwardEnable := TRUE; M11.bLimitForwardEnable := TRUE; mpi_upeurad := ULINT_TO_LREAL(mpi_upe.Count)*0.004505; gpi_upeurad := ULINT_TO_LREAL(gpi_upe.Count)*0.0066667; (*Flow Switches and RTDs*) FLOW1 := INT_TO_LREAL(flow_1)/32767*4; FLOW2 := INT_TO_LREAL(flow_2)/32767*4; PRES1 := INT_TO_LREAL(pres_1)/32767*2; RTD1(); RTD2(); RTD3(); RTD4(); RTD5(); RTD6(); RTD7(); RTD8(); END_PROGRAM