diff --git a/solution/tc_project_app/POUs/MAIN.TcPOU b/solution/tc_project_app/POUs/MAIN.TcPOU
index a8867bd..a6f6a9a 100644
--- a/solution/tc_project_app/POUs/MAIN.TcPOU
+++ b/solution/tc_project_app/POUs/MAIN.TcPOU
@@ -40,7 +40,7 @@ VAR
(******Startup, Shutdown and UPS********)
eStartUp: (ColdStart, ReadAxisFeedbackType, CheckReadDone, PrepareToRestore, ExecuteRestore, CheckRestore, FinishRestore);
- bColdstartDone : BOOL := FALSE; // First cycle of the PLC after being reset/power cycled
+ bPositionRestoreDone : BOOL := FALSE;
bExecuteReadEncRefSys : BOOL := TRUE;
iRetry : INT;
fbReadEncRefSys : ARRAY [1..gvl_app.axisNum] OF MC_ReadParameter;
@@ -153,116 +153,114 @@ END_FOR]]>
// Note from Beckhoff: "A maximum of 1 MB persistent data can be reliably saved over the entire service life."
///#########################################################
-// Cycle through function blocks that read the encoder reference system i.e. whether axis is incremental or absolute
-// Result stored in Value, 0=Inc 1=Abs, execute set during the case statement
-FOR i:=1 TO gvl_app.axisNum DO
- fbReadEncRefSys[i](
- Axis:= gvl.axes[i].Axis,
- Enable:= bExecuteReadEncRefSys,
- ParameterNumber:= MC_AxisParameter.AxisEncoderReferenceSystem,
- Value=>,
- ReadMode:= E_READMODE.READMODE_ONCE);
-END_FOR
+// Upon startup bPositionRestoreDone will be set to FALSE, after successfully completing the following code it will be set TRUE
+// and should stay TRUE for the rest of the time the PLC is operational, thus this routine should only be completed once.
+IF bPositionRestoreDone = FALSE THEN
-// Cycle through set position function blocks for each axis
-// Only axes with RestorePosition=RestoreWithoutHome (mode 1) will be utilised
-FOR i:=1 TO gvl_app.axisNum DO
- fbRestorePosition[i](
- Axis:= gvl.axes[i].Axis,
- Execute:= ,
- Position:= iPositionAtShutdown[i]);
-END_FOR
+ // Cycle through function blocks that read the encoder reference system i.e. whether axis is incremental or absolute
+ // Result stored in Value, 0=Inc 1=Abs, execute set during the case statement
+ FOR i:=1 TO gvl_app.axisNum DO
+ fbReadEncRefSys[i](
+ Axis:= gvl.axes[i].Axis,
+ Enable:= bExecuteReadEncRefSys,
+ ParameterNumber:= MC_AxisParameter.AxisEncoderReferenceSystem,
+ Value=>,
+ ReadMode:= E_READMODE.READMODE_ONCE);
+ END_FOR
+
+ // Cycle through set position function blocks for each axis
+ // Only axes with RestorePosition=RestoreWithoutHome (mode 1) will be utilised
+ FOR i:=1 TO gvl_app.axisNum DO
+ fbRestorePosition[i](
+ Axis:= gvl.axes[i].Axis,
+ Execute:= ,
+ Position:= iPositionAtShutdown[i]);
+ END_FOR
-// Upon startup bColdStartDone will be set to FALSE, after the following initialisation it is set to TRUE
-// and should stay TRUE for the rest of the time the PLC is operational, thus this routine should only be completed once
-IF bColdstartDone = FALSE THEN
CASE eStartUp OF
-
- ColdStart:
- // First cycle of the PLC, do nothing just give one cycle for variables to initialise
- IF NOT bColdstartDone THEN
- eStartUp:=eStartUp+1;
- iRetry:=0;
- END_IF
-
- ReadAxisFeedbackType:
- // Exectute the function blocks to read the encoder reference system (inc or abs)
- bExecuteReadEncRefSys:=TRUE;
- eStartUp:=eStartUp+1;
-
- CheckReadDone:
- // Check the encoder reference system has been read for all axis -> if busy then continue with PLC cycle and check again next time
- // If fbReadEncRefSys not started then go back a step
- FOR i:=1 TO gvl_app.axisNum DO
- IF fbReadEncRefSys[i].Valid = FALSE THEN
- IF fbReadEncRefSys[i].Busy = TRUE THEN
- // Exit MAIN.STARTUP Action and wait till next cycle, needs to cycle through whole program in order for data to update
- RETURN;
- ELSE
- // Sometimes the code gets here and the fbReadEncRefSys[i] misses the rising edge.
- // If it gets here it means .valid=FALSE, .error=FALSE and .busy=FALSE which indicateds the FB probably hasn't started
- // and thus needs to see a rising edge. Set execute to low and go back a step in the CASE.
- bExecuteReadEncRefSys:=FALSE;
- eStartUp:=eStartUp-1;
- iRetry:=iRetry+1;
- RETURN;
- END_IF
- END_IF
- END_FOR
- // If the code gets here all axes either have .valid=TRUE or .ERROR=TRUE
- // We disregard errors so that the whole program isn't held up, if there is an error on a axis the value is not restored
- eStartUp:=eStartUp+1;
-
- PrepareToRestore:
- // Prepare to home for axes that opt in for mode 2 RestoreWithHome i.e. normal direct home
- FOR i:=1 TO gvl_app.axisNum DO
- IF fbReadEncRefSys[i].Value=0 AND NOT(bMovingAtShutdown[i]) AND gvl.axes[i].config.eRestorePosition=2 THEN
- gvl.axes[i].control.eCommand:=MotionFunctions.Home;
- gvl.axes[i].config.nHomeSeq:=15;
- gvl.axes[i].config.fHomePosition:=iPositionAtShutdown[i];
- END_IF
- END_FOR
- eStartUp:=eStartUp+1;
-
- ExecuteRestore:
- // Execute position restore using either mode 1: fbRestorePosition or mode 2: normal direct homing (depending on mode)
- FOR i:=1 TO gvl_app.axisNum DO
- IF fbReadEncRefSys[i].Valid = TRUE AND fbReadEncRefSys[i].Value = 0 THEN
- CASE GVL.axes[i].config.eRestorePosition OF
- RestorePosition.RestoreWithoutHome: fbRestorePosition[i].Execute:=TRUE;
- RestorePosition.RestoreWithHome: gvl.axes[i].control.bExecute:=TRUE;
- END_CASE
- END_IF
- END_FOR
- eStartUp:=eStartUp+1;
-
- CheckRestore:
- // Check mode 1: fbRestorePosition or mode 2: direct homing is finished on axes that were opt-in
- // Nothing actually happens if the restore is not done, the code just returns from here each cycle and the
- // bColdStartDone will never get set to TRUE
- FOR i:=1 TO gvl_app.axisNum DO
- IF fbReadEncRefSys[i].Valid = TRUE AND fbReadEncRefSys[i].Value = 0 THEN
- CASE gvl.axes[i].config.eRestorePosition OF
- RestorePosition.RestoreWithoutHome:
- IF NOT fbRestorePosition[i].Done THEN
- RETURN;
- END_IF
- RestorePosition.RestoreWithHome:
- IF NOT gvl.axes[i].status.bHomed THEN
- RETURN;
- END_IF
- END_CASE
- END_IF
- END_FOR
- eStartUp:=eStartUp+1;
-
- FinishRestore: // Remove execute = TRUE for fbRestorePosition
- FOR i:=1 TO gvl_app.axisNum DO
- fbRestorePosition[i].Execute:=FALSE;
- END_FOR
- bColdstartDone:=TRUE;
-
- END_CASE
+ ColdStart:
+ // First cycle of the PLC, do nothing just give one cycle for variables to initialise
+ IF NOT bPositionRestoreDone THEN
+ eStartUp:=eStartUp+1;
+ iRetry:=0;
+ END_IF
+
+ ReadAxisFeedbackType:
+ // Exectute the FUNCTION blocks TO read the encoder REFERENCE system (inc OR ABS)
+ bExecuteReadEncRefSys:=TRUE;
+ eStartUp:=eStartUp+1;
+
+ CheckReadDone:
+ // Check the encoder reference system has been read for all axis -> if busy then continue with PLC cycle and check again next time
+ // If fbReadEncRefSys not started then go back a step
+ FOR i:=1 TO gvl_app.axisNum DO
+ IF fbReadEncRefSys[i].Valid = FALSE THEN
+ IF fbReadEncRefSys[i].Busy = TRUE THEN
+ // Exit MAIN.STARTUP Action and wait till next cycle, needs to cycle through whole program in order for data to update
+ RETURN;
+ ELSE
+ // Sometimes the code gets here and the fbReadEncRefSys[i] misses the rising edge.
+ // If the code gets here it means .valid=FALSE and .busy=FALSE which indicateds the FB probably hasn't started
+ // and thus needs to see a rising edge. Set execute to low and go back a step in the CASE.
+ bExecuteReadEncRefSys:=FALSE;
+ eStartUp:=eStartUp-1;
+ iRetry:=iRetry+1; // counter used for troubleshooting to see how many cycles it takes before fbReadEncRefSys function blocks are read correctly
+ RETURN;
+ END_IF
+ END_IF
+ END_FOR
+ // If the code gets here all axes either have .valid=TRUE for all axes
+ eStartUp:=eStartUp+1;
+
+ PrepareToRestore:
+ // Prepare to home for axes that opt in for mode 2 RestoreWithHome i.e. normal direct home
+ FOR i:=1 TO gvl_app.axisNum DO
+ IF fbReadEncRefSys[i].Value=0 AND NOT(bMovingAtShutdown[i]) AND gvl.axes[i].config.eRestorePosition=2 THEN
+ gvl.axes[i].control.eCommand:=MotionFunctions.Home;
+ gvl.axes[i].config.nHomeSeq:=15;
+ gvl.axes[i].config.fHomePosition:=iPositionAtShutdown[i];
+ END_IF
+ END_FOR
+ eStartUp:=eStartUp+1;
+
+ ExecuteRestore:
+ // Execute position restore using either mode 1: fbRestorePosition or mode 2: normal direct homing (depending on mode)
+ FOR i:=1 TO gvl_app.axisNum DO
+ IF fbReadEncRefSys[i].Valid = TRUE AND fbReadEncRefSys[i].Value = 0 THEN
+ CASE GVL.axes[i].config.eRestorePosition OF
+ RestorePosition.RestoreWithoutHome: fbRestorePosition[i].Execute:=TRUE;
+ RestorePosition.RestoreWithHome: gvl.axes[i].control.bExecute:=TRUE;
+ END_CASE
+ END_IF
+ END_FOR
+ eStartUp:=eStartUp+1;
+
+ CheckRestore:
+ // Check mode 1: fbRestorePosition or mode 2: direct homing is finished on axes that were opt-in
+ // Nothing actually happens if the restore is not done, the code just returns from here each cycle and the
+ // bPositionRestoreDone will never get set to TRUE
+ FOR i:=1 TO gvl_app.axisNum DO
+ IF fbReadEncRefSys[i].Valid = TRUE AND fbReadEncRefSys[i].Value = 0 THEN
+ CASE gvl.axes[i].config.eRestorePosition OF
+ RestorePosition.RestoreWithoutHome:
+ IF NOT fbRestorePosition[i].Done THEN
+ RETURN;
+ END_IF
+ RestorePosition.RestoreWithHome:
+ IF NOT gvl.axes[i].status.bHomed THEN
+ RETURN;
+ END_IF
+ END_CASE
+ END_IF
+ END_FOR
+ eStartUp:=eStartUp+1;
+
+ FinishRestore: // Remove execute = TRUE for fbRestorePosition
+ FOR i:=1 TO gvl_app.axisNum DO
+ fbRestorePosition[i].Execute:=FALSE;
+ END_FOR
+ bPositionRestoreDone:=TRUE;
+ END_CASE
END_IF]]>
@@ -320,6 +318,9 @@ END_IF]]>
+
+
+
@@ -327,12 +328,7 @@ END_IF]]>
-
-
-
-
-
-
+
@@ -357,7 +353,6 @@ END_IF]]>
-
@@ -377,9 +372,7 @@ END_IF]]>
-
-
-
+