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 @@
-
-
-
-