From 5382f7e2b4538d0523082b1bb80da558ee9792c9 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Fri, 12 Sep 2025 13:32:56 +0200 Subject: [PATCH 1/8] FB_SlitPair updated with improvements (soft limits update, operational mode, homing --- DUTs/E_SlitSoftLimits.TcDUT | 16 +++ POUs/Motion/FB_SlitPair.TcPOU | 256 ++++++++++++++++++++++++++++------ 2 files changed, 228 insertions(+), 44 deletions(-) create mode 100644 DUTs/E_SlitSoftLimits.TcDUT diff --git a/DUTs/E_SlitSoftLimits.TcDUT b/DUTs/E_SlitSoftLimits.TcDUT new file mode 100644 index 00000000..97e44d26 --- /dev/null +++ b/DUTs/E_SlitSoftLimits.TcDUT @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index adde0016..0f2d221c 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -1,8 +1,7 @@  - + eSoftLimitsUpdate: E_SlitSoftLimits := E_SlitSoftLimits.START; // Sequence steps for update of soft limits + fbNoMovingRising: R_TRIG; + fbInOpRising: R_TRIG; + bUpdateSoftLimits: BOOL := FALSE; + bHomingRequested: BOOL := FALSE; + fbEnableRising: R_TRIG; + fbStopRising: R_TRIG; + fbDisableRising: R_TRIG; + fbDisabledRising: R_TRIG; + fbHomingRising: R_TRIG; +END_VAR]]> 0) OR (GVL.astAxes[iBladePositive].stStatus.nErrorID >0) THEN + eSlitPairState := E_SlitPairStates.ERROR; END_IF E_SlitPairStates.HOME_GAP: //"Home" the virtual axes @@ -111,8 +131,9 @@ CASE eSlitPairState OF eSlitPairState := E_SlitPairStates.CHECK_GAP_HOME_COMPLETE; E_SlitPairStates.CHECK_GAP_HOME_COMPLETE: //Wait for virtual homing completion - IF bGapHomed THEN + IF bGapHomed AND NOT GVL.astAxes[iGapSize].stStatus.bBusy AND NOT GVL.astAxes[iGapCentre].stStatus.bBusy THEN eSlitPairState := E_SlitPairStates.GEARIN_SLITS; + bHomingRequested := FALSE; END_IF E_SlitPairStates.GEARIN_SLITS: //Setup gearing @@ -126,9 +147,15 @@ CASE eSlitPairState OF E_SlitPairStates.SLITS_OPERATIONAL: //SLITS OPERATIONAL - Monitor for any gear outs and re-gear when no busy blades bEnabled := TRUE; - IF NOT bBladesCoupled AND NOT GVL.astAxes[iBladeNegative].stStatus.bBusy AND NOT GVL.astAxes[iBladePositive].stStatus.bBusy THEN + checkSoftLimits(); // Soft limits are updated when axes are stopped + IF (NOT bBladesCoupled OR NOT bEnable) AND NOT GVL.astAxes[iBladeNegative].stStatus.bBusy AND NOT GVL.astAxes[iBladePositive].stStatus.bBusy THEN eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; END_IF + IF (GVL.astAxes[iGapSize].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapSize].stControl.bExecute) OR + (GVL.astAxes[iGapCentre].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapCentre].stControl.bExecute) THEN + eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; + bHomingRequested := TRUE; + END_IF E_SlitPairStates.GEAROUT_BLADES: //Clear amy residual gearing actClearSlitGearing(); @@ -136,20 +163,19 @@ CASE eSlitPairState OF E_SlitPairStates.CHECK_GEAROUT_COMPLETE: //Check gearing cleared IF bBladesUncoupled THEN - eSlitPairState := E_SlitPairStates.CLEAR_GAP_CALIBRATION; //Back to homing, this ensures the setpoint position of the axis is updated. - END_IF - - E_SlitPairStates.CLEAR_GAP_CALIBRATION: - mcHomeGapSize.Execute := TRUE; - mcHomeGapCentre.Execute := TRUE; - IF mcHomeGapSize.Done AND mcHomeGapCentre.Done THEN - eSlitPairState := E_SlitPairStates.HOME_GAP; //Back to homing, this ensures the setpoint position of the axis is updated. + IF bHomingRequested THEN + eSlitPairState := E_SlitPairStates.HOME_BLADES; + bEnabled := FALSE; + ELSE + eSlitPairState := E_SlitPairStates.INIT; + END_IF END_IF E_SlitPairStates.ERROR: //ERROR STATE resetCounterTimeout := 0; bError := TRUE; bEnabled := FALSE; + actStopAxes(); IF bReset THEN bResetting := TRUE; eSlitPairState := E_SlitPairStates.ERROR_GEAROUT; @@ -186,6 +212,7 @@ CASE eSlitPairState OF bResetting := FALSE; END_IF END_CASE + bReset := FALSE; ]]> @@ -196,6 +223,41 @@ GVL.astAxes[iBladeNegative].stControl.eCommand := E_MotionFunctions.eGearOut; GVL.astAxes[iBladePositive].stControl.eCommand := E_MotionFunctions.eGearOut; GVL.astAxes[iBladeNegative].stControl.bExecute := TRUE; GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; +]]> + + + + + @@ -206,15 +268,18 @@ IF bResetting THEN //ignore setting in error state if FB going through a reset RETURN; END_IF +// RESET - Use the reset from the virtual axes in order to reset the slits +bReset := GVL.astAxes[iGapCentre].stControl.bReset OR GVL.astAxes[iGapSize].stControl.bReset; + IF NOT bError AND bAxisErrorsPresent THEN eSlitPairState := E_SlitPairStates.ERROR; END_IF -IF eSlitPairState <> E_SlitPairStates.INIT AND NOT bAxesEnabled THEN - eSlitPairState := E_SlitPairStates.ERROR; -END_IF -IF (eSlitPairState <> E_SlitPairStates.INIT AND NOT bFunctionInErrorState) AND NOT bEnable THEN - eSlitPairState := E_SlitPairStates.ERROR; -END_IF +//IF eSlitPairState <> E_SlitPairStates.INIT AND NOT bAxesEnabled THEN +// eSlitPairState := E_SlitPairStates.ERROR; +//END_IF +//IF (eSlitPairState <> E_SlitPairStates.INIT AND NOT bFunctionInErrorState) AND NOT bEnable THEN +// eSlitPairState := E_SlitPairStates.ERROR; +//END_IF IF bEnabled AND NOT bBladesHomed THEN eSlitPairState := E_SlitPairStates.ERROR; END_IF @@ -224,11 +289,19 @@ END_IF +GVL.astAxes[iGapSize].stInputs.bLimitBwd := GVL.astAxes[iBladeNegative].stInputs.bLimitFwd OR GVL.astAxes[iBladePositive].stInputs.bLimitBwd; +GVL.astAxes[iGapSize].stInputs.bLimitFwd := GVL.astAxes[iBladeNegative].stInputs.bLimitBwd OR GVL.astAxes[iBladePositive].stInputs.bLimitFwd;; +GVL.astAxes[iGapCentre].stInputs.bLimitBwd := GVL.astAxes[iBladeNegative].stInputs.bLimitFwd OR GVL.astAxes[iBladePositive].stInputs.bLimitBwd;; +GVL.astAxes[iGapCentre].stInputs.bLimitFwd :=GVL.astAxes[iBladeNegative].stInputs.bLimitBwd OR GVL.astAxes[iBladePositive].stInputs.bLimitFwd;;]]> + + + + + = GVL.astAxes[iBladePositive].stStatus.fActPosition + OR GVL.astAxes[iBladeNegative].stControl.fPosition >= GVL.astAxes[iBladePositive].stStatus.fActPosition ; +GVL.astAxes[iBladePositive].stControl.bInterlockBwd := GVL.astAxes[iBladePositive].stStatus.fActPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition + OR GVL.astAxes[iBladePositive].stControl.fPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition ;]]> @@ -260,6 +333,68 @@ GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; ]]> + + + + + + + + = 0.0 THEN + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); + ELSE + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); + END_IF + END_IF + +E_SlitSoftLimits.WRITE_GAP_SIZE_FWD: //WRITE GAP SIZE FWD SOFT LIMIT DONE. + + IF GVL.astAxes[iGapSize].stStatus.bDone AND NOT GVL.astAxes[iGapSize].stControl.bExecute THEN + eSoftLimitsUpdate := E_SlitSoftLimits.START; + bUpdateSoftLimits := FALSE; + END_IF + +END_CASE]]> + + +END_IF]]> @@ -409,6 +543,40 @@ END_IF ]]> + + + + + + + + + + + + Date: Fri, 12 Sep 2025 14:46:04 +0200 Subject: [PATCH 2/8] formating fix --- POUs/Motion/FB_SlitPair.TcPOU | 221 ++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 107 deletions(-) diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index 0f2d221c..65c1c919 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -11,7 +11,7 @@ VAR_INPUT bReset: BOOL; //Reset the slit set fEncoderScaling: LREAL := 10000; //default scaling denominator of 10000 bAutoHome: BOOL := TRUE; // Blades homing is automatically done if they are not homed - bAnticolisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently + bAnticolisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently END_VAR VAR_OUTPUT @@ -25,7 +25,7 @@ VAR //Internal statuses for logic bResetting: BOOL := FALSE; //TRUE if axis going through a reset bAxesEnabled: BOOL := FALSE; //TRUE if all axes enabled - bSlitsHomed : BOOL := FALSE; //TRUE if all axes Homed after reboot + bSlitsHomed : BOOL := FALSE; //TRUE if all axes Homed after reboot bBladesHomed: BOOL:= FALSE; //TRUE if blade axes are calibrated bGapHomed: BOOL:= FALSE; //TRUE if virtual axes are calibrated bBladesCoupled: BOOL:= FALSE; //TRUE if both blade axes are coupled @@ -37,17 +37,18 @@ VAR fGapCentrePosition: LREAL; iGapCentrePosition AT %Q*: UDINT := 0; resetCounterTimeout: UINT :=0; - eSoftLimitsUpdate: E_SlitSoftLimits := E_SlitSoftLimits.START; // Sequence steps for update of soft limits - fbNoMovingRising: R_TRIG; - fbInOpRising: R_TRIG; - bUpdateSoftLimits: BOOL := FALSE; - bHomingRequested: BOOL := FALSE; - fbEnableRising: R_TRIG; - fbStopRising: R_TRIG; - fbDisableRising: R_TRIG; - fbDisabledRising: R_TRIG; - fbHomingRising: R_TRIG; -END_VAR]]> + eSoftLimitsUpdate: E_SlitSoftLimits := E_SlitSoftLimits.START; // Sequence steps for update of soft limits + fbNoMovingRising: R_TRIG; + fbInOpRising: R_TRIG; + bUpdateSoftLimits: BOOL := FALSE; + bHomingRequested: BOOL := FALSE; + fbEnableRising: R_TRIG; + fbStopRising: R_TRIG; + fbDisableRising: R_TRIG; + fbDisabledRising: R_TRIG; + fbHomingRising: R_TRIG; +END_VAR +]]> 0) OR (GVL.astAxes[iBladePositive].stStatus.nErrorID >0) THEN - eSlitPairState := E_SlitPairStates.ERROR; + ELSIF (GVL.astAxes[iBladeNegative].stStatus.nErrorID > 0) OR (GVL.astAxes[iBladePositive].stStatus.nErrorID >0) THEN + eSlitPairState := E_SlitPairStates.ERROR; END_IF E_SlitPairStates.HOME_GAP: //"Home" the virtual axes @@ -133,7 +134,7 @@ CASE eSlitPairState OF E_SlitPairStates.CHECK_GAP_HOME_COMPLETE: //Wait for virtual homing completion IF bGapHomed AND NOT GVL.astAxes[iGapSize].stStatus.bBusy AND NOT GVL.astAxes[iGapCentre].stStatus.bBusy THEN eSlitPairState := E_SlitPairStates.GEARIN_SLITS; - bHomingRequested := FALSE; + bHomingRequested := FALSE; END_IF E_SlitPairStates.GEARIN_SLITS: //Setup gearing @@ -147,15 +148,15 @@ CASE eSlitPairState OF E_SlitPairStates.SLITS_OPERATIONAL: //SLITS OPERATIONAL - Monitor for any gear outs and re-gear when no busy blades bEnabled := TRUE; - checkSoftLimits(); // Soft limits are updated when axes are stopped + checkSoftLimits(); // Soft limits are updated when axes are stopped IF (NOT bBladesCoupled OR NOT bEnable) AND NOT GVL.astAxes[iBladeNegative].stStatus.bBusy AND NOT GVL.astAxes[iBladePositive].stStatus.bBusy THEN eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; END_IF - IF (GVL.astAxes[iGapSize].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapSize].stControl.bExecute) OR - (GVL.astAxes[iGapCentre].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapCentre].stControl.bExecute) THEN - eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; - bHomingRequested := TRUE; - END_IF + IF (GVL.astAxes[iGapSize].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapSize].stControl.bExecute) OR + (GVL.astAxes[iGapCentre].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapCentre].stControl.bExecute) THEN + eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; + bHomingRequested := TRUE; + END_IF E_SlitPairStates.GEAROUT_BLADES: //Clear amy residual gearing actClearSlitGearing(); @@ -163,19 +164,19 @@ CASE eSlitPairState OF E_SlitPairStates.CHECK_GEAROUT_COMPLETE: //Check gearing cleared IF bBladesUncoupled THEN - IF bHomingRequested THEN - eSlitPairState := E_SlitPairStates.HOME_BLADES; - bEnabled := FALSE; - ELSE - eSlitPairState := E_SlitPairStates.INIT; - END_IF + IF bHomingRequested THEN + eSlitPairState := E_SlitPairStates.HOME_BLADES; + bEnabled := FALSE; + ELSE + eSlitPairState := E_SlitPairStates.INIT; + END_IF END_IF E_SlitPairStates.ERROR: //ERROR STATE resetCounterTimeout := 0; bError := TRUE; bEnabled := FALSE; - actStopAxes(); + actStopAxes(); IF bReset THEN bResetting := TRUE; eSlitPairState := E_SlitPairStates.ERROR_GEAROUT; @@ -233,11 +234,11 @@ GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; fbEnableRising(CLK := GVL.astAxes[iGapSize].stControl.bEnable OR GVL.astAxes[iGapCentre].stControl.bEnable ); IF fbEnableRising.Q THEN - GVL.astAxes[iBladePositive].stControl.bEnable := TRUE; - GVL.astAxes[iBladeNegative].stControl.bEnable := TRUE; - GVL.astAxes[iGapSize].stControl.bEnable := TRUE; - GVL.astAxes[iGapCentre].stControl.bEnable := TRUE; - bEnable := TRUE; + GVL.astAxes[iBladePositive].stControl.bEnable := TRUE; + GVL.astAxes[iBladeNegative].stControl.bEnable := TRUE; + GVL.astAxes[iGapSize].stControl.bEnable := TRUE; + GVL.astAxes[iGapCentre].stControl.bEnable := TRUE; + bEnable := TRUE; END_IF @@ -245,19 +246,19 @@ END_IF fbDisableRising(CLK := NOT GVL.astAxes[iGapSize].stControl.bEnable OR NOT GVL.astAxes[iGapCentre].stControl.bEnable ); IF fbDisableRising.Q THEN - GVL.astAxes[iBladePositive].stControl.bEnable := FALSE; - GVL.astAxes[iBladeNegative].stControl.bEnable := FALSE; - GVL.astAxes[iGapSize].stControl.bEnable := FALSE; - GVL.astAxes[iGapCentre].stControl.bEnable := FALSE; + GVL.astAxes[iBladePositive].stControl.bEnable := FALSE; + GVL.astAxes[iBladeNegative].stControl.bEnable := FALSE; + GVL.astAxes[iGapSize].stControl.bEnable := FALSE; + GVL.astAxes[iGapCentre].stControl.bEnable := FALSE; END_IF // Set Enable flag when all axes are enabled -bEnable := GVL.astAxes[iBladePositive].stStatus.bEnabled AND GVL.astAxes[iBladeNegative].stStatus.bEnabled - AND GVL.astAxes[iGapSize].stStatus.bEnabled AND GVL.astAxes[iGapCentre].stStatus.bEnabled; +bEnable := GVL.astAxes[iBladePositive].stStatus.bEnabled AND GVL.astAxes[iBladeNegative].stStatus.bEnabled + AND GVL.astAxes[iGapSize].stStatus.bEnabled AND GVL.astAxes[iGapCentre].stStatus.bEnabled; -// Set flag when all axis are disable -fbDisabledRising(CLK := NOT GVL.astAxes[iBladePositive].stStatus.bEnabled AND GVL.astAxes[iBladeNegative].stStatus.bEnabled - AND GVL.astAxes[iGapSize].stStatus.bEnabled AND GVL.astAxes[iGapCentre].stStatus.bEnabled); +// Set flag when all axis are disable +fbDisabledRising(CLK := NOT GVL.astAxes[iBladePositive].stStatus.bEnabled AND GVL.astAxes[iBladeNegative].stStatus.bEnabled + AND GVL.astAxes[iGapSize].stStatus.bEnabled AND GVL.astAxes[iGapCentre].stStatus.bEnabled); ]]> @@ -292,16 +293,18 @@ END_IF GVL.astAxes[iGapSize].stInputs.bLimitBwd := GVL.astAxes[iBladeNegative].stInputs.bLimitFwd OR GVL.astAxes[iBladePositive].stInputs.bLimitBwd; GVL.astAxes[iGapSize].stInputs.bLimitFwd := GVL.astAxes[iBladeNegative].stInputs.bLimitBwd OR GVL.astAxes[iBladePositive].stInputs.bLimitFwd;; GVL.astAxes[iGapCentre].stInputs.bLimitBwd := GVL.astAxes[iBladeNegative].stInputs.bLimitFwd OR GVL.astAxes[iBladePositive].stInputs.bLimitBwd;; -GVL.astAxes[iGapCentre].stInputs.bLimitFwd :=GVL.astAxes[iBladeNegative].stInputs.bLimitBwd OR GVL.astAxes[iBladePositive].stInputs.bLimitFwd;;]]> +GVL.astAxes[iGapCentre].stInputs.bLimitFwd :=GVL.astAxes[iBladeNegative].stInputs.bLimitBwd OR GVL.astAxes[iBladePositive].stInputs.bLimitFwd;; +]]> = GVL.astAxes[iBladePositive].stStatus.fActPosition - OR GVL.astAxes[iBladeNegative].stControl.fPosition >= GVL.astAxes[iBladePositive].stStatus.fActPosition ; -GVL.astAxes[iBladePositive].stControl.bInterlockBwd := GVL.astAxes[iBladePositive].stStatus.fActPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition - OR GVL.astAxes[iBladePositive].stControl.fPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition ;]]> + OR GVL.astAxes[iBladeNegative].stControl.fPosition >= GVL.astAxes[iBladePositive].stStatus.fActPosition ; +GVL.astAxes[iBladePositive].stControl.bInterlockBwd := GVL.astAxes[iBladePositive].stStatus.fActPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition + OR GVL.astAxes[iBladePositive].stControl.fPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition ; +]]> @@ -351,48 +354,49 @@ GVL.astAxes[iGapCentre].stControl.bStop := TRUE; CASE eSoftLimitsUpdate OF E_SlitSoftLimits.START: //START SEQ Software limit center gap fwd (When not busy start) - IF NOT GVL.astAxes[iGapCentre].stStatus.bBusy AND NOT GVL.astAxes[iGapSize].stStatus.bBusy THEN - eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_CENTRE_FWD; - GVL.astAxes[iGapCentre].stControl.bExecute := TRUE; - GVL.astAxes[iGapCentre].stControl.eCommand := E_MotionFunctions.eWriteParameter; - GVL.astAxes[iGapCentre].stConfig.eAxisParameters := E_AxisParameters.SWLimitForward; - GVL.astAxes[iGapCentre].stConfig.fWriteAxisParameter := (GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit - - GVL.astAxes[iGapSize].stStatus.fActPosition/2); - END_IF - + IF NOT GVL.astAxes[iGapCentre].stStatus.bBusy AND NOT GVL.astAxes[iGapSize].stStatus.bBusy THEN + eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_CENTRE_FWD; + GVL.astAxes[iGapCentre].stControl.bExecute := TRUE; + GVL.astAxes[iGapCentre].stControl.eCommand := E_MotionFunctions.eWriteParameter; + GVL.astAxes[iGapCentre].stConfig.eAxisParameters := E_AxisParameters.SWLimitForward; + GVL.astAxes[iGapCentre].stConfig.fWriteAxisParameter := (GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit + - GVL.astAxes[iGapSize].stStatus.fActPosition/2); + END_IF + E_SlitSoftLimits.WRITE_GAP_CENTRE_FWD: //WRITE GAP CENTRE FWD SOFT LIMIT DONE. Calculate software limit center gap bwd - IF GVL.astAxes[iGapCentre].stStatus.bDone AND NOT GVL.astAxes[iGapCentre].stControl.bExecute THEN - eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_CENTRE_BWD; - GVL.astAxes[iGapCentre].stControl.bExecute := TRUE; - GVL.astAxes[iGapCentre].stControl.eCommand := E_MotionFunctions.eWriteParameter; - GVL.astAxes[iGapCentre].stConfig.eAxisParameters := E_AxisParameters.SWLimitBackward; - GVL.astAxes[iGapCentre].stConfig.fWriteAxisParameter := (GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit - + GVL.astAxes[iGapSize].stStatus.fActPosition/2); - END_IF - + IF GVL.astAxes[iGapCentre].stStatus.bDone AND NOT GVL.astAxes[iGapCentre].stControl.bExecute THEN + eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_CENTRE_BWD; + GVL.astAxes[iGapCentre].stControl.bExecute := TRUE; + GVL.astAxes[iGapCentre].stControl.eCommand := E_MotionFunctions.eWriteParameter; + GVL.astAxes[iGapCentre].stConfig.eAxisParameters := E_AxisParameters.SWLimitBackward; + GVL.astAxes[iGapCentre].stConfig.fWriteAxisParameter := (GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit + + GVL.astAxes[iGapSize].stStatus.fActPosition/2); + END_IF + E_SlitSoftLimits.WRITE_GAP_CENTRE_BWD: //WRITE GAP CENTRE BWD SOFT LIMIT DONE. Calculate software limit gap size fwd - IF GVL.astAxes[iGapCentre].stStatus.bDone AND NOT GVL.astAxes[iGapCentre].stControl.bExecute THEN - eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_SIZE_FWD; - GVL.astAxes[iGapSize].stControl.bExecute := TRUE; - GVL.astAxes[iGapSize].stControl.eCommand := E_MotionFunctions.eWriteParameter; - GVL.astAxes[iGapSize].stConfig.eAxisParameters := E_AxisParameters.SWLimitForward; - IF GVL.astAxes[iGapCentre].stStatus.fActPosition >= 0.0 THEN - GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit - - GVL.astAxes[iGapCentre].stStatus.fActPosition); - ELSE - GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit - - GVL.astAxes[iGapCentre].stStatus.fActPosition); - END_IF - END_IF - + IF GVL.astAxes[iGapCentre].stStatus.bDone AND NOT GVL.astAxes[iGapCentre].stControl.bExecute THEN + eSoftLimitsUpdate := E_SlitSoftLimits.WRITE_GAP_SIZE_FWD; + GVL.astAxes[iGapSize].stControl.bExecute := TRUE; + GVL.astAxes[iGapSize].stControl.eCommand := E_MotionFunctions.eWriteParameter; + GVL.astAxes[iGapSize].stConfig.eAxisParameters := E_AxisParameters.SWLimitForward; + IF GVL.astAxes[iGapCentre].stStatus.fActPosition >= 0.0 THEN + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); + ELSE + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); + END_IF + END_IF + E_SlitSoftLimits.WRITE_GAP_SIZE_FWD: //WRITE GAP SIZE FWD SOFT LIMIT DONE. - - IF GVL.astAxes[iGapSize].stStatus.bDone AND NOT GVL.astAxes[iGapSize].stControl.bExecute THEN - eSoftLimitsUpdate := E_SlitSoftLimits.START; - bUpdateSoftLimits := FALSE; - END_IF -END_CASE]]> + IF GVL.astAxes[iGapSize].stStatus.bDone AND NOT GVL.astAxes[iGapSize].stControl.bExecute THEN + eSoftLimitsUpdate := E_SlitSoftLimits.START; + bUpdateSoftLimits := FALSE; + END_IF + +END_CASE +]]> @@ -497,7 +501,8 @@ END_VAR END_IF IF NOT GVL.astAxes[iBladePositive].stStatus.bHomed THEN bOutput := FALSE; -END_IF]]> +END_IF +]]> @@ -552,11 +557,12 @@ VAR_OUTPUT END_VAR ]]> - + bSlitsHomed := TRUE; +END_IF +]]> @@ -569,12 +575,13 @@ END_VAR fbInOpRising(CLK := eSlitPairState = E_SlitPairStates.SLITS_OPERATIONAL); IF fbNoMovingRising.Q OR fbInOpRising.Q THEN - bUpdateSoftLimits := TRUE; + bUpdateSoftLimits := TRUE; END_IF IF bUpdateSoftLimits THEN - actUpdateSoftLimits(); -END_IF]]> + actUpdateSoftLimits(); +END_IF +]]> From 130915b76aae7b141bd395dcd96623652c0dc5b3 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Fri, 12 Sep 2025 16:31:49 +0200 Subject: [PATCH 3/8] FB_Axis update, take away multiaxes 3 and 4 to avoid issue coupling issues --- POUs/Motion/FB_Axis.TcPOU | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/POUs/Motion/FB_Axis.TcPOU b/POUs/Motion/FB_Axis.TcPOU index 4689df3d..1ccb0f3f 100644 --- a/POUs/Motion/FB_Axis.TcPOU +++ b/POUs/Motion/FB_Axis.TcPOU @@ -638,8 +638,8 @@ IF _stAxis.stControl.eCommand = E_MotionFunctions.eGearInMultiMaster AND _stAxis //Transfer gear ratios to FB fbGearInMultiMaster.GearRatio1 := _stAxis.stConfig.astMultiMasterAxisLatched[1].fRatio; fbGearInMultiMaster.GearRatio2 := _stAxis.stConfig.astMultiMasterAxisLatched[2].fRatio; - fbGearInMultiMaster.GearRatio3 := _stAxis.stConfig.astMultiMasterAxisLatched[3].fRatio; - fbGearInMultiMaster.GearRatio4 := _stAxis.stConfig.astMultiMasterAxisLatched[4].fRatio; +// fbGearInMultiMaster.GearRatio3 := _stAxis.stConfig.astMultiMasterAxisLatched[3].fRatio; (Not in use, commented due to slits code) +// fbGearInMultiMaster.GearRatio4 := _stAxis.stConfig.astMultiMasterAxisLatched[4].fRatio; (Not in use, commented due to slits code) fbGearInMultiMaster.Enable := TRUE; END_IF From 149481773215f57bd5ce6d9296ce673c71053c33 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Fri, 19 Sep 2025 15:41:40 +0200 Subject: [PATCH 4/8] enable and reset out of the inputs var --- POUs/Motion/FB_SlitPair.TcPOU | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index 65c1c919..7782b03b 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -7,8 +7,6 @@ VAR_INPUT iBladePositive: UINT; //Axis ID for positively positioned blade iGapSize: UINT; //Axis ID for the size of gap between slit blades iGapCentre: UINT; //Axis ID for the centre position of the gap formed by slit blades - bEnable: BOOL; //Enable/disable the slit set - bReset: BOOL; //Reset the slit set fEncoderScaling: LREAL := 10000; //default scaling denominator of 10000 bAutoHome: BOOL := TRUE; // Blades homing is automatically done if they are not homed bAnticolisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently @@ -23,6 +21,8 @@ VAR eSlitPairState: E_SlitPairStates := E_SlitPairStates.INIT; //statemachine index //Internal statuses for logic + bEnable: BOOL; //Enable/disable the slit set + bReset: BOOL; //Reset the slit set bResetting: BOOL := FALSE; //TRUE if axis going through a reset bAxesEnabled: BOOL := FALSE; //TRUE if all axes enabled bSlitsHomed : BOOL := FALSE; //TRUE if all axes Homed after reboot From 6fc92af102bdae869457fd8bdfdf216c5b309eb3 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Mon, 29 Sep 2025 09:47:54 +0200 Subject: [PATCH 5/8] error report to virtual axis --- POUs/Motion/FB_SlitPair.TcPOU | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index 7782b03b..3e3e21e0 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -275,6 +275,13 @@ bReset := GVL.astAxes[iGapCentre].stControl.bReset OR GVL.astAxes[iGapSize].stCo IF NOT bError AND bAxisErrorsPresent THEN eSlitPairState := E_SlitPairStates.ERROR; END_IF + +// Report error to virtual axes +IF eSlitPairState = E_SlitPairStates.ERROR THEN + GVL.astAxes[iGapCentre].stStatus.bError := TRUE; + GVL.astAxes[iGapSize].stStatus.bError := TRUE; +END_IF + //IF eSlitPairState <> E_SlitPairStates.INIT AND NOT bAxesEnabled THEN // eSlitPairState := E_SlitPairStates.ERROR; //END_IF From 103aed96d2b102da2fb5bd33d4c565a7c706b3a5 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Fri, 10 Oct 2025 14:02:47 +0200 Subject: [PATCH 6/8] multimaster index 3&4 not used, gear out if axes disabled --- POUs/Motion/FB_Axis.TcPOU | 6 +++--- POUs/Motion/FB_SlitPair.TcPOU | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/POUs/Motion/FB_Axis.TcPOU b/POUs/Motion/FB_Axis.TcPOU index 1ccb0f3f..5955d21b 100644 --- a/POUs/Motion/FB_Axis.TcPOU +++ b/POUs/Motion/FB_Axis.TcPOU @@ -645,9 +645,9 @@ END_IF fbGearInMultiMaster(Slave := _stAxis.Axis, Master1 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[1].nIndex].Axis, - Master2 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[2].nIndex].Axis, - Master3 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[3].nIndex].Axis, - Master4 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[4].nIndex].Axis); + Master2 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[2].nIndex].Axis); +// Master3 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[3].nIndex].Axis, +// Master4 := GVL.astAxes[_stAxis.stConfig.astMultiMasterAxisLatched[4].nIndex].Axis); fbGearInMultiMaster.Enable:= FALSE; IF fbGearInMultiMaster.InGear THEN diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index 3e3e21e0..d0d05761 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -144,6 +144,8 @@ CASE eSlitPairState OF E_SlitPairStates.CHECK_GEARIN_SLITS_COMPLETE: //Wait for gearing complete IF bBladesCoupled THEN eSlitPairState := E_SlitPairStates.SLITS_OPERATIONAL; + ELSIF NOT GVL.astAxes[iGapSize].stStatus.bEnabled AND NOT GVL.astAxes[iGapCentre].stStatus.bEnabled THEN + eSlitPairState := E_SlitPairStates.ERROR_GEAROUT; END_IF E_SlitPairStates.SLITS_OPERATIONAL: //SLITS OPERATIONAL - Monitor for any gear outs and re-gear when no busy blades From f80d61cf7a6e3f09ec3e5bd4dc9a49ab06dc3f41 Mon Sep 17 00:00:00 2001 From: rubenmess Date: Mon, 24 Nov 2025 08:23:19 +0100 Subject: [PATCH 7/8] SOFT LIMITS FUNCTION UPDATE Update soft limits to have a better understanding of the sequence. New step finish added --- DUTs/E_SlitSoftLimits.TcDUT | 3 ++- POUs/Motion/FB_SlitPair.TcPOU | 44 ++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/DUTs/E_SlitSoftLimits.TcDUT b/DUTs/E_SlitSoftLimits.TcDUT index 97e44d26..c2610442 100644 --- a/DUTs/E_SlitSoftLimits.TcDUT +++ b/DUTs/E_SlitSoftLimits.TcDUT @@ -8,7 +8,8 @@ TYPE E_SlitSoftLimits : START := 0, WRITE_GAP_CENTRE_FWD, WRITE_GAP_CENTRE_BWD, - WRITE_GAP_SIZE_FWD + WRITE_GAP_SIZE_FWD, + FINISH ); END_TYPE ]]> diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index d0d05761..24bdaf68 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -9,7 +9,7 @@ VAR_INPUT iGapCentre: UINT; //Axis ID for the centre position of the gap formed by slit blades fEncoderScaling: LREAL := 10000; //default scaling denominator of 10000 bAutoHome: BOOL := TRUE; // Blades homing is automatically done if they are not homed - bAnticolisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently + bAnticollisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently END_VAR VAR_OUTPUT @@ -50,8 +50,7 @@ VAR END_VAR ]]> - @@ -271,14 +270,14 @@ IF bResetting THEN //ignore setting in error state if FB going through a reset RETURN; END_IF -// RESET - Use the reset from the virtual axes in order to reset the slits +//RESET - Use the reset from the virtual axes in order to reset the slits bReset := GVL.astAxes[iGapCentre].stControl.bReset OR GVL.astAxes[iGapSize].stControl.bReset; IF NOT bError AND bAxisErrorsPresent THEN eSlitPairState := E_SlitPairStates.ERROR; END_IF -// Report error to virtual axes +//Report error to virtual axes IF eSlitPairState = E_SlitPairStates.ERROR THEN GVL.astAxes[iGapCentre].stStatus.bError := TRUE; GVL.astAxes[iGapSize].stStatus.bError := TRUE; @@ -347,7 +346,7 @@ GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; - - - Date: Fri, 12 Dec 2025 09:10:37 +0100 Subject: [PATCH 8/8] Fix formatting and spelling Aligns the FB_SlitPair with the coding style guide. Removes unused VAR_INPUTRemoves unused VAR_INPUT. Corrects spelling. --- POUs/Motion/FB_SlitPair.TcPOU | 74 +++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index 24bdaf68..78c2b4a4 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -8,8 +8,8 @@ VAR_INPUT iGapSize: UINT; //Axis ID for the size of gap between slit blades iGapCentre: UINT; //Axis ID for the centre position of the gap formed by slit blades fEncoderScaling: LREAL := 10000; //default scaling denominator of 10000 - bAutoHome: BOOL := TRUE; // Blades homing is automatically done if they are not homed - bAnticollisionEnable : BOOL := FALSE; // Blades anticolision option, only for when blades are moved independiently + bAutoHome: BOOL := TRUE; //Blades homing is automatically done if they are not homed + bAnticollisionEnable: BOOL := FALSE; //Blades anticollision option, only for when blades are moved independently END_VAR VAR_OUTPUT @@ -25,7 +25,7 @@ VAR bReset: BOOL; //Reset the slit set bResetting: BOOL := FALSE; //TRUE if axis going through a reset bAxesEnabled: BOOL := FALSE; //TRUE if all axes enabled - bSlitsHomed : BOOL := FALSE; //TRUE if all axes Homed after reboot + bSlitsHomed: BOOL := FALSE; //TRUE if all axes Homed after reboot bBladesHomed: BOOL:= FALSE; //TRUE if blade axes are calibrated bGapHomed: BOOL:= FALSE; //TRUE if virtual axes are calibrated bBladesCoupled: BOOL:= FALSE; //TRUE if both blade axes are coupled @@ -37,7 +37,7 @@ VAR fGapCentrePosition: LREAL; iGapCentrePosition AT %Q*: UDINT := 0; resetCounterTimeout: UINT :=0; - eSoftLimitsUpdate: E_SlitSoftLimits := E_SlitSoftLimits.START; // Sequence steps for update of soft limits + eSoftLimitsUpdate: E_SlitSoftLimits := E_SlitSoftLimits.START; //Sequence steps for update of soft limits fbNoMovingRising: R_TRIG; fbInOpRising: R_TRIG; bUpdateSoftLimits: BOOL := FALSE; @@ -68,7 +68,7 @@ actGapLimits(); //Set virtual axis limits to TRUE actVirtualAxisPositions(); //Virtual axis encoder position subroutine actRunMethods(); //Update statuses actEnableAxes(); //Enable the axes -checkSlitsHomed(); // Status of the axes homing +checkSlitsHomed(); //Status of the axes homing IF bAnticollisionEnable THEN //Blades anticollision enabled actInterlocking(); END_IF @@ -154,7 +154,7 @@ CASE eSlitPairState OF eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; END_IF IF (GVL.astAxes[iGapSize].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapSize].stControl.bExecute) OR - (GVL.astAxes[iGapCentre].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapCentre].stControl.bExecute) THEN + (GVL.astAxes[iGapCentre].stControl.eCommand = E_MotionFunctions.eHome AND GVL.astAxes[iGapCentre].stControl.bExecute) THEN eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; bHomingRequested := TRUE; END_IF @@ -230,11 +230,10 @@ GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; - @@ -297,21 +296,21 @@ END_IF - - = GVL.astAxes[iBladePositive].stStatus.fActPosition - OR GVL.astAxes[iBladeNegative].stControl.fPosition >= GVL.astAxes[iBladePositive].stStatus.fActPosition ; + OR GVL.astAxes[iBladeNegative].stControl.fPosition >= GVL.astAxes[iBladePositive].stStatus.fActPosition; GVL.astAxes[iBladePositive].stControl.bInterlockBwd := GVL.astAxes[iBladePositive].stStatus.fActPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition - OR GVL.astAxes[iBladePositive].stControl.fPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition ; + OR GVL.astAxes[iBladePositive].stControl.fPosition <= GVL.astAxes[iBladeNegative].stStatus.fActPosition; ]]> @@ -346,7 +345,7 @@ GVL.astAxes[iBladePositive].stControl.bExecute := TRUE; - - = 0.0 THEN - GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit - - GVL.astAxes[iGapCentre].stStatus.fActPosition); + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladePositive].stConfig.fMaxSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); ELSE - GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit - - GVL.astAxes[iGapCentre].stStatus.fActPosition); + GVL.astAxes[iGapSize].stConfig.fWriteAxisParameter := 2 * ABS(GVL.astAxes[iBladeNegative].stConfig.fMinSoftPosLimit + - GVL.astAxes[iGapCentre].stStatus.fActPosition); END_IF END_IF E_SlitSoftLimits.FINISH: //FINISHED WHEN LAST WRITING OF PARAMETERS IS DONE - IF GVL.astAxes[iGapSize].stStatus.bDone AND NOT GVL.astAxes[iGapSize].stControl.bExecute THEN - eSoftLimitsUpdate := E_SlitSoftLimits.START; - bUpdateSoftLimits := FALSE; + eSoftLimitsUpdate := E_SlitSoftLimits.START; + bUpdateSoftLimits := FALSE; END_IF END_CASE @@ -568,7 +566,11 @@ VAR_OUTPUT END_VAR ]]> -