diff --git a/lcls-twincat-motion/Library/DUTs/DS402/ENUM_AxisStates.TcDUT b/lcls-twincat-motion/Library/DUTs/DS402/ENUM_AxisStates.TcDUT deleted file mode 100644 index 669ab7e1..00000000 --- a/lcls-twincat-motion/Library/DUTs/DS402/ENUM_AxisStates.TcDUT +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/lcls-twincat-motion/Library/DUTs/DS402/E_MoveDoneCause.TcDUT b/lcls-twincat-motion/Library/DUTs/DS402/E_MoveDoneCause.TcDUT new file mode 100644 index 00000000..fbec8742 --- /dev/null +++ b/lcls-twincat-motion/Library/DUTs/DS402/E_MoveDoneCause.TcDUT @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/DUTs/DS402/E_StartupState.TcDUT b/lcls-twincat-motion/Library/DUTs/DS402/E_StartupState.TcDUT new file mode 100644 index 00000000..8705337e --- /dev/null +++ b/lcls-twincat-motion/Library/DUTs/DS402/E_StartupState.TcDUT @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/DUTs/DS402/ST_ChannelState.TcDUT b/lcls-twincat-motion/Library/DUTs/DS402/ST_ChannelState.TcDUT new file mode 100644 index 00000000..41a7eb4c --- /dev/null +++ b/lcls-twincat-motion/Library/DUTs/DS402/ST_ChannelState.TcDUT @@ -0,0 +1,142 @@ + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/DUTs/DS402/ST_DS402Drive.TcDUT b/lcls-twincat-motion/Library/DUTs/DS402/ST_DS402Drive.TcDUT index ddfe7c3c..8e479312 100644 --- a/lcls-twincat-motion/Library/DUTs/DS402/ST_DS402Drive.TcDUT +++ b/lcls-twincat-motion/Library/DUTs/DS402/ST_DS402Drive.TcDUT @@ -4,16 +4,16 @@ + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/DUTs/E_EpicsMotorCmd.TcDUT b/lcls-twincat-motion/Library/DUTs/E_EpicsMotorCmd.TcDUT index 5054791b..48663950 100644 --- a/lcls-twincat-motion/Library/DUTs/E_EpicsMotorCmd.TcDUT +++ b/lcls-twincat-motion/Library/DUTs/E_EpicsMotorCmd.TcDUT @@ -12,9 +12,10 @@ TYPE E_EpicsMotorCmd : MOVE_ABSOLUTE := 3, MOVE_MODULO := 4, HOME := 10, - GEAR := 30 + GEAR := 30, + CALIBRATE:=40 ); END_TYPE ]]> - \ No newline at end of file + diff --git a/lcls-twincat-motion/Library/Library.plcproj b/lcls-twincat-motion/Library/Library.plcproj index 5418dbb1..9c54c057 100644 --- a/lcls-twincat-motion/Library/Library.plcproj +++ b/lcls-twincat-motion/Library/Library.plcproj @@ -18,7 +18,7 @@ SLAC false lcls-twincat-motion - 0.0.0 + 1.0.0 false false false @@ -32,6 +32,7 @@ + @@ -109,9 +110,6 @@ Code - - Code - Code @@ -130,18 +128,30 @@ Code + + Code + Code Code + + Code + + + Code + Code Code + + Code + Code @@ -157,9 +167,6 @@ Code - - Code - Code @@ -271,10 +278,40 @@ Code - + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + Code - + Code diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/FB_MotionStageE727.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/FB_MotionStageE727.TcPOU index 181146fd..65ba00db 100644 --- a/lcls-twincat-motion/Library/POUs/Motion/DS402/FB_MotionStageE727.TcPOU +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/FB_MotionStageE727.TcPOU @@ -6,7 +6,7 @@ set bServo PV to true, fort open loop step mode bServo must be cleared *) {attribute 'call_after_init'} -FUNCTION_BLOCK FB_MotionStageE727 IMPLEMENTS I_DS402GenericDrive +FUNCTION_BLOCK FB_MotionStageE727 VAR {attribute 'no_copy'} stMotionStage : REFERENCE TO ST_MotionStage; @@ -173,7 +173,7 @@ IF bInit THEN stMotionStage.nMotionAxisID := stMotionStage.Axis.NcToPlc.AxisId; (* Clear drive error/wraning condition, in open loop mode this will trigger a correct startup for procedure *) - stDS402Drive.nDS402DriveControl := 128; + stDS402Drive.nDriveControl := 128; // fist cycle reading of NC paramters bExecParamsRead := TRUE; bInit := FALSE; @@ -279,7 +279,7 @@ bExecMove:=bLocalExec AND NOT bExecHome; rtExec(CLK:=bLocalExec); IF rtExec.Q THEN // Release previous interruption if any - stDS402Drive.nDS402DriveControl.8 := FALSE; + stDS402Drive.nDriveControl.8 := FALSE; stMotionStage.bDone := FALSE; END_IF @@ -307,7 +307,7 @@ IF stMotionStage.bReset THEN stMotionStage.sCustomErrorMessage:=''; (*Manual Drive reset*) IF bDS402ManualEnabled THEN - stDS402Drive.nDS402DriveControl := 128; + stDS402Drive.nDriveControl := 128; ELSE bLocalReset := TRUE; END_IF @@ -336,10 +336,10 @@ CASE nCommandLocal OF MoveAbsolute(); (*IN CSP mode the drive control word is update via the NC Manual step mode and Homing will override this *) - stDS402Drive.nDS402DriveControl := stDS402Drive.nDS402DriveControlNC; + stDS402Drive.nDriveControl := stDS402Drive.nDriveControlNC; E_EpicsMotorCmd.HOME: (*DS402 Manual Homing*) - Home(); + Home(Enable:=TRUE); END_CASE stMotionStage.bBusy := bHomeBusy OR fbMcMoveAbsolute.Busy; @@ -514,7 +514,9 @@ THIS^.eModule := eModule; E_DS402OpMode.HOME) THEN stDS402Drive.nModeOfOperation := E_DS402OpMode.HOME; - stDS402Drive.nDS402DriveControl := 128; + stDS402Drive.nDriveControl := 128; // clear previous operational from switching away from this mode. bOperational := FALSE; bCSPModeEnabled := FALSE; @@ -692,7 +694,7 @@ IF rtUserExec.Q AND stMotionStage.bHomeCmd THEN ELSIF rtUserExec.Q THEN IF (stDS402Drive.nModeOfOperationDisplay<>E_DS402OpMode.CSP) THEN stDS402Drive.nModeOfOperation := E_DS402OpMode.CSP; - stDS402Drive.nDS402DriveControl := 128; + stDS402Drive.nDriveControl := 128; bHomeModeEnabled := FALSE; bManualTransition := FALSE; ELSE @@ -942,24 +944,6 @@ stMotionStage.fPosDiff:=stMotionStage.Axis.NcToPlc.PosDiff; ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 THEN - stDS402Drive.nDS402DriveControl := 128; // clear errors, prepare for startup - bExecParamsRead := TRUE; // trigger NC param read on first scan - bSystemInit := FALSE; - END_IF -END_IF -(* Check for the plc shortcut commands - Used for testing or to circumvent motor record issues*) -rtMoveCmdShortcut(CLK:=stMotionStage.bMoveCmd); -rtHomeCmdShortcut(CLK:=stMotionStage.bHomeCmd); - -(* Execute on rising edge*) -IF rtMoveCmdShortcut.Q AND NOT stMotionStage.bExecute THEN - stMotionStage.bExecute:=TRUE; - stMotionStage.nCommand := E_EpicsMotorCmd.MOVE_ABSOLUTE; - bEnPosLag := bRecentEnPosLagStatus; - fParameterValue := BOOL_TO_LREAL(bRecentEnPosLagStatus); - -ELSIF rtHomeCmdShortcut.Q AND NOT stMotionStage.bExecute THEN - stMotionStage.bExecute:= NOT ( stMotionStage.nCmdData=E_EpicsHomeCmd.ABSOLUTE_SET ) - OR NOT ( stMotionStage.nCmdData=E_EpicsHomeCmd.NONE); - stMotionStage.nCommand:=E_EpicsMotorCmd.HOME; - (* Automatically fill the correct nCmdData for homing*) - stMotionStage.nCmdData:=stMotionStage.nHomingMode; - (* Positional lag is not evaluated by E727 during homing, but NC does evaluated - the condition which will lead to error as the lag is significant during homing - disable the NC lag check and reenable it after homing is done - *) - IF stMotionStage.stAxisParameters.bCtrlEnablePosDiffControl.0 THEN - bRecentEnPosLagStatus := stMotionStage.stAxisParameters.bCtrlEnablePosDiffControl.0; - bEnPosLag := TRUE; - fParameterValue := 0; - END_IF - -END_IF - -(* entry point for local and EPICS main execs *) -rtUserExec(CLK:=stMotionStage.bExecute); -(* if a Move/Home Goal is comfirmed and there is no persistant - error conditions, then we have a valid move request.*) -bNewMoveReq S= NOT stMotionStage.bBusy AND rtUserExec.Q AND NOT stMotionStage.bError; -(* this Move request is valid till an error occurs or the currently move is done *) -bNewMoveReq R= NOT stMotionStage.bExecute OR stMotionStage.bError; -bPrepareDisable R= bNewMoveReq; -rtNewMoveReq(CLK:=bNewMoveReq); -(* Moves are automatically allowed if no safety hooks. - Otherwise, some other code will set this.*) -stMotionStage.bSafetyReady S= stMotionStage.bPowerSelf; -(* Set the proper command for the request move; - if bservo not set, manual step moves will be performed *) -IF rtUserExec.Q THEN - // Transfer nCommand and nCmdData to local copies at rising edge of bExecute (avoid issues if nCommand or nCmdData are changed during a command) - nCmdDataLocal:=stMotionStage.nCmdData; - nCommandLocal:=stMotionStage.nCommand; - IF NOT stMotionStage.bHomeCmd THEN - IF NOT bServo THEN - (* Open Loop Step Mode *) - stMotionStage.nCommand:=E_EpicsMotorCmd.JOG; - nCommandLocal := E_EpicsMotorCmd.JOG; - END_IF - - (* attempting to move an axis without homing first? *) - IF stMotionStage.nHomingMode <> E_EpicsHomeCmd.NONE AND NOT stMotionStage.bHomed THEN - (* one can just set bHome here even though no homing was done?*) - stMotionStage.sErrorMessage:='Axis homing mode set, but homing routine pending'; - END_IF - END_IF -END_IF - -(* Set the drive in the correct operating mode. based on requested move command! - NB: bservo must set for close loop motion -*) -ModeOperation(); - -(* NB: This is the only tested mode of operation so far. also aligned - piezo drive position holding feature -*) -rtEnableMode(CLK:=(stMotionStage.nEnableMode = E_StageEnableMode.DURING_MOTION)); -(* Handle auto-enable timing *) -CASE stMotionStage.nEnableMode OF - (* Not recommended, not tested *) - E_StageEnableMode.ALWAYS: - stMotionStage.bEnable:=TRUE; - E_StageEnableMode.DURING_MOTION: - IF rtEnableMode.Q THEN - stMotionStage.bEnable := FALSE; - END_IF - IF rtNewMoveReq.Q THEN - (* override ongoing holding.*) - bPositionHold := FALSE; - tonHoldTime.IN:=FALSE; - (*MC block are not compatible with open loop Motion - thus we wathc for correct close loop modes to use NC features *) - stMotionStage.bEnable S= stMotionStage.bSafetyReady; - bLastHoltTimeOut := FALSE; - bStop:=FALSE; - END_IF -END_CASE -(* Interlock mainly react on internal limit conditions inthe ove direction. - MCS2 drive will go into error state when an internal limit is hit *) -Interlock(); - -IF bCSPModeEnabled THEN - (*CSP using TwinCAT NC*) - bLocalExec:= NOT stMotionStage.bError AND stMotionStage.bExecute AND stMotionStage.bAllEnable AND stMotionStage.bEnableDone AND stMotionStage.bSafetyReady AND bServo; -ELSIF bHomeModeEnabled THEN - bLocalExec:= NOT stMotionStage.bError AND stMotionStage.bExecute AND stMotionStage.bAllEnable AND bOperational AND stMotionStage.bSafetyReady; -ELSIF bStepModeEnabled THEN - (*Manual, i.e Homing using DS402*) - bLocalExec:= NOT stMotionStage.bError AND stMotionStage.bExecute AND stMotionStage.bAllEnable AND bOperational AND stMotionStage.bSafetyReady AND NOT bServo; -ELSE - bLocalExec:= FALSE; -END_IF -bExecHome:=bLocalExec AND stMotionStage.nCommand = 10; -bExecMove:=bLocalExec AND NOT bExecHome; - -(* When we start, set the busy/done appropriately - NB: CLose loop control using NC *) -rtExec(CLK:=bLocalExec); -IF rtExec.Q THEN - // Release previous interruption if any - stDS402Drive.nDS402DriveControl.8 := FALSE; - stMotionStage.bDone := FALSE; -END_IF - -(* updated axis status - Not needed in manual mode *) -IF NOT bDS402ManualEnabled THEN - stMotionStage.Axis.ReadStatus(); -END_IF - -(* Get a definitive bEnabled reading - NB: use only in close loop mode, NC feature needed*) -CASE stMotionStage.Axis.Status.MotionState OF - (* We are not enabled if there is an issue*) - MC_AXISSTATE_UNDEFINED, MC_AXISSTATE_DISABLED, MC_AXISSTATE_ERRORSTOP: - stMotionStage.bEnableDone := FALSE; - ELSE - stMotionStage.bEnableDone := TRUE; -END_CASE -// -IF stMotionStage.bReset THEN - stMotionStage.bExecute:=FALSE; - stMotionStage.bError := FALSE; - stMotionStage.nErrorId := 0; - stMotionStage.sErrorMessage:=''; - stMotionStage.sCustomErrorMessage:=''; - (*Manual Drive reset*) - IF bDS402ManualEnabled THEN - // Clear error/warning - bManualTransition:=FALSE; - IF NOT stMotionStage.bBusy THEN - stDS402Drive.nDS402DriveControl := 128; - ELSE - // Power off the drive - stMotionStage.bEnable:=FALSE; - stDS402Drive.nDS402DriveControl := 6; - END_IF - ELSE - bLocalReset := TRUE; - END_IF - stMotionStage.bReset:=FALSE; -END_IF - -// Halt is always a user stop during motion -bStop S= NOT bLocalExec AND NOT bLocalReset AND ((bHomeBusy AND (nCommandLocal=10)) - OR(fbMcMoveAbsolute.Busy AND (nCommandLocal=3)) OR (bStepMoveBusy AND (nCommandLocal=0))); - -//auto handle position lag monitoring, disable during homing. -WriteParameterNC( Execute:=bEnPosLag, - ParameterNumber:=MC_AxisParameter.AxisEnPositionLagMonitoring, - ParameterValue:=fParameterValue); - -(* Requested commands processing *) -CASE nCommandLocal OF - E_EpicsMotorCmd.MOVE_ABSOLUTE: - (*NC CSP Move Handling*) - Reset(); - Power(); - Halt(); - (*Wait for drive to be in the correct mode after a request was validated *) - bCommandMoveAbsolute := bExecMove AND fbMcPower.Status AND bCSPModeEnabled; - MoveAbsolute(); - (*IN CSP mode the drive control word is update via the NC - Manual step mode and Homing will override this *) - stDS402Drive.nDS402DriveControl := stDS402Drive.nDS402DriveControlNC; - E_EpicsMotorCmd.HOME: - (*DS402 Manual Homing*) - Home(); - E_EpicsMotorCmd.JOG: - (* Set drive to correct operating mode, ensure motion params are correct - following a validated open loop mode request. - NB: bservo must be off. a PV is provided for that - *) - StepMove(Enable:=bExecMove AND bStepModeparamsSetDone AND NOT bWrongParameter); -END_CASE - -stMotionStage.bBusy := bHomeBusy OR fbMcMoveAbsolute.Busy OR bStepMoveBusy; - -(* Check done moving via user stop, limit hit, Target Position reached, or from homing.*) -rtMoveDone(CLK:=fbMcMoveAbsolute.Done); -rtStepMoveDone(CLK:=bStepMoveDone); -rtHomeDone(CLK:=bHomeDone); -rtStopDone(CLK:=fbMcHalt.Done); -rtAborted(CLK:=bHomeAborted OR bStepMoveAborted); -IF rtAborted.Q OR rtStopDone.Q OR rtMoveDone.Q OR rtHomeDone.Q OR rtStepMoveDone.Q THEN - IF NOT stMotionStage.bDone THEN - stMotionStage.bHomed := bHomeDone; - stMotionStage.bExecute:=FALSE; - bCommandMoveAbsolute := FALSE; - stMotionStage.bDone := fbMcMoveAbsolute.Done OR bHomeDone OR bStepMoveDone; - IF bDS402ManualEnabled THEN - (*Restore Postional lag monitoring*) - bEnPosLag := FALSE; - END_IF - (* Release the internal limit override*) - bLimOverride := FALSE; - bHomeAborted := FALSE; - bStepMoveAborted := FALSE; - END_IF -END_IF - -(* hold stage in place before timeout *) -tonHoldTime(PT:=UDINT_TO_TIME(nHoldTime)); -IF tonHoldTime.Q THEN - bPositionHold := FALSE; - tonHoldTime.IN:=FALSE; - bLastHoltTimeOut := TRUE; - (* open loop mode is not compatible with MC_Power, MC _Halt...*) - (* Manual power disabling is required*) - IF bDS402ManualEnabled THEN - stDS402Drive.nDS402DriveControl := 6; - END_IF - stMotionStage.bEnable:=FALSE; - bStop := FALSE; -END_IF - -(* updated axis status - Not needed in manual mode *) -IF NOT bDS402ManualEnabled THEN - stMotionStage.Axis.ReadStatus(); -END_IF -// -ftExec(CLK:=stMotionStage.bExecute); -(*Handle auto-disable timing*) -bPrepareDisable S= stMotionStage.nEnableMode = E_StageEnableMode.DURING_MOTION AND ftExec.Q; -(* Delay the disable until we reach standstill *) -IF bPrepareDisable AND stMotionStage.Axis.Status.StandStill THEN - IF NOT bPositionHold THEN - bPrepareDisable:=FALSE; - stMotionStage.bEnable:=FALSE; - END_IF -END_IF - -(* update encoder value and calibrated position*) -ScaleEncRawValue(); -(*Drive parameters*) -ExposedParameters(Enable:=TRUE, tRefreshDelay:=T#2S); -(* Open Loop Motion paramters Update*) -UpdateServoOffMotionParams(Enable:=stMotionStage.bAxisParamsInit AND NOT stMotionStage.bBusy AND bStepModeEnabled); -(*Sync NC setting to drive settings*) -UpdateDriveMonitoringParams(Enable:=stMotionStage.bAxisParamsInit AND NOT stMotionStage.bBusy); -(* Save and restore as long as not an absolute encoder*) -PersistParameters( Enable:=stMotionStage.nHomingMode <> E_EpicsHomeCmd.NONE); -(*Restore encoder value at initialization*) -RestoreMotionParams(Enable:=stMotionStage.nHomingMode <> E_EpicsHomeCmd.NONE); - -(*EPICS Motor record Update*) -UpdateEpicsStatus(); -(* - Error from functions and Nc. The error will send to EPICS interface based on predifined - priority: axis, power, backlash, absoluteMove, etc... -*) -IF fbMcPower.Error AND fbMcPower.Active THEN - stMotionStage.bError:=fbMcPower.Error; - stMotionStage.nErrorId:=fbMcPower.ErrorID; -ELSIF fbMcMoveAbsolute.Error THEN - stMotionStage.bError:=fbMcMoveAbsolute.Error; - stMotionStage.nErrorId:=fbMcMoveAbsolute.ErrorID; -ELSIF fbMcHalt.Error AND fbMcHalt.Active THEN - stMotionStage.bError:=fbMcHalt.Error; - stMotionStage.nErrorId:=fbMcHalt.ErrorID; -ELSIF fbMcReset.Error THEN - stMotionStage.bError:=fbMcReset.Error; - stMotionStage.nErrorId:=fbMcReset.ErrorID; -ELSIF fbMcWriteParameter.Error THEN - stMotionStage.bError:=fbMcWriteParameter.Error; - stMotionStage.nErrorId:=fbMcWriteParameter.ErrorID; -ELSIF fbMcReadParams.Error AND NOT stMotionStage.bBusy THEN - stMotionStage.bError:=fbMcReadParams.Error; - stMotionStage.nErrorId:=fbMcReadParams.ErrorID; -ELSE - IF stMotionStage.bBusy THEN - stMotionStage.sErrorMessage := ''; - stMotionStage.sCustomErrorMessage := ''; - END_IF -END_IF; - -(*Double function, prioritize NC error otherwise read drive channel error code*) -ReadDriveCodes(); - -IF stMotionStage.sCustomErrorMessage <> '' - AND stMotionStage.sErrorMessage = '' THEN - stMotionStage.sErrorMessage := stMotionStage.sCustomErrorMessage; -END_IF - -(*Clear motion flag when error occurs*) -IF stMotionStage.bError THEN - stMotionStage.bBusy := FALSE; - stMotionStage.bDone := FALSE; - stMotionStage.bEnable := FALSE; -END_IF - -(* We've got the rising edge clear this flags.*) -stMotionStage.bMoveCmd:=FALSE; -stMotionStage.bHomeCmd:=FALSE; -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0; -bNegativeDirection:=stMotionStage.bBusy AND stMotionStage.fPosDiff < 0; - -// For SmartAct MCS2 these limit are range and enstop limits. however a single bit in the status is used -// bLimOverride : act as an override after limit was hit to allow reverse movement -stMotionStage.bLimitForwardEnable := bLimOverride OR NOT( bPositiveDirection AND stDS402Drive.stDS402DriveStatus.InternalLimitActive ); -stMotionStage.bLimitBackwardEnable := bLimOverride OR NOT( bNegativeDirection AND stDS402Drive.stDS402DriveStatus.InternalLimitActive ); - -// use falling trigger to avoid spaming sErrorMessage -ftForwardEnabled(CLK:=stMotionStage.bLimitForwardEnable); -ftBackwardEnabled(CLK:=stMotionStage.bLimitBackwardEnable); - -IF NOT bHomeBusy AND ftForwardEnabled.Q THEN - // Not an error, just a warning - stMotionStage.sCustomErrorMessage:='Cannot move past positive limit.'; - IF NOT bStepModeEnabled THEN - bLimOverride := TRUE; - bStop := TRUE; - END_IF -END_IF - -IF NOT bHomeBusy AND ftBackwardEnabled.Q THEN - // Not an error, just a warning - stMotionStage.sCustomErrorMessage:='Cannot move past Negative limit.'; - IF NOT bStepModeEnabled THEN - bLimOverride := TRUE; - bStop := TRUE; - END_IF -END_IF - -IF NOT stMotionStage.bError AND stMotionStage.bExecute AND NOT stMotionStage.bUserEnable THEN - stMotionStage.bError := TRUE; - stMotionStage.nErrorId := 1; - stMotionStage.sCustomErrorMessage := 'Move requested, but user enable is disabled!'; -END_IF - -// Update all enable booleans -SetEnables();]]> - - - - - - E_DS402OpMode.HOME) THEN - stDS402Drive.nModeOfOperation := E_DS402OpMode.HOME; - IF stDS402Drive.nDS402DriveControl.4 THEN - stDS402Drive.nDS402DriveControl := 15; - ELSE - stDS402Drive.nDS402DriveControl := 128; - END_IF - bManualTransition := TRUE; - // clear previous operational from switching away from this mode. - bOperational := FALSE; - bStepModeEnabled := FALSE; - bCSPModeEnabled := FALSE; - ELSE - bHomeModeEnabled := TRUE; - END_IF -ELSIF rtUserExec.Q AND bServo THEN - IF (stDS402Drive.nModeOfOperationDisplay<>E_DS402OpMode.CSP) THEN - stDS402Drive.nModeOfOperation := E_DS402OpMode.CSP; - IF stDS402Drive.nDS402DriveControl.4 THEN - stDS402Drive.nDS402DriveControl := 15; - ELSE - stDS402Drive.nDS402DriveControl := 128; - END_IF - bManualTransition := FALSE; - bHomeModeEnabled := FALSE; - bStepModeEnabled := FALSE; - ELSE - bCSPModeEnabled := TRUE; - END_IF -ELSIF rtUserExec.Q AND NOT bServo THEN - IF (stDS402Drive.nModeOfOperationDisplay<>E_DS402OpMode.MCS2_OL_STEP_MODE) THEN - stDS402Drive.nModeOfOperation := E_DS402OpMode.MCS2_OL_STEP_MODE; - stDS402Drive.nDS402DriveControl := 128; - // clear previous operational from switching away from this mode. - bOperational := FALSE; - bCSPModeEnabled := FALSE; - bHomeModeEnabled := FALSE; - ELSE - bStepModeEnabled := TRUE; - END_IF - bManualTransition := TRUE; -END_IF - -bDS402ManualEnabled :=bHomeModeEnabled OR bStepModeEnabled; -(*Handle correct startup procedure for manual move*) -StateMachine(Enable:=1);]]> - - - - - - - - - - - - = 16#4400 AND stMotionStage.Axis.Status.ErrorID <= 16#44FF ); - // Do not save if we're currently loading or if there is an encoder error - IF NOT bRestoreLoad AND NOT bEncError AND NOT bRestoreWaitRetry THEN - fSavedPosition := stMotionStage.Axis.NcToPlc.ActPos; - // This persistent variable lets us check if anything was saved - // It will be TRUE at startup if we have saved values - bSaved := TRUE; - (* - use this with a timer of a change threshold on the fActPosition - to trigger a save from this PLC program. otherwise this will be a spamming - persistence, filling up the disk. - *) - //iPersistentDataStorage.TriggerWriteOfPersistentData := bSaveEnabled; - END_IF -END_IF]]> - - - - - - - - - - - - - - - - - - 0 THEN - stMotionStage.nErrorId := nPiezoErrorCode; - END_IF - stMotionStage.sErrorMessage := F_MotionErrorCodeLookup(nErrorId:=stMotionStage.nErrorId); - fbLogError( stMotionStage:=stMotionStage, bEnable:=stMotionStage.bError); -END_IF - -]]> - - - - - - - - - - - - = nMaxRetries THEN - // Alert the user that something has gone wrong - stMotionStage.bError := TRUE; - stMotionStage.nErrorId := nLatchError; - stMotionStage.sCustomErrorMessage := 'Error loading previously saved position.'; - ELSE - // Reset the FB for the next retry - fbSetPos( Axis:=stMotionStage.Axis, Execute:=bRestoreLoad, Position:=fSavedPosition); - // Try again - bRestoreWaitRetry := TRUE; - END_IF - ELSE - IF NOT bRestoreDone THEN - stMotionStage.fPosition := fSavedPosition; - END_IF - bRestoreDone := TRUE; - END_IF - - tonRestoreRetry( IN := bRestoreWaitRetry, PT := T#100MS); - bRestoreLoad S= tonRestoreRetry.Q; - bRestoreWaitRetry R= tonRestoreRetry.Q; -END_IF]]> - - - - - - - - - - - - 0 THEN - stMotionStage.nEncoderCount:=DINT_TO_UDINT(ABS(stMotionStage.nRawEncoderDINT)); -ELSE - stMotionStage.nEncoderCount:=0; -END_IF - -// calibrated encoder readback -IF NOT bStepModeEnabled THEN - // Close loop NC - fMeasuredPos:=stMotionStage.Axis.NcToPlc.ActPos; - fMeasuredVelo :=stMotionStage.Axis.NcToPlc.ActVelo; - fMeasuredAcc := stMotionStage.Axis.NcToPlc.ActAcc; - stMotionStage.fPosDiff:=stMotionStage.Axis.NcToPlc.PosDiff; -ELSE - fMeasuredPos:=DINT_TO_REAL(stMotionStage.nRawEncoderDINT) * MAX(stMotionStage.stAxisParameters.fEncScaleFactorInternal, fScalingFactor); - stMotionStage.fPosDiff:=stMotionStage.fPosition - fMeasuredPos; - // NB: Not actual in open loop - fMeasuredVelo :=stMotionStage.fVelocity; - fMeasuredAcc := stMotionStage.fAcceleration; -END_IF - -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nRecentFErrWin) - ); - fbSetSoftLimMin( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanSoftLimitIdx, - nSubIndex := 1, - pSrcBuf := ADR(nSoftLimMin), - cbBufLen := SIZEOF(nSoftLimMin), - bExecute := NOT stMotionStage.bBusy AND (nSoftLimMin <> nRecentSoftLimMin) - ); - fbSetSoftLimMax( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanSoftLimitIdx, - nSubIndex := 2, - pSrcBuf := ADR(nSoftLimMax), - cbBufLen := SIZEOF(nSoftLimMax), - bExecute := NOT stMotionStage.bBusy AND (nSoftLimMax <> nRecentSoftLimMax) - ); - fbSetHomeVeloFast( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanHomeVeloIdx, - nSubIndex := 1, - pSrcBuf := ADR(nHomeVeloFast), - cbBufLen := SIZEOF(nHomeVeloFast), - bExecute := NOT stMotionStage.bBusy AND (nHomeVeloFast <> nRecentHomeVeloFast) - ); - fbSetHomeVeloSlow( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanHomeVeloIdx, - nSubIndex := 2, - pSrcBuf := ADR(nHomeVeloSlow), - cbBufLen := SIZEOF(nHomeVeloSlow), - bExecute := NOT stMotionStage.bBusy AND (nHomeVeloSlow <> nRecentHomeVeloSlow) - ); - fbSetHomeAcc( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanhomeAccIdx, - nSubIndex := 0, - pSrcBuf := ADR(nHomeAcc), - cbBufLen := SIZEOF(nHomeAcc), - bExecute := NOT stMotionStage.bBusy AND (nHomeAcc <> nRecentHomeAcc) - ); - - fbSetHomeOffs( - sNetId := THIS^.stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanHomeOffsIdx, - nSubIndex := 0, - pSrcBuf := ADR(nHomeOffset), - cbBufLen := SIZEOF(nHomeOffset), - bExecute := NOT stMotionStage.bBusy AND (nHomeOffset <> nRecentHomeOffset) - ); - - ftFErrWinSetDone(CLK:=fbSetFErrorWin.bBusy); - ftSoftLimMaxSetDone(CLK:=fbSetSoftLimMax.bBusy); - ftSoftLimMinSetDone(CLK:=fbSetSoftLimMin.bBusy); - ftHomeVeloFastSetDone(CLK:=fbSetHomeVeloFast.bBusy); - ftHomeVeloSlowSetDone(CLK:=fbSetHomeVeloFast.bBusy); - ftHomeAccSetDone(CLK:=fbSetHomeAcc.bBusy); - ftHomeOffsSetDone(CLK:=fbSetHomeOffs.bBusy); - - IF ftFErrWinSetDone.Q OR ftSoftLimMaxSetDone.Q - OR ftSoftLimMinSetDone.Q OR ftHomeVeloFastSetDone.Q - OR ftHomeAccSetDone.Q OR ftHomeOffsSetDone.Q OR ftHomeVeloSlowSetDone.Q THEN - IF fbSetFErrorWin.bError THEN - stMotionStage.bError := fbSetFErrorWin.bError; - stMotionStage.nErrorId := fbSetFErrorWin.nErrId; - ELSIF fbSetSoftLimMin.bError THEN - stMotionStage.bError := fbSetSoftLimMin.bError; - stMotionStage.nErrorId := fbSetSoftLimMin.nErrId; - ELSIF fbSetSoftLimMax.bError THEN - stMotionStage.bError := fbSetSoftLimMax.bError; - stMotionStage.nErrorId := fbSetSoftLimMax.nErrId; - ELSIF fbSetHomeVeloFast.bError THEN - stMotionStage.bError := fbSetHomeVeloFast.bError; - stMotionStage.nErrorId := fbSetHomeVeloFast.nErrId; - ELSIF fbSetHomeVeloSlow.bError THEN - stMotionStage.bError := fbSetHomeVeloSlow.bError; - stMotionStage.nErrorId := fbSetHomeVeloSlow.nErrId; - ELSIF fbSetHomeAcc.bError THEN - stMotionStage.bError := fbSetHomeAcc.bError; - stMotionStage.nErrorId := fbSetHomeAcc.nErrId; - ELSIF fbSetHomeOffs.bError THEN - stMotionStage.bError := fbSetHomeOffs.bError; - stMotionStage.nErrorId := fbSetHomeOffs.nErrId; - ELSE - nRecentFErrWin := nScaledFErrWin; - nRecentSoftLimMax := nSoftLimMax; - nRecentSoftLimMin := nSoftLimMin; - nRecentHomeVeloFast :=nHomeVeloFast; - nRecentHomeVeloSlow := nHomeVeloSlow; - nRecentHomeAcc := nHomeAcc; - nRecentHomeOffset := nHomeOffs; - END_IF - fbSetFErrorWin.bExecute := FALSE; - fbSetSoftLimMin.bExecute := FALSE; - fbSetSoftLimMax.bExecute := FALSE; - fbSetHomeVeloFast.bExecute := FALSE; - fbSetHomeVeloSlow.bExecute := FALSE; - fbSetHomeAcc.bExecute := FALSE; - fbSetHomeOffs.bExecute := FALSE; - END_IF -END_IF]]> - - - - - - - - - - - - nRecentSteps) - ); - fbSetStepAmp( - sNetId := stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanStepAmpIdx, - nSubIndex := 0, - pSrcBuf := ADR(nScalededStepAmp), - cbBufLen := SIZEOF(nChanStepAmp), - bExecute := NOT stMotionStage.bBusy AND (nScalededStepAmp <> nRecentStepAmp) - ); - fbSetStepFreq( - sNetId := stMotionStage.stAxisParameters.sAmsNetId, - nSlaveAddr := stDS402Drive.nSlaveAddr, - nIndex := nChanStepFreqIdx, - nSubIndex := 0, - pSrcBuf := ADR(nScaledStepFreq), - cbBufLen := SIZEOF(nChanStepFreq), - bExecute := NOT stMotionStage.bBusy AND (nScaledStepFreq <> nRecentStepFreq) - ); - ftStepUpdateDone(CLK:=fbSetSteps.bBusy); - ftStepAmpUpdateDone(CLK:=fbSetStepAmp.bBusy); - ftStepFreqUpdateDone(CLK:=fbSetStepFreq.bBusy); - - bStepModeparamsSetDone R= fbSetSteps.bBusy OR fbSetStepAmp.bBusy OR fbSetStepFreq.bBusy; - IF ftStepUpdateDone.Q - OR ftStepAmpUpdateDone.Q - OR ftStepFreqUpdateDone.Q THEN - IF fbSetSteps.bError THEN - stMotionStage.bError := fbSetSteps.bError; - stMotionStage.nErrorId := fbSetSteps.nErrId; - ELSIF fbSetStepFreq.bError THEN - stMotionStage.bError := fbSetStepFreq.bError; - stMotionStage.nErrorId := fbSetStepFreq.nErrId; - ELSIF fbSetStepAmp.bError THEN - stMotionStage.bError := fbSetStepAmp.bError; - stMotionStage.nErrorId := fbSetStepAmp.nErrId; - ELSE - nRecentSteps := nScalededSteps; - nRecentStepAmp := nScalededStepAmp; - nRecentStepFreq := nScaledStepFreq; - bStepModeparamsSetDone S= TRUE; - END_IF - fbSetSteps.bExecute := FALSE; - fbSetStepFreq.bExecute := FALSE; - fbSetStepAmp.bExecute := FALSE; - END_IF -END_IF -]]> - - - - - - - - - - \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/I_DS402GenericDrive.TcIO b/lcls-twincat-motion/Library/POUs/Motion/DS402/I_DS402GenericDrive.TcIO deleted file mode 100644 index 3d833b38..00000000 --- a/lcls-twincat-motion/Library/POUs/Motion/DS402/I_DS402GenericDrive.TcIO +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Calibrate.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Calibrate.TcPOU new file mode 100644 index 00000000..d6c41e15 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Calibrate.TcPOU @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2DriveManager.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2DriveManager.TcPOU new file mode 100644 index 00000000..d57f426d --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2DriveManager.TcPOU @@ -0,0 +1,220 @@ + + + + + + E_DS402OpMode.CSP); + +// DS402 startup sequence at boot or after fault (until operational) +IF bStartupActive AND bDS402Manual THEN + CASE eStartupState OF + 0: // CLEAR CONTROL WORD + stDS402Drive.nDriveControl := 0; + tonStartupStep(IN := TRUE); + IF tonStartupStep.Q THEN + tonStartupStep(IN := FALSE); + eStartupState := 1; + END_IF + 1: // RESET FAULT + stDS402Drive.nDriveControl := 16#80; + tonStartupStep(IN := TRUE); + IF tonStartupStep.Q THEN + tonStartupStep(IN := FALSE); + eStartupState := 2; + END_IF + 2: // SHUTDOWN + stDS402Drive.nDriveControl := 6; + tonStartupStep(IN := TRUE); + IF tonStartupStep.Q THEN + tonStartupStep(IN := FALSE); + eStartupState := 3; + END_IF + 3: // SWITCH ON + stDS402Drive.nDriveControl := 7; + tonStartupStep(IN := TRUE); + IF tonStartupStep.Q THEN + tonStartupStep(IN := FALSE); + eStartupState := 4; + END_IF + 4: // ENABLE OPERATION + stDS402Drive.nDriveControl := 15; + tonStartupStep(IN := TRUE); + IF tonStartupStep.Q THEN + tonStartupStep(IN := FALSE); + eStartupState := 5; + END_IF + 5: // WAIT FOR OPERATIONAL + IF bOperational THEN + eStartupState := 0; + bStartupActive := FALSE; + END_IF + ELSE + eStartupState := 0; + END_CASE +ELSE + // regular operation/control logic (only when startup is finished and drive is operational) + IF bOperational THEN + CASE stDS402Drive.nModeOfOperationDisplay OF + E_DS402OpMode.CSP: + bCSPModeEnabled := TRUE; + bHomeModeEnabled := FALSE; + bStepModeEnabled := FALSE; + bCalibrationModeEnabled := FALSE; + E_DS402OpMode.HOME: + bCSPModeEnabled := FALSE; + bHomeModeEnabled := TRUE; + bStepModeEnabled := FALSE; + bCalibrationModeEnabled := FALSE; + E_DS402OpMode.MCS2_OL_STEP_MODE: + bCSPModeEnabled := FALSE; + bHomeModeEnabled := FALSE; + bStepModeEnabled := TRUE; + bCalibrationModeEnabled := FALSE; + E_DS402OpMode.MCS2_CALIBRATION: + bCSPModeEnabled := FALSE; + bHomeModeEnabled := FALSE; + bStepModeEnabled := FALSE; + bCalibrationModeEnabled := TRUE; + ELSE + bCSPModeEnabled := FALSE; + bHomeModeEnabled := FALSE; + bStepModeEnabled := FALSE; + bCalibrationModeEnabled := FALSE; + END_CASE + ELSE + bCSPModeEnabled := FALSE; + bHomeModeEnabled := FALSE; + bStepModeEnabled := FALSE; + bCalibrationModeEnabled := FALSE; + END_IF + + // Mode switch/request evaluator + IF bUserExec AND ( + stMCS2ChanParameter.bStepMoveCmd + OR stMotionStage.bHomeCmd + OR stMCS2ChanParameter.bCalibrationCmd + OR stMotionStage.bMoveCmd ) THEN + + // Which mode is requested? + IF stMCS2ChanParameter.bStepMoveCmd THEN + eRequestedManualMode := E_DS402OpMode.MCS2_OL_STEP_MODE; + ELSIF stMotionStage.bHomeCmd THEN + eRequestedManualMode := E_DS402OpMode.HOME; + ELSIF stMCS2ChanParameter.bCalibrationCmd THEN + eRequestedManualMode := E_DS402OpMode.MCS2_CALIBRATION; + ELSIF stMotionStage.bMoveCmd THEN + eRequestedManualMode := E_DS402OpMode.CSP; + END_IF + + // -- Check if we are already in the requested mode -- + IF stDS402Drive.nModeOfOperationDisplay = eRequestedManualMode THEN + IF bOperational THEN + bPendingManualModeSwitch := FALSE; + bManualTransition := FALSE; + ELSE + // Already in requested mode but NOT operational: (re-)trigger DS402 startup sequence! + bStartupActive := TRUE; + eStartupState := 0; // Start DS402 boot up + bPendingManualModeSwitch := FALSE; + bManualTransition := FALSE; + END_IF + ELSE + IF eRequestedManualMode = E_DS402OpMode.CSP THEN + stDS402Drive.nModeOfOperation := E_DS402OpMode.CSP; + bPendingManualModeSwitch := FALSE; + ELSE + stDS402Drive.nDriveControl.4 := FALSE; + stDS402Drive.nModeOfOperation := eRequestedManualMode; + bPendingManualModeSwitch := TRUE; + END_IF + END_IF + END_IF + + // === Pending manual mode switch === + IF bPendingManualModeSwitch THEN + IF stDS402Drive.nModeOfOperationDisplay = eRequestedManualMode THEN + IF bOperational THEN + // correct mode AND operational; just set the manual transition flag + bManualTransition := TRUE; + bPendingManualModeSwitch := FALSE; + ELSE + // correct mode, BUT NOT operational: initiate DS402 startup boot sequence + bStartupActive := TRUE; + eStartupState := 0; + bPendingManualModeSwitch := FALSE; + END_IF + END_IF + END_IF + +END_IF + +tonStartupStep( PT := T#80MS);]]> + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Home.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Home.TcPOU new file mode 100644 index 00000000..fbc4a5d6 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2Home.TcPOU @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2ReadParams.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2ReadParams.TcPOU new file mode 100644 index 00000000..dd9fc625 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2ReadParams.TcPOU @@ -0,0 +1,44 @@ + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2StepMode.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2StepMode.TcPOU new file mode 100644 index 00000000..62971ad2 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MCS2StepMode.TcPOU @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MotionStageMCS2.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MotionStageMCS2.TcPOU new file mode 100644 index 00000000..2dfc8812 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_MotionStageMCS2.TcPOU @@ -0,0 +1,1089 @@ + + + + + + 0 THEN + bExecParamRead := TRUE; // trigger NC param read on first scan + stMCS2ChanParameter.bStageReady := TRUE; + bSystemInit := FALSE; + stMCS2ChanParameter.fPosition := stMotionStage.Axis.NcToPlc.ActPos; + END_IF +END_IF +(* Check for the plc shortcut commands + Used for testing or to circumvent motor record issues*) +rtMoveCmdShortcut(CLK:= stMotionStage.bMoveCmd); +rtHomeCmdShortcut(CLK:= stMotionStage.bHomeCmd); +rtStepCmdShortcut(CLK:= stMCS2ChanParameter.bStepMoveCmd); +rtCalibrateCmdShortcut(CLK:= stMCS2ChanParameter.bCalibrationCmd); + +(* Execute on rising edge*) +IF rtMoveCmdShortcut.Q AND NOT stMotionStage.bExecute THEN + stMotionStage.bExecute := TRUE; + stMotionStage.nCommand := E_EpicsMotorCmd.MOVE_ABSOLUTE; + bEnPosLag := bRecentEnPosLagStatus; + fParameterValue := BOOL_TO_LREAL(bRecentEnPosLagStatus); + +ELSIF rtStepCmdShortcut.Q AND NOT stMotionStage.bExecute THEN + stMotionStage.bExecute := TRUE; + stMotionStage.nCommand := E_EpicsMotorCmd.JOG; // Step mode uses JOG + nCommandLocal := E_EpicsMotorCmd.JOG; + bEnPosLag := bRecentEnPosLagStatus; + fParameterValue := BOOL_TO_LREAL(bRecentEnPosLagStatus); + +ELSIF rtCalibrateCmdShortcut.Q AND NOT stMotionStage.bExecute THEN + stMotionStage.bExecute := TRUE; + stMotionStage.nCommand := E_EpicsMotorCmd.CALIBRATE; // Calibration mode uses CALIBRATE + nCommandLocal := E_EpicsMotorCmd.CALIBRATE; + bEnPosLag := bRecentEnPosLagStatus; + fParameterValue := BOOL_TO_LREAL(bRecentEnPosLagStatus); + +ELSIF rtHomeCmdShortcut.Q AND NOT stMotionStage.bExecute THEN + stMotionStage.bExecute := NOT (stMotionStage.nCmdData = E_EpicsHomeCmd.ABSOLUTE_SET) + OR NOT (stMotionStage.nCmdData = E_EpicsHomeCmd.NONE); + stMotionStage.nCommand := E_EpicsMotorCmd.HOME; + stMotionStage.nCmdData := stMotionStage.nHomingMode; + IF stMotionStage.stAxisParameters.bCtrlEnablePosDiffControl.0 THEN + bRecentEnPosLagStatus := stMotionStage.stAxisParameters.bCtrlEnablePosDiffControl.0; + bEnPosLag := TRUE; + fParameterValue := 0; + END_IF +END_IF + +(* entry point for local and EPICS main execs *) +rtUserExec(CLK:= stMotionStage.bExecute); +(* if a Move/Home Goal is comfirmed and there is no persistant + error conditions, then we have a valid move request.*) +bNewMoveReq S= NOT stMotionStage.bBusy AND rtUserExec.Q AND NOT stMotionStage.bError; +(* this Move request is valid till an error occurs or the currently move is done *) +bNewMoveReq R= NOT stMotionStage.bExecute OR stMotionStage.bError; +bPrepareDisable R= bNewMoveReq; + +(* Set the proper command for the request move; + if bservo not set, manual step moves will be performed *) +IF rtUserExec.Q THEN + // if we enter here from state movers + stMotionStage.bMoveCmd := TRUE; + nCommandLocal := E_EpicsMotorCmd.MOVE_ABSOLUTE; + IF stMotionStage.bHomeCmd THEN + nCommandLocal := stMotionStage.nCommand; + nCmdDataLocal := stMotionStage.nCmdData; + ELSIF stMCS2ChanParameter.bStepMoveCmd THEN + // For stepmode, directly write the command + stMotionStage.nCommand := E_EpicsMotorCmd.JOG; + nCommandLocal := E_EpicsMotorCmd.JOG; + ELSIF stMCS2ChanParameter.bCalibrationCmd THEN + // For calibration, directly write the command + stMotionStage.nCommand := E_EpicsMotorCmd.CALIBRATE; + nCommandLocal := E_EpicsMotorCmd.CALIBRATE; + END_IF + + IF NOT stMotionStage.bHomeCmd AND NOT stMCS2ChanParameter.stChannelState.bIsReferenced THEN + // attempting to move an axis without homing first? + IF stMotionStage.nHomingMode <> E_EpicsHomeCmd.NONE AND NOT stMotionStage.bHomed THEN + stMotionStage.sErrorMessage := 'Axis homing mode set, but homing routine pending'; + END_IF + END_IF +END_IF + +(* Set the drive in the correct operating mode. based on requested move command! + NB: bservo must set for close loop motion +*) +fbDriveManager( + stMotionStage := stMotionStage, + stDS402Drive:=stDS402Drive, + stMCS2ChanParameter :=stMCS2ChanParameter, + bUserExec := rtUserExec.Q +); + +(* NB: This is the only tested mode of operation so far. also aligned + piezo drive position holding feature +*) +rtEnableMode(CLK:=( stMotionStage.nEnableMode = E_StageEnableMode.DURING_MOTION)); +(* Handle auto-enable timing *) +CASE stMotionStage.nEnableMode OF + (* Not recommended, not tested *) + E_StageEnableMode.ALWAYS: + stMotionStage.bEnable:=stMotionStage.bSafetyReady; + E_StageEnableMode.DURING_MOTION: + IF rtEnableMode.Q THEN + stMotionStage.bEnable := FALSE; + END_IF + IF bNewMoveReq THEN + (* override ongoing holding.*) + bPositionHold := FALSE; + tonHoldTime.IN:=FALSE; + (*MC block are not compatible with open loop Motion + thus we wathc for correct close loop modes to use NC features *) + stMotionStage.bEnable := stMotionStage.bSafetyReady; + bLastHoltTimeOut := FALSE; + bHalt:=FALSE; + END_IF +END_CASE + +(* Interlock mainly react on internal limit conditions inthe ove direction. + MCS2 drive will go into error state when an internal limit is hit *) +Interlock(); + +IF fbDriveManager.bCSPModeEnabled THEN + bLocalExec := NOT stMotionStage.bError + AND stMotionStage.bExecute + AND stMotionStage.bAllEnable + AND stMotionStage.bEnableDone + AND stMotionStage.bSafetyReady + AND nCommandLocal = E_EpicsMotorCmd.MOVE_ABSOLUTE; +ELSIF fbDriveManager.bHomeModeEnabled THEN + bLocalExec := NOT stMotionStage.bError + AND stMotionStage.bExecute + AND stMotionStage.bAllEnable + AND fbDriveManager.bOperational + AND stMotionStage.bSafetyReady + AND nCommandLocal = E_EpicsMotorCmd.HOME; +ELSIF fbDriveManager.bStepModeEnabled THEN + bLocalExec := NOT stMotionStage.bError + AND stMotionStage.bExecute + AND stMotionStage.bAllEnable + AND fbDriveManager.bOperational + AND stMotionStage.bSafetyReady + AND nCommandLocal = E_EpicsMotorCmd.JOG; +ELSIF fbDriveManager.bCalibrationModeEnabled THEN + bLocalExec := NOT stMotionStage.bError + AND stMotionStage.bExecute + AND stMotionStage.bAllEnable + AND fbDriveManager.bOperational + AND stMotionStage.bSafetyReady + AND nCommandLocal = E_EpicsMotorCmd.CALIBRATE; +ELSE + bLocalExec := FALSE; +END_IF + +bExecMove:=bLocalExec AND ((nCommandLocal=E_EpicsMotorCmd.MOVE_ABSOLUTE) + OR (nCommandLocal=E_EpicsMotorCmd.JOG) + OR (nCommandLocal=E_EpicsMotorCmd.CALIBRATE)); +bExecHome:=bLocalExec AND NOT bExecMove; + +(* When we start, set the busy/done appropriately + NB: CLose loop control using NC *) +rtExec(CLK:=bLocalExec); +IF rtExec.Q THEN + // Release previous interruption if any + stDS402Drive.nDriveControl.8 := FALSE; + stMotionStage.bDone := FALSE; +END_IF + +(* updated axis status + Not needed in manual mode *) +IF NOT fbDriveManager.bDS402Manual THEN + stMotionStage.Axis.ReadStatus(); +END_IF + +(* Get a definitive bEnabled reading + NB: use only in close loop mode, NC feature needed*) +CASE stMotionStage.Axis.Status.MotionState OF + (* We are not enabled if there is an issue*) + MC_AXISSTATE_UNDEFINED, MC_AXISSTATE_DISABLED, MC_AXISSTATE_ERRORSTOP: + stMotionStage.bEnableDone := FALSE; + ELSE + stMotionStage.bEnableDone := TRUE; +END_CASE +// +IF stMotionStage.bReset THEN + // Clear all motion and error flags + stMotionStage.bExecute := FALSE; + stMotionStage.bError := FALSE; + stMotionStage.nErrorId := 0; + stMotionStage.sErrorMessage := ''; + stMotionStage.sCustomErrorMessage := ''; + fbMCS2StepMode.Reset(); + fbMCS2home.Reset(); + bReset := TRUE; + IF fbDriveManager.bDS402Manual THEN + // Set bit 7 for reset in manual mode + stDS402Drive.nDriveControl.7 := TRUE; + END_IF + stMotionStage.bReset := FALSE; +END_IF + +// EPICS user requested a stop ? +ftExec(CLK := stMotionStage.bExecute); + +bHalt:=ftExec.Q AND stMotionStage.bBusy; +rtHaltEdge(CLK := bHalt); +IF rtHaltEdge.Q AND fbDriveManager.bDS402Manual THEN + fbMCS2StepMode.Halt(); + fbMCS2home.Halt(); + stDS402Drive.nDriveControl.8 := TRUE; +END_IF + +//auto handle position lag monitoring, disable during homing. +WriteParameterNC( Execute:=bEnPosLag, + ParameterNumber:=MC_AxisParameter.AxisEnPositionLagMonitoring, + ParameterValue:=fParameterValue); +fbChanParams ( + bEnable:=stMotionStage.bAxisParamsInit AND stMCS2ChanParameter.bEnableHardwareOps, + stMCS2ChanParameter := stMCS2ChanParameter, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, +); + +fbHomingParams ( + bEnable:=stMotionStage.bAxisParamsInit AND stMCS2ChanParameter.bEnableHardwareOps, + stMCS2ChanParameter := stMCS2ChanParameter, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, +); + +fbStepModeParams ( + bEnable:=stMotionStage.bAxisParamsInit AND stMCS2ChanParameter.bEnableHardwareOps, + stMCS2ChanParameter := stMCS2ChanParameter, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, +); + +fbCalibrationParams ( + bEnable:=stMotionStage.bAxisParamsInit AND stMCS2ChanParameter.bEnableHardwareOps, + stMCS2ChanParameter := stMCS2ChanParameter, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, +); +(* Requested commands processing *) +CASE nCommandLocal OF + E_EpicsMotorCmd.MOVE_ABSOLUTE: + (*NC CSP Move Handling*) + Reset(); + Power(); + Halt(); + (*Wait for drive to be in the correct mode after a request was validated *) + MoveAbsolute(); + (*IN CSP mode the drive control word is update via the NC + Manual step mode and Homing will override this *) + stDS402Drive.nModeOfOperation:= stDS402Drive.nModeOfOperationNC; + stDS402Drive.nDriveControl := stDS402Drive.nDriveControlNC; + E_EpicsMotorCmd.HOME: + (*DS402 Manual Homing*) + fbMCS2home( + bEnable:=bExecHome AND fbChanParams.bChanParamsSet AND fbHomingParams.bHomingParamsSet, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, + ); + E_EpicsMotorCmd.JOG: + (* Set drive to correct operating mode, ensure motion params are correct + following a validated open loop mode request. + NB: bservo must be off. a PV is provided for that + *) + fbMCS2StepMode( + bEnable:=bExecMove AND fbStepModeParams.bStepModeParamsSet, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, + ); + E_EpicsMotorCmd.CALIBRATE: + fbMCS2Calibrate( + bEnable:=bExecMove AND fbChanParams.bChanParamsSet AND fbCalibrationParams.bCalibrationsParamsSet, + stDS402Drive:=stDS402Drive, + stMotionStage:=stMotionStage, + ); +END_CASE + +stMotionStage.bBusy := fbMcMoveAbsolute.Busy + OR stMCS2ChanParameter.stChannelState.bReferencing + OR fbMCS2StepMode.bStepMoveBusy + OR stMCS2ChanParameter.stChannelState.bCalibrating; +(* Check done moving via user stop, limit hit, Target Position reached, or from homing.*) +PostMoveChecks(); + +(* update encoder value and calibrated position*) +ScaleEncRawValue(); + +(*Drive parameters*) +ExposedParameters(Enable:=stMCS2ChanParameter.bStageReady, tRefreshDelay:=T#2S); + +(*Read MCS2 Channel Parameters*) +fbReadChanParams( + bEnable:= stMCS2ChanParameter.bEnableHardwareOps, + stMotionStage:=stMotionStage, + stMCS2ChanParameter:=stMCS2ChanParameter, + stDS402Drive:=stDS402Drive, +); + +(* Save and restore as long as not an absolute encoder*) +PersistParameters( Enable:= stMCS2ChanParameter.bStageReady); + +(*Restore encoder value at initialization*) +RestoreMotionParams(Enable:= stMCS2ChanParameter.bStageReady); + +(*EPICS Motor record Update*) +UpdateEpicsStatus(); +(* + Error from functions and Nc. The error will send to EPICS interface based on predifined + priority: axis, power, backlash, absoluteMove, etc... +*) +IF fbMcPower.Error AND fbMcPower.Active THEN + stMotionStage.bError:=fbMcPower.Error; + stMotionStage.nErrorId:=fbMcPower.ErrorID; +ELSIF fbMcMoveAbsolute.Error THEN + stMotionStage.bError:=fbMcMoveAbsolute.Error; + stMotionStage.nErrorId:=fbMcMoveAbsolute.ErrorID; +ELSIF fbMcHalt.Error AND fbMcHalt.Active THEN + stMotionStage.bError:=fbMcHalt.Error; + stMotionStage.nErrorId:=fbMcHalt.ErrorID; +ELSIF fbMcReset.Error THEN + stMotionStage.bError:=fbMcReset.Error; + stMotionStage.nErrorId:=fbMcReset.ErrorID; +ELSIF fbMcWriteParameter.Error THEN + stMotionStage.bError:=fbMcWriteParameter.Error; + stMotionStage.nErrorId:=fbMcWriteParameter.ErrorID; +ELSIF fbMcReadParams.Error AND NOT stMotionStage.bBusy THEN + stMotionStage.bError:=fbMcReadParams.Error; + stMotionStage.nErrorId:=fbMcReadParams.ErrorID; +ELSE + IF stMotionStage.bBusy THEN + stMotionStage.sErrorMessage := ''; + stMotionStage.sCustomErrorMessage := ''; + END_IF +END_IF; + +(*Double function, prioritize NC error otherwise read drive channel error code*) +fbReadDriveCodes( + bEnable:= stMCS2ChanParameter.bEnableHardwareOps, + stMotionStage:=stMotionStage, + stMCS2ChanParameter:=stMCS2ChanParameter, + stDS402Drive:=stDS402Drive +); + +IF stMotionStage.sCustomErrorMessage <> '' + AND stMotionStage.sErrorMessage = '' THEN + stMotionStage.sErrorMessage := stMotionStage.sCustomErrorMessage; +END_IF + +(*Clear motion flag when error occurs*) +IF stMotionStage.bError THEN + stMotionStage.bExecute := FALSE; + stMotionStage.bBusy := FALSE; + stMotionStage.bDone := FALSE; + stMotionStage.bEnable := FALSE; +END_IF + +(* We've got the rising edge clear this flags.*) +stMotionStage.bMoveCmd := FALSE; +stMotionStage.bHomeCmd := FALSE; +stMCS2ChanParameter.bStepMoveCmd := FALSE; +stMCS2ChanParameter.bCalibrationCmd := FALSE; +]]> + + + + + + + + + + + + + + + + + + + + + + + 0; +bNegativeDirection:= stMotionStage.bBusy AND stMotionStage.fPosDiff < 0; + +// For SmartAct MCS2 these limit are range and enstop limits. however a single bit in the status is used +// bLimOverride : act as an override after limit was hit to allow reverse movement + stMotionStage.bLimitForwardEnable := bLimOverride OR NOT( bPositiveDirection AND stDS402Drive.stDriveStatus.InternalLimitActive ); + stMotionStage.bLimitBackwardEnable := bLimOverride OR NOT( bNegativeDirection AND stDS402Drive.stDriveStatus.InternalLimitActive ); + +// use falling trigger to avoid spaming sErrorMessage +ftForwardEnabled(CLK:= stMotionStage.bLimitForwardEnable); +ftBackwardEnabled(CLK:= stMotionStage.bLimitBackwardEnable); + +IF NOT fbMCS2home.bHomeMoveBusy AND ftForwardEnabled.Q THEN + // Not an error, just a warning + stMotionStage.sCustomErrorMessage:='Cannot move past positive limit.'; + IF NOT fbDriveManager.bStepModeEnabled THEN + bLimOverride := TRUE; + bHalt := TRUE; + END_IF +END_IF + +IF NOT fbMCS2home.bHomeMoveBusy AND ftBackwardEnabled.Q THEN + // Not an error, just a warning + stMotionStage.sCustomErrorMessage:='Cannot move past Negative limit.'; + IF NOT fbDriveManager.bStepModeEnabled THEN + bLimOverride := TRUE; + bHalt := TRUE; + END_IF +END_IF + +IF NOT stMotionStage.bError AND stMotionStage.bExecute AND NOT stMotionStage.bUserEnable THEN + stMotionStage.bError := TRUE; + stMotionStage.nErrorId := 1; + stMotionStage.sCustomErrorMessage := 'Move requested, but user enable is disabled!'; +END_IF + +// Update all enable booleans +SetEnables();]]> + + + + + + + + + + + + = 16#4400 AND stMotionStage.Axis.Status.ErrorID <= 16#44FF ); + // Do not save if we're currently loading or if there is an encoder error + IF NOT bRestoreLoad AND NOT bEncError AND NOT bRestoreWaitRetry THEN + fSavedPosition := stMotionStage.Axis.NcToPlc.ActPos; + // This persistent variable lets us check if anything was saved + // It will be TRUE at startup if we have saved values + bSaved := TRUE; + END_IF +END_IF]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = nMaxRetries THEN + // Alert the user that something has gone wrong + stMotionStage.bError := TRUE; + stMotionStage.nErrorId := nLatchError; + stMotionStage.sCustomErrorMessage := 'Error loading previously saved position.'; + ELSE + // Reset the FB for the next retry + fbSetPos( Axis:= stMotionStage.Axis, Execute:=bRestoreLoad, Position:=fSavedPosition); + // Try again + bRestoreWaitRetry := TRUE; + END_IF + ELSIF fbSetPos.Done THEN + stMotionStage.fPosition := fSavedPosition; + END_IF + + // Only load once, at startup + bRestoreLoad R= fbSetPos.Done OR fbSetPos.Error; + + tonRestoreRetry( IN := bRestoreWaitRetry, PT := T#100MS); + bRestoreLoad S= tonRestoreRetry.Q; + bRestoreWaitRetry R= tonRestoreRetry.Q; +END_IF]]> + + + + + + 0 THEN + stMotionStage.nEncoderCount:=DINT_TO_UDINT(ABS( stMotionStage.nRawEncoderDINT)); +ELSE + stMotionStage.nEncoderCount:=0; +END_IF + +// calibrated encoder readback +IF NOT fbDriveManager.bStepModeEnabled THEN + // Close loop NC + fMeasuredPos:= stMotionStage.Axis.NcToPlc.ActPos; + fMeasuredVelo := stMotionStage.Axis.NcToPlc.ActVelo; + fMeasuredAcc := stMotionStage.Axis.NcToPlc.ActAcc; + stMotionStage.fPosDiff:= stMotionStage.Axis.NcToPlc.PosDiff; +ELSE + fMeasuredPos:=DINT_TO_REAL( stMotionStage.nRawEncoderDINT) * MAX( stMotionStage.stAxisParameters.fEncScaleFactorInternal, stMCS2ChanParameter.fScalingFactor); + stMotionStage.fPosDiff:= stMotionStage.fPosition - fMeasuredPos; + // NB: Not actual in open loop + fMeasuredVelo := stMotionStage.fVelocity; + fMeasuredAcc := stMotionStage.fAcceleration; +END_IF + +]]> + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadChanParameters.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadChanParameters.TcPOU new file mode 100644 index 00000000..caf0f0dc --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadChanParameters.TcPOU @@ -0,0 +1,250 @@ + + + + + + 0; + stMCS2ChanParameter.stChannelState.bClosedLoopActive := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000002) <> 0; + stMCS2ChanParameter.stChannelState.bCalibrating := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000004) <> 0; + stMCS2ChanParameter.stChannelState.bReferencing := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000008) <> 0; + stMCS2ChanParameter.stChannelState.bMoveDelayed := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000010) <> 0; + stMCS2ChanParameter.stChannelState.bSensorPresent := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000020) <> 0; + stMCS2ChanParameter.stChannelState.bIsCalibrated := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000040) <> 0; + stMCS2ChanParameter.stChannelState.bIsReferenced := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000080) <> 0; + stMCS2ChanParameter.stChannelState.bEndStopReached := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000100) <> 0; + stMCS2ChanParameter.stChannelState.bRangeLimitReached := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000200) <> 0; + stMCS2ChanParameter.stChannelState.bFollowingLimitReached := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000400) <> 0; + stMCS2ChanParameter.stChannelState.bMovementFailed := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00000800) <> 0; + stMCS2ChanParameter.stChannelState.bIsStreaming := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00001000) <> 0; + stMCS2ChanParameter.stChannelState.bPositionerOverload := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00002000) <> 0; + stMCS2ChanParameter.stChannelState.bOverTemperature := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00004000) <> 0; + stMCS2ChanParameter.stChannelState.bReferenceMark := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00008000) <> 0; + stMCS2ChanParameter.stChannelState.bIsPhased := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00010000) <> 0; + stMCS2ChanParameter.stChannelState.bPositionerFault := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00020000) <> 0; + stMCS2ChanParameter.stChannelState.bAmplifierEnabled := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00040000) <> 0; + stMCS2ChanParameter.stChannelState.bInPosition := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00080000) <> 0; + stMCS2ChanParameter.stChannelState.bBrakeEnabled := (stMCS2ChanParameter.stChannelState.nChannelStateRaw AND 16#00100000) <> 0; + ELSE + IF NOT stMotionStage.bBusy THEN + stMotionStage.sErrorMessage := 'Failed to read ChannelState'; + END_IF + END_IF + // RE-trigger the timer (restarts after SDO read is finished and bits decoded) + bChanReadTrigger := FALSE; + tonSDOReadTrigger(IN := TRUE); + eSDOReadStep := 0; + END_IF + + ELSE + eSDOReadStep := 0; + END_CASE + + IF eSDOReadStep = 0 THEN + tonSDOReadTrigger( + IN := stMotionStage.bAxisParamsInit, + PT := stMCS2ChanParameter.nReadTime + ); + ELSE + tonSDOReadTrigger( + IN := FALSE, + PT := stMCS2ChanParameter.nReadTime + ); + END_IF + + + fbMaxCloseLoopFreqRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanMaxCloseLoopFreqIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nMaxCloseLoopFreq), + cbBufLen := SIZEOF(stMCS2ChanParameter.nMaxCloseLoopFreq), + bExecute := bChanReadTrigger + ); + + fbPositionerTypeRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanPositionerTypeIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nPositionerType), + cbBufLen := SIZEOF(stMCS2ChanParameter.nPositionerType), + bExecute := bChanReadTrigger + ); + + fbCalibrationOptRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanCalibrationOptIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nCalibrationOpt), + cbBufLen := SIZEOF(stMCS2ChanParameter.nCalibrationOpt), + bExecute := bChanReadTrigger + ); + // + fbSensorPowerModeRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanSensorPowerModeIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nSensorPowerMode), + cbBufLen := SIZEOF(stMCS2ChanParameter.nSensorPowerMode), + bExecute := bChanReadTrigger + ); + + fbReferencingOptRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanReferencingOptIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nReferencingOpt), + cbBufLen := SIZEOF(stMCS2ChanParameter.nReferencingOpt), + bExecute := bChanReadTrigger + ); + // + fbReferenceTypeRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanReferenceTypeIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nReferenceType), + cbBufLen := SIZEOF(stMCS2ChanParameter.nReferenceType), + bExecute := bChanReadTrigger + ); + + fbSafeDirRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanSafeDirIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nSafeDir), + cbBufLen := SIZEOF(stMCS2ChanParameter.nSafeDir), + bExecute := bChanReadTrigger + ); + + fbMotorLoadRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanMotorLoadIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nMotorLoad), + cbBufLen := SIZEOF(stMCS2ChanParameter.nMotorLoad), + bExecute := bChanReadTrigger + ); + + fbChannelTypeRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChannelTypeIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nChannelType), + cbBufLen := SIZEOF(stMCS2ChanParameter.nChannelType), + bExecute := bChanReadTrigger + ); + + fbChannelStateRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanStateIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.stChannelState.nChannelStateRaw), + cbBufLen := SIZEOF(stMCS2ChanParameter.stChannelState.nChannelStateRaw), + bExecute := bChanReadTrigger + ); + + fbLogicalScaleOffsetRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanLogicalScaleOfsIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nLogicalScaleOffset), + cbBufLen := SIZEOF(stMCS2ChanParameter.nLogicalScaleOffset), + bExecute := bChanReadTrigger + ); + + fbLogicalScaleInvRead( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanLogicalScaleInvIdx, + nSubIndex := 0, + pDstBuf := ADR(stMCS2ChanParameter.nLogicalScaleInv), + cbBufLen := SIZEOF(stMCS2ChanParameter.nLogicalScaleInv), + bExecute := bChanReadTrigger + ); + +END_IF]]> + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadDriveCodes.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadDriveCodes.TcPOU new file mode 100644 index 00000000..63c52136 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_ReadDriveCodes.TcPOU @@ -0,0 +1,57 @@ + + + + + + 0 THEN + stMotionStage.nErrorId := nPiezoErrorCode; + END_IF + stMotionStage.sErrorMessage := F_MotionErrorCodeLookup(nErrorId:=stMotionStage.nErrorId); + fbLogError( stMotionStage:=stMotionStage, bEnable:=stMotionStage.bError); +ELSE + // just return the NC error + stMotionStage.sErrorMessage := F_MotionErrorCodeLookup(nErrorId:=stMotionStage.nErrorId); + fbLogError( stMotionStage:=stMotionStage, bEnable:=stMotionStage.bError); +END_IF +]]> + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteCalibrationParameters.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteCalibrationParameters.TcPOU new file mode 100644 index 00000000..b90f3356 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteCalibrationParameters.TcPOU @@ -0,0 +1,138 @@ + + + + + + 0) AND (NOT bForceSequentialSDOs) THEN + nCalibParamStep := 0; + END_IF + + IF (nCalibParamStep = -1) AND bErrorAcknowledge THEN + nCalibParamStep := 0; + stMotionStage.bError := FALSE; + stMotionStage.nErrorId := 0; + END_IF + + ftCalibrationOptSetDone(CLK := fbCalibrationOptWrite.bBusy); + + IF tonStartUp.Q OR bForceSequentialSDOs THEN + + CASE nCalibParamStep OF + 0: + bCalibrationsParamsSet := FALSE; + fbCalibrationOptWrite.bExecute := FALSE; + nCalibParamStep := 1; + + 1: + IF (stMCS2ChanParameter.nCalibrationOpt <> nRecentCalibrationOpt) THEN + fbCalibrationOptWrite.bExecute := TRUE; + IF ftCalibrationOptSetDone.Q THEN + IF fbCalibrationOptWrite.bError THEN + stMotionStage.bError := fbCalibrationOptWrite.bError; + stMotionStage.nErrorId := fbCalibrationOptWrite.nErrId; + nCalibParamStep := -1; + ELSE + nRecentCalibrationOpt := stMCS2ChanParameter.nCalibrationOpt; + fbCalibrationOptWrite.bExecute := FALSE; + nCalibParamStep := 10; + END_IF + END_IF + ELSE + nCalibParamStep := 10; + END_IF + + 10: + bCalibrationsParamsSet := TRUE; + -1: + bCalibrationsParamsSet := FALSE; + ELSE + nCalibParamStep := 0; + END_CASE + ELSE + fbCalibrationOptWrite.bExecute := (stMCS2ChanParameter.nCalibrationOpt <> nRecentCalibrationOpt); + + IF ftCalibrationOptSetDone.Q THEN + IF fbCalibrationOptWrite.bError THEN + stMotionStage.bError := fbCalibrationOptWrite.bError; + stMotionStage.nErrorId := fbCalibrationOptWrite.nErrId; + ELSE + nRecentCalibrationOpt := stMCS2ChanParameter.nCalibrationOpt; + bCalibrationsParamsSet := TRUE; + END_IF + fbCalibrationOptWrite.bExecute := FALSE; + END_IF + END_IF + + fbCalibrationOptWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanCalibrationOptIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nCalibrationOpt), + cbBufLen := SIZEOF(stMCS2ChanParameter.nCalibrationOpt) + ); + + bCalibrationsParamsSet R= fbCalibrationOptWrite.bBusy; +END_IF]]> + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteChanParameters.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteChanParameters.TcPOU new file mode 100644 index 00000000..ff97c4bb --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteChanParameters.TcPOU @@ -0,0 +1,403 @@ + + + + + + 0) AND (NOT bForceSequentialSDOs) THEN + nChanParamStep := 0; + END_IF + + IF (nChanParamStep = -1) AND bErrorAcknowledge THEN + nChanParamStep := 0; + stMotionStage.bError := FALSE; + stMotionStage.nErrorId := 0; + END_IF + + ScaleDriveParams(); + + ftFErrWinSetDone (CLK := fbSetFErrorWin.bBusy); + ftSoftLimMinSetDone (CLK := fbSetSoftLimMin.bBusy); + ftSoftLimMaxSetDone (CLK := fbSetSoftLimMax.bBusy); + ftMaxCloseLoopFreqSetDone (CLK := fbMaxCloseLoopFreqWrite.bBusy); + ftSensorPowerModeSetDone (CLK := fbSensorPowerModeWrite.bBusy); + ftLogicalScaleOffsetSetDone (CLK := fbLogicalScaleOffsetWrite.bBusy); + ftLogicalScaleInvSetDone (CLK := fbLogicalScaleInvWrite.bBusy); + + IF tonStartUp.Q OR bForceSequentialSDOs THEN + + CASE nChanParamStep OF + 0: + bChanParamsSet := FALSE; + fbSetFErrorWin.bExecute := FALSE; + fbSetSoftLimMin.bExecute := FALSE; + fbSetSoftLimMax.bExecute := FALSE; + fbMaxCloseLoopFreqWrite.bExecute := FALSE; + fbSensorPowerModeWrite.bExecute := FALSE; + fbLogicalScaleOffsetWrite.bExecute := FALSE; + fbLogicalScaleInvWrite.bExecute := FALSE; + nChanParamStep := 1; + + 1: // Following Error Window + IF (nScaledFErrWin <> nRecentFErrWin) THEN + fbSetFErrorWin.bExecute := TRUE; + IF ftFErrWinSetDone.Q THEN + IF fbSetFErrorWin.bError THEN + stMotionStage.bError := fbSetFErrorWin.bError; + stMotionStage.nErrorId := fbSetFErrorWin.nErrId; + nChanParamStep := -1; + ELSE + nRecentFErrWin := nScaledFErrWin; + fbSetFErrorWin.bExecute := FALSE; + nChanParamStep := 2; + END_IF + END_IF + ELSE + nChanParamStep := 2; + END_IF + + 2: // Soft Limit Min + IF (stMCS2ChanParameter.nSoftLimMin <> nRecentSoftLimMin) THEN + fbSetSoftLimMin.bExecute := TRUE; + IF ftSoftLimMinSetDone.Q THEN + IF fbSetSoftLimMin.bError THEN + stMotionStage.bError := fbSetSoftLimMin.bError; + stMotionStage.nErrorId := fbSetSoftLimMin.nErrId; + nChanParamStep := -1; + ELSE + nRecentSoftLimMin := stMCS2ChanParameter.nSoftLimMin; + fbSetSoftLimMin.bExecute := FALSE; + nChanParamStep := 3; + END_IF + END_IF + ELSE + nChanParamStep := 3; + END_IF + + 3: // Soft Limit Max + IF (stMCS2ChanParameter.nSoftLimMax <> nRecentSoftLimMax) THEN + fbSetSoftLimMax.bExecute := TRUE; + IF ftSoftLimMaxSetDone.Q THEN + IF fbSetSoftLimMax.bError THEN + stMotionStage.bError := fbSetSoftLimMax.bError; + stMotionStage.nErrorId := fbSetSoftLimMax.nErrId; + nChanParamStep := -1; + ELSE + nRecentSoftLimMax := stMCS2ChanParameter.nSoftLimMax; + fbSetSoftLimMax.bExecute := FALSE; + nChanParamStep := 4; + END_IF + END_IF + ELSE + nChanParamStep := 4; + END_IF + + 4: // Max Close Loop Freq + IF (stMCS2ChanParameter.nMaxCloseLoopFreq <> nRecentMaxCloseLoopFreq) THEN + fbMaxCloseLoopFreqWrite.bExecute := TRUE; + IF ftMaxCloseLoopFreqSetDone.Q THEN + IF fbMaxCloseLoopFreqWrite.bError THEN + stMotionStage.bError := fbMaxCloseLoopFreqWrite.bError; + stMotionStage.nErrorId := fbMaxCloseLoopFreqWrite.nErrId; + nChanParamStep := -1; + ELSE + nRecentMaxCloseLoopFreq := stMCS2ChanParameter.nMaxCloseLoopFreq; + fbMaxCloseLoopFreqWrite.bExecute := FALSE; + nChanParamStep := 5; + END_IF + END_IF + ELSE + nChanParamStep := 5; + END_IF + + 5: // Sensor Power Mode + IF (stMCS2ChanParameter.nSensorPowerMode <> nRecentSensorPowerMode) THEN + fbSensorPowerModeWrite.bExecute := TRUE; + IF ftSensorPowerModeSetDone.Q THEN + IF fbSensorPowerModeWrite.bError THEN + stMotionStage.bError := fbSensorPowerModeWrite.bError; + stMotionStage.nErrorId := fbSensorPowerModeWrite.nErrId; + nChanParamStep := -1; + ELSE + nRecentSensorPowerMode := stMCS2ChanParameter.nSensorPowerMode; + fbSensorPowerModeWrite.bExecute := FALSE; + nChanParamStep := 6; + END_IF + END_IF + ELSE + nChanParamStep := 6; + END_IF + + 6: // Logical Scale Offset + IF (stMCS2ChanParameter.nLogicalScaleOffset <> nRecentLogicalScaleOffset) THEN + fbLogicalScaleOffsetWrite.bExecute := TRUE; + IF ftLogicalScaleOffsetSetDone.Q THEN + IF fbLogicalScaleOffsetWrite.bError THEN + stMotionStage.bError := fbLogicalScaleOffsetWrite.bError; + stMotionStage.nErrorId := fbLogicalScaleOffsetWrite.nErrId; + nChanParamStep := -1; + ELSE + nRecentLogicalScaleOffset := stMCS2ChanParameter.nLogicalScaleOffset; + fbLogicalScaleOffsetWrite.bExecute := FALSE; + nChanParamStep := 7; + END_IF + END_IF + ELSE + nChanParamStep := 7; + END_IF + + 7: // Logical Scale Inv + IF (stMCS2ChanParameter.nLogicalScaleInv <> nRecentLogicalScaleInv) THEN + fbLogicalScaleInvWrite.bExecute := TRUE; + IF ftLogicalScaleInvSetDone.Q THEN + IF fbLogicalScaleInvWrite.bError THEN + stMotionStage.bError := fbLogicalScaleInvWrite.bError; + stMotionStage.nErrorId := fbLogicalScaleInvWrite.nErrId; + nChanParamStep := -1; + ELSE + nRecentLogicalScaleInv := stMCS2ChanParameter.nLogicalScaleInv; + fbLogicalScaleInvWrite.bExecute := FALSE; + nChanParamStep := 10; + END_IF + END_IF + ELSE + nChanParamStep := 10; + END_IF + + 10: // Done + bChanParamsSet := TRUE; + -1: + bChanParamsSet := FALSE; + ELSE + nChanParamStep := 0; + END_CASE + + ELSE + fbSetFErrorWin.bExecute := (nScaledFErrWin <> nRecentFErrWin); + fbSetSoftLimMin.bExecute := (stMCS2ChanParameter.nSoftLimMin <> nRecentSoftLimMin); + fbSetSoftLimMax.bExecute := (stMCS2ChanParameter.nSoftLimMax <> nRecentSoftLimMax); + fbMaxCloseLoopFreqWrite.bExecute := (stMCS2ChanParameter.nMaxCloseLoopFreq <> nRecentMaxCloseLoopFreq); + fbSensorPowerModeWrite.bExecute := (stMCS2ChanParameter.nSensorPowerMode <> nRecentSensorPowerMode); + fbLogicalScaleOffsetWrite.bExecute := (stMCS2ChanParameter.nLogicalScaleOffset <> nRecentLogicalScaleOffset); + fbLogicalScaleInvWrite.bExecute := (stMCS2ChanParameter.nLogicalScaleInv <> nRecentLogicalScaleInv); + + IF ftFErrWinSetDone.Q OR ftSoftLimMinSetDone.Q OR ftSoftLimMaxSetDone.Q OR + ftMaxCloseLoopFreqSetDone.Q OR ftSensorPowerModeSetDone.Q OR + ftLogicalScaleOffsetSetDone.Q OR ftLogicalScaleInvSetDone.Q THEN + + IF fbSetFErrorWin.bError THEN + stMotionStage.bError := fbSetFErrorWin.bError; + stMotionStage.nErrorId := fbSetFErrorWin.nErrId; + ELSIF fbSetSoftLimMin.bError THEN + stMotionStage.bError := fbSetSoftLimMin.bError; + stMotionStage.nErrorId := fbSetSoftLimMin.nErrId; + ELSIF fbSetSoftLimMax.bError THEN + stMotionStage.bError := fbSetSoftLimMax.bError; + stMotionStage.nErrorId := fbSetSoftLimMax.nErrId; + ELSIF fbMaxCloseLoopFreqWrite.bError THEN + stMotionStage.bError := fbMaxCloseLoopFreqWrite.bError; + stMotionStage.nErrorId := fbMaxCloseLoopFreqWrite.nErrId; + ELSIF fbSensorPowerModeWrite.bError THEN + stMotionStage.bError := fbSensorPowerModeWrite.bError; + stMotionStage.nErrorId := fbSensorPowerModeWrite.nErrId; + ELSIF fbLogicalScaleOffsetWrite.bError THEN + stMotionStage.bError := fbLogicalScaleOffsetWrite.bError; + stMotionStage.nErrorId := fbLogicalScaleOffsetWrite.nErrId; + ELSIF fbLogicalScaleInvWrite.bError THEN + stMotionStage.bError := fbLogicalScaleInvWrite.bError; + stMotionStage.nErrorId := fbLogicalScaleInvWrite.nErrId; + ELSE + nRecentFErrWin := nScaledFErrWin; + nRecentSoftLimMin := stMCS2ChanParameter.nSoftLimMin; + nRecentSoftLimMax := stMCS2ChanParameter.nSoftLimMax; + nRecentMaxCloseLoopFreq := stMCS2ChanParameter.nMaxCloseLoopFreq; + nRecentSensorPowerMode := stMCS2ChanParameter.nSensorPowerMode; + nRecentLogicalScaleOffset:= stMCS2ChanParameter.nLogicalScaleOffset; + nRecentLogicalScaleInv := stMCS2ChanParameter.nLogicalScaleInv; + bChanParamsSet := TRUE; + END_IF + + fbSetFErrorWin.bExecute := FALSE; + fbSetSoftLimMin.bExecute := FALSE; + fbSetSoftLimMax.bExecute := FALSE; + fbMaxCloseLoopFreqWrite.bExecute := FALSE; + fbSensorPowerModeWrite.bExecute := FALSE; + fbLogicalScaleOffsetWrite.bExecute := FALSE; + fbLogicalScaleInvWrite.bExecute := FALSE; + END_IF + END_IF + + fbSetFErrorWin( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanFErrWinIdx, + nSubIndex := 0, + pSrcBuf := ADR(nScaledFErrWin), + cbBufLen := SIZEOF(nScaledFErrWin) + ); + fbSetSoftLimMin( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanSoftLimitIdx, + nSubIndex := 1, + pSrcBuf := ADR(stMCS2ChanParameter.nSoftLimMin), + cbBufLen := SIZEOF(stMCS2ChanParameter.nSoftLimMin) + ); + fbSetSoftLimMax( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanSoftLimitIdx, + nSubIndex := 2, + pSrcBuf := ADR(stMCS2ChanParameter.nSoftLimMax), + cbBufLen := SIZEOF(stMCS2ChanParameter.nSoftLimMax) + ); + fbMaxCloseLoopFreqWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanMaxCloseLoopFreqIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nMaxCloseLoopFreq), + cbBufLen := SIZEOF(stMCS2ChanParameter.nMaxCloseLoopFreq) + ); + fbSensorPowerModeWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanSensorPowerModeIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nSensorPowerMode), + cbBufLen := SIZEOF(stMCS2ChanParameter.nSensorPowerMode) + ); + fbLogicalScaleOffsetWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanLogicalScaleOfsIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nLogicalScaleOffset), + cbBufLen := SIZEOF(stMCS2ChanParameter.nLogicalScaleOffset) + ); + fbLogicalScaleInvWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanLogicalScaleInvIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nLogicalScaleInv), + cbBufLen := SIZEOF(stMCS2ChanParameter.nLogicalScaleInv) + ); + + // Set a busy flag for status + bChanParamsSet R= fbSetFErrorWin.bBusy + OR fbSetSoftLimMin.bBusy + OR fbSetSoftLimMax.bBusy + OR fbMaxCloseLoopFreqWrite.bBusy + OR fbSensorPowerModeWrite.bBusy + OR fbLogicalScaleOffsetWrite.bBusy + OR fbLogicalScaleInvWrite.bBusy; +END_IF]]> + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteHomeParameters.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteHomeParameters.TcPOU new file mode 100644 index 00000000..8f72e35e --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteHomeParameters.TcPOU @@ -0,0 +1,299 @@ + + + + + + 0) AND (NOT bForceSequentialSDOs) THEN + nHomingStep := 0; + END_IF + + IF (nHomingStep = -1) AND bErrorAcknowledge THEN + nHomingStep := 0; + stMotionStage.bError := FALSE; + stMotionStage.nErrorId := 0; + bErrorAcknowledge := FALSE; + END_IF + + ScaleHomingParams(); + ftHomeVeloFastSetDone(CLK:=fbSetHomeVeloFast.bBusy); + ftHomeVeloSlowSetDone(CLK:=fbSetHomeVeloSlow.bBusy); + ftHomeAccSetDone(CLK:=fbSetHomeAcc.bBusy); + ftHomeOffsSetDone(CLK:=fbSetHomeOffs.bBusy); + ftReferencingOptSetDone(CLK:=fbReferencingOptWrite.bBusy); + + IF tonStartUp.Q OR bForceSequentialSDOs THEN + + CASE nHomingStep OF + + 0: + bHomingParamsSet := FALSE; + fbSetHomeVeloFast.bExecute := FALSE; + fbSetHomeVeloSlow.bExecute := FALSE; + fbSetHomeAcc.bExecute := FALSE; + fbSetHomeOffs.bExecute := FALSE; + fbReferencingOptWrite.bExecute := FALSE; + nHomingStep := 1; + + 1: // Write Home Velo Fast + IF (stMCS2ChanParameter.nHomeVeloFast <> nRecentHomeVeloFast) THEN + fbSetHomeVeloFast.bExecute := TRUE; + IF ftHomeVeloFastSetDone.Q THEN + IF fbSetHomeVeloFast.bError THEN + stMotionStage.bError := fbSetHomeVeloFast.bError; + stMotionStage.nErrorId := fbSetHomeVeloFast.nErrId; + nHomingStep := -1; + ELSE + nRecentHomeVeloFast := stMCS2ChanParameter.nHomeVeloFast; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeVeloFast.bExecute := FALSE; + nHomingStep := 2; + END_IF + ELSE + nHomingStep := 2; + END_IF + + 2: // Write Home Velo Slow + IF (stMCS2ChanParameter.nHomeVeloSlow <> nRecentHomeVeloSlow) THEN + fbSetHomeVeloSlow.bExecute := TRUE; + + IF fbSetHomeVeloSlow.bError THEN + stMotionStage.bError := fbSetHomeVeloSlow.bError; + stMotionStage.nErrorId := fbSetHomeVeloSlow.nErrId; + nHomingStep := -1; + ELSE + nRecentHomeVeloSlow := stMCS2ChanParameter.nHomeVeloSlow; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeVeloSlow.bExecute := FALSE; + nHomingStep := 3; + ELSE + nHomingStep := 3; + END_IF + + 3: // Write Home Acc + IF (stMCS2ChanParameter.nHomeAcc <> nRecentHomeAcc) THEN + fbSetHomeAcc.bExecute := TRUE; + IF fbSetHomeAcc.bError THEN + stMotionStage.bError := fbSetHomeAcc.bError; + stMotionStage.nErrorId := fbSetHomeAcc.nErrId; + nHomingStep := -1; + ELSE + nRecentHomeAcc := stMCS2ChanParameter.nHomeAcc; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeAcc.bExecute := FALSE; + nHomingStep := 4; + ELSE + nHomingStep := 4; + END_IF + + 4: // Write Home Offset + IF (stMCS2ChanParameter.nHomeOffset <> nRecentHomeOffset) THEN + fbSetHomeOffs.bExecute := TRUE; + IF fbSetHomeOffs.bError THEN + stMotionStage.bError := fbSetHomeOffs.bError; + stMotionStage.nErrorId := fbSetHomeOffs.nErrId; + nHomingStep := -1; + ELSE + nRecentHomeOffset := stMCS2ChanParameter.nHomeOffset; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeAcc.bExecute := FALSE; + nHomingStep := 5; + ELSE + nHomingStep := 5; + END_IF + + 5: // Write Referencing Option + IF (stMCS2ChanParameter.nReferencingOpt <> nRecentReferencingOpt) THEN + fbReferencingOptWrite.bExecute := TRUE; + IF fbSetHomeOffs.bError THEN + stMotionStage.bError := fbReferencingOptWrite.bError; + stMotionStage.nErrorId := fbReferencingOptWrite.nErrId; + nHomingStep := -1; + ELSE + nRecentReferencingOpt := stMCS2ChanParameter.nReferencingOpt; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeAcc.bExecute := FALSE; + nHomingStep := 10; + ELSE + nHomingStep := 10; + END_IF + + 10: // All done + bHomingParamsSet := TRUE; + -1: // Error state + bHomingParamsSet := FALSE; + ELSE + nHomingStep := 0; + END_CASE + ELSE + fbSetHomeVeloFast.bExecute := (stMCS2ChanParameter.nHomeVeloFast <> nRecentHomeVeloFast); + fbSetHomeVeloSlow.bExecute := (stMCS2ChanParameter.nHomeVeloSlow <> nRecentHomeVeloSlow); + fbSetHomeAcc.bExecute := (stMCS2ChanParameter.nHomeAcc <> nRecentHomeAcc); + fbSetHomeOffs.bExecute := (stMCS2ChanParameter.nHomeOffset <> nRecentHomeOffset); + fbReferencingOptWrite.bExecute := (stMCS2ChanParameter.nReferencingOpt <> nRecentReferencingOpt); + + IF ftHomeVeloFastSetDone.Q OR ftHomeVeloSlowSetDone.Q OR ftHomeAccSetDone.Q + OR ftHomeOffsSetDone.Q OR ftReferencingOptSetDone.Q THEN + IF fbSetHomeVeloFast.bError THEN + stMotionStage.bError := fbSetHomeVeloFast.bError; + stMotionStage.nErrorId := fbSetHomeVeloFast.nErrId; + ELSIF fbSetHomeVeloSlow.bError THEN + stMotionStage.bError := fbSetHomeVeloSlow.bError; + stMotionStage.nErrorId := fbSetHomeVeloSlow.nErrId; + ELSIF fbSetHomeAcc.bError THEN + stMotionStage.bError := fbSetHomeAcc.bError; + stMotionStage.nErrorId := fbSetHomeAcc.nErrId; + ELSIF fbSetHomeOffs.bError THEN + stMotionStage.bError := fbSetHomeOffs.bError; + stMotionStage.nErrorId := fbSetHomeOffs.nErrId; + ELSIF fbReferencingOptWrite.bError THEN + stMotionStage.bError := fbReferencingOptWrite.bError; + stMotionStage.nErrorId := fbReferencingOptWrite.nErrId; + ELSE + nRecentHomeVeloFast := stMCS2ChanParameter.nHomeVeloFast; + nRecentHomeVeloSlow := stMCS2ChanParameter.nHomeVeloSlow; + nRecentHomeAcc := stMCS2ChanParameter.nHomeAcc; + nRecentHomeOffset := stMCS2ChanParameter.nHomeOffset; + nRecentReferencingOpt := stMCS2ChanParameter.nReferencingOpt; + bHomingParamsSet := TRUE; + END_IF + fbSetHomeVeloFast.bExecute := FALSE; + fbSetHomeVeloSlow.bExecute := FALSE; + fbSetHomeAcc.bExecute := FALSE; + fbSetHomeOffs.bExecute := FALSE; + fbReferencingOptWrite.bExecute := FALSE; + END_IF + END_IF + + fbSetHomeVeloFast( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanHomeVeloIdx, + nSubIndex := 1, + pSrcBuf := ADR(stMCS2ChanParameter.nHomeVeloFast), + cbBufLen := SIZEOF(stMCS2ChanParameter.nHomeVeloFast) + ); + fbSetHomeVeloSlow( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanHomeVeloIdx, + nSubIndex := 2, + pSrcBuf := ADR(stMCS2ChanParameter.nHomeVeloSlow), + cbBufLen := SIZEOF(stMCS2ChanParameter.nHomeVeloSlow) + ); + fbSetHomeAcc( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanhomeAccIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nHomeAcc), + cbBufLen := SIZEOF(stMCS2ChanParameter.nHomeAcc) + ); + fbSetHomeOffs( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanHomeOffsIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nHomeOffset), + cbBufLen := SIZEOF(stMCS2ChanParameter.nHomeOffset) + ); + fbReferencingOptWrite( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanReferencingOptIdx, + nSubIndex := 0, + pSrcBuf := ADR(stMCS2ChanParameter.nReferencingOpt), + cbBufLen := SIZEOF(stMCS2ChanParameter.nReferencingOpt) + ); + + bHomingParamsSet R= fbSetHomeVeloFast.bBusy + OR fbSetHomeVeloSlow.bBusy + OR fbSetHomeAcc.bBusy + OR fbSetHomeOffs.bBusy + OR fbReferencingOptWrite.bBusy; +END_IF]]> + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteStepModeParameters.TcPOU b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteStepModeParameters.TcPOU new file mode 100644 index 00000000..f01bf587 --- /dev/null +++ b/lcls-twincat-motion/Library/POUs/Motion/DS402/MCS2/FB_WriteStepModeParameters.TcPOU @@ -0,0 +1,236 @@ + + + + + + 0) AND (NOT bForceSequentialSDOs) THEN + nJogParamStep := 0; + END_IF + + IF (nJogParamStep = -1) AND bErrorAcknowledge THEN + nJogParamStep := 0; + stMotionStage.bError := FALSE; + stMotionStage.nErrorId := 0; + END_IF + ScaleStepModeParams(); + + ftStepUpdateDone (CLK := fbSetSteps.bBusy); + ftStepAmpUpdateDone(CLK := fbSetStepAmp.bBusy); + ftStepFreqUpdateDone(CLK := fbSetStepFreq.bBusy); + + IF tonStartUp.Q OR bForceSequentialSDOs THEN + CASE nJogParamStep OF + 0: + bStepModeParamsSet := FALSE; + fbSetSteps.bExecute := FALSE; + fbSetStepAmp.bExecute := FALSE; + fbSetStepFreq.bExecute := FALSE; + nJogParamStep := 1; + + 1: // Set Steps + IF (nScalededSteps <> nRecentSteps) THEN + fbSetSteps.bExecute := TRUE; + IF ftStepUpdateDone.Q THEN + IF fbSetSteps.bError THEN + stMotionStage.bError := fbSetSteps.bError; + stMotionStage.nErrorId := fbSetSteps.nErrId; + nJogParamStep := -1; + ELSE + nRecentSteps := nScalededSteps; + fbSetSteps.bExecute := FALSE; + nJogParamStep := 2; + END_IF + END_IF + ELSE + nJogParamStep := 2; + END_IF + + 2: // Set Step Amp + IF (nScalededStepAmp <> nRecentStepAmp) THEN + fbSetStepAmp.bExecute := TRUE; + IF ftStepAmpUpdateDone.Q THEN + IF fbSetStepAmp.bError THEN + stMotionStage.bError := fbSetStepAmp.bError; + stMotionStage.nErrorId := fbSetStepAmp.nErrId; + nJogParamStep := -1; + ELSE + nRecentStepAmp := nScalededStepAmp; + fbSetStepAmp.bExecute := FALSE; + nJogParamStep := 3; + END_IF + END_IF + ELSE + nJogParamStep := 3; + END_IF + + 3: // Set Step Frequency + IF (nScaledStepFreq <> nRecentStepFreq) THEN + fbSetStepFreq.bExecute := TRUE; + IF ftStepFreqUpdateDone.Q THEN + IF fbSetStepFreq.bError THEN + stMotionStage.bError := fbSetStepFreq.bError; + stMotionStage.nErrorId := fbSetStepFreq.nErrId; + nJogParamStep := -1; + ELSE + nRecentStepFreq := nScaledStepFreq; + fbSetStepFreq.bExecute := FALSE; + nJogParamStep := 10; + END_IF + END_IF + ELSE + nJogParamStep := 10; + END_IF + + 10: // Done + bStepModeParamsSet := TRUE; + -1: // Error state + bStepModeParamsSet := FALSE; + ELSE + nJogParamStep := 0; + END_CASE + + ELSE + fbSetSteps.bExecute := (nScalededSteps <> nRecentSteps); + fbSetStepAmp.bExecute := (nScalededStepAmp <> nRecentStepAmp); + fbSetStepFreq.bExecute := (nScaledStepFreq <> nRecentStepFreq); + + IF ftStepUpdateDone.Q OR ftStepAmpUpdateDone.Q OR ftStepFreqUpdateDone.Q THEN + IF fbSetSteps.bError THEN + stMotionStage.bError := fbSetSteps.bError; + stMotionStage.nErrorId := fbSetSteps.nErrId; + ELSIF fbSetStepAmp.bError THEN + stMotionStage.bError := fbSetStepAmp.bError; + stMotionStage.nErrorId := fbSetStepAmp.nErrId; + ELSIF fbSetStepFreq.bError THEN + stMotionStage.bError := fbSetStepFreq.bError; + stMotionStage.nErrorId := fbSetStepFreq.nErrId; + ELSE + nRecentSteps := nScalededSteps; + nRecentStepAmp := nScalededStepAmp; + nRecentStepFreq := nScaledStepFreq; + bStepModeParamsSet := TRUE; + END_IF + + fbSetSteps.bExecute := FALSE; + fbSetStepAmp.bExecute := FALSE; + fbSetStepFreq.bExecute := FALSE; + END_IF + END_IF + + fbSetSteps( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanStepIdx, + nSubIndex := 0, + pSrcBuf := ADR(nScalededSteps), + cbBufLen := SIZEOF(stMCS2ChanParameter.nChanStep) + ); + fbSetStepAmp( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanStepAmpIdx, + nSubIndex := 0, + pSrcBuf := ADR(nScalededStepAmp), + cbBufLen := SIZEOF(stMCS2ChanParameter.nChanStepAmp) + ); + fbSetStepFreq( + sNetId := stMotionStage.stAxisParameters.sAmsNetId, + nSlaveAddr := stDS402Drive.nSlaveAddr, + nIndex := stMCS2ChanParameter.nChanStepFreqIdx, + nSubIndex := 0, + pSrcBuf := ADR(nScaledStepFreq), + cbBufLen := SIZEOF(stMCS2ChanParameter.nChanStepFreq) + ); + + bStepModeParamsSet R= fbSetSteps.bBusy + OR fbSetStepAmp.bBusy + OR fbSetStepFreq.bBusy; +END_IF]]> + + + + + + + + + \ No newline at end of file diff --git a/lcls-twincat-motion/Library/_CompileInfo_Upload/AB9F1DA2-32AF-AFB4-FE1B-87E42F17C5BE.compileinfo b/lcls-twincat-motion/Library/_CompileInfo_Upload/AB9F1DA2-32AF-AFB4-FE1B-87E42F17C5BE.compileinfo new file mode 100644 index 00000000..a880ae7e Binary files /dev/null and b/lcls-twincat-motion/Library/_CompileInfo_Upload/AB9F1DA2-32AF-AFB4-FE1B-87E42F17C5BE.compileinfo differ diff --git a/lcls-twincat-motion/_Config/NC/NC.xti b/lcls-twincat-motion/_Config/NC/NC.xti index 346525db..95a2fa55 100644 --- a/lcls-twincat-motion/_Config/NC/NC.xti +++ b/lcls-twincat-motion/_Config/NC/NC.xti @@ -1,5 +1,5 @@ - + UINTARR2 diff --git a/lcls-twincat-motion/_Config/PLC/Library.xti b/lcls-twincat-motion/_Config/PLC/Library.xti index 4bb6f1f2..4320e810 100644 --- a/lcls-twincat-motion/_Config/PLC/Library.xti +++ b/lcls-twincat-motion/_Config/PLC/Library.xti @@ -983,7 +983,7 @@ External Setpoint Generation: - + Library Instance {08500001-0000-0000-F000-000000000064} diff --git a/lcls-twincat-motion/lcls-twincat-motion.tsproj b/lcls-twincat-motion/lcls-twincat-motion.tsproj index f5ff632b..c24b6e11 100644 --- a/lcls-twincat-motion/lcls-twincat-motion.tsproj +++ b/lcls-twincat-motion/lcls-twincat-motion.tsproj @@ -1,6 +1,6 @@ - + @@ -14,9 +14,5 @@ - - - -