diff --git a/DUTs/Axis_Structures/ST_AxisParamSpec.TcDUT b/DUTs/Axis_Structures/ST_AxisParamSpec.TcDUT new file mode 100644 index 0000000..ca843cd --- /dev/null +++ b/DUTs/Axis_Structures/ST_AxisParamSpec.TcDUT @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/DUTs/E_AxisParamCheckState.TcDUT b/DUTs/E_AxisParamCheckState.TcDUT new file mode 100644 index 0000000..454580b --- /dev/null +++ b/DUTs/E_AxisParamCheckState.TcDUT @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/DUTs/E_AxisParameters.TcTLEO b/DUTs/E_AxisParameters.TcTLEO index 4c799dd..82c72bc 100644 --- a/DUTs/E_AxisParameters.TcTLEO +++ b/DUTs/E_AxisParameters.TcTLEO @@ -3,6 +3,7 @@ diff --git a/DUTs/E_SlitSoftLimits.TcDUT b/DUTs/E_SlitSoftLimits.TcDUT new file mode 100644 index 0000000..71496e1 --- /dev/null +++ b/DUTs/E_SlitSoftLimits.TcDUT @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/POUs/Motion/FB_SlitPair.TcPOU b/POUs/Motion/FB_SlitPair.TcPOU index adde001..793d10b 100644 --- a/POUs/Motion/FB_SlitPair.TcPOU +++ b/POUs/Motion/FB_SlitPair.TcPOU @@ -1,17 +1,30 @@  - - 0) OR (stBladePositive.stStatus.nErrorID > 0) THEN + eSlitPairState := E_SlitPairStates.eError; END_IF - E_SlitPairStates.HOME_GAP: //"Home" the virtual axes - GVL.astAxes[iGapSize].stConfig.eHomeSeq := E_HomingRoutines.eHomeDirect; - GVL.astAxes[iGapCentre].stConfig.eHomeSeq := E_HomingRoutines.eHomeDirect; - GVL.astAxes[iGapSize].stConfig.fHomePosition := fGapSizePosition; - GVL.astAxes[iGapCentre].stConfig.fHomePosition := fGapCentrePosition; - GVL.astAxes[iGapSize].stControl.eCommand := E_MotionFunctions.eHome; - GVL.astAxes[iGapCentre].stControl.eCommand := E_MotionFunctions.eHome; - GVL.astAxes[iGapSize].stControl.bExecute := TRUE; - GVL.astAxes[iGapCentre].stControl.bExecute := TRUE; - eSlitPairState := E_SlitPairStates.CHECK_GAP_HOME_COMPLETE; - - E_SlitPairStates.CHECK_GAP_HOME_COMPLETE: //Wait for virtual homing completion - IF bGapHomed THEN - eSlitPairState := E_SlitPairStates.GEARIN_SLITS; + E_SlitPairStates.eHomeGap: //"Home" the virtual axes + stGapSize.stConfig.eHomeSeq := E_HomingRoutines.eHomeDirect; + stGapCentre.stConfig.eHomeSeq := E_HomingRoutines.eHomeDirect; + stGapSize.stConfig.fHomePosition := fGapSizePosition; + stGapCentre.stConfig.fHomePosition := fGapCentrePosition; + stGapSize.stControl.eCommand := E_MotionFunctions.eHome; + stGapCentre.stControl.eCommand := E_MotionFunctions.eHome; + stGapSize.stControl.bExecute := TRUE; + stGapCentre.stControl.bExecute := TRUE; + eSlitPairState := E_SlitPairStates.eCheckGapHomeComplete; + + E_SlitPairStates.eCheckGapHomeComplete: //Wait for virtual homing completion + IF bGapHomed AND NOT stGapSize.stStatus.bBusy AND NOT stGapCentre.stStatus.bBusy THEN + eSlitPairState := E_SlitPairStates.eGearInSlits; END_IF - E_SlitPairStates.GEARIN_SLITS: //Setup gearing + E_SlitPairStates.eGearInSlits: //Setup gearing actSetupSlitGearing(); - eSlitPairState := E_SlitPairStates.CHECK_GEARIN_SLITS_COMPLETE; + eSlitPairState := E_SlitPairStates.eCheckGearInSlitsComplete; - E_SlitPairStates.CHECK_GEARIN_SLITS_COMPLETE: //Wait for gearing complete + E_SlitPairStates.eCheckGearInSlitsComplete: //Wait for gearing complete IF bBladesCoupled THEN - eSlitPairState := E_SlitPairStates.SLITS_OPERATIONAL; + eSlitPairState := E_SlitPairStates.eSlitsOperational; + ELSIF NOT stGapSize.stStatus.bEnabled AND NOT stGapCentre.stStatus.bEnabled THEN + eSlitPairState := E_SlitPairStates.eErrorGearOut; END_IF - E_SlitPairStates.SLITS_OPERATIONAL: //SLITS OPERATIONAL - Monitor for any gear outs and re-gear when no busy blades + E_SlitPairStates.eSlitsOperational: //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 - eSlitPairState := E_SlitPairStates.GEAROUT_BLADES; + checkSoftLimits(stGapSize, stGapCentre); //Soft limits are updated when axes are stopped + IF (NOT bBladesCoupled OR NOT bEnable) AND NOT stBladeNegative.stStatus.bBusy AND NOT stBladePositive.stStatus.bBusy THEN + eSlitPairState := E_SlitPairStates.eGearOutBlades; + END_IF + IF (stGapSize.stControl.eCommand = E_MotionFunctions.eHome AND stGapSize.stControl.bExecute) OR + (stGapCentre.stControl.eCommand = E_MotionFunctions.eHome AND stGapCentre.stControl.bExecute) THEN + eSlitPairState := E_SlitPairStates.eGearOutBlades; + bHomingRequested := TRUE; END_IF - E_SlitPairStates.GEAROUT_BLADES: //Clear amy residual gearing + E_SlitPairStates.eGearOutBlades: //Clear any residual gearing actClearSlitGearing(); - eSlitPairState := E_SlitPairStates.CHECK_GEAROUT_COMPLETE; + eSlitPairState := E_SlitPairStates.eCheckGearOutComplete; - E_SlitPairStates.CHECK_GEAROUT_COMPLETE: //Check gearing cleared + E_SlitPairStates.eCheckGearOutComplete: //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. + IF bHomingRequested THEN + eSlitPairState := E_SlitPairStates.eResetCalibration; + bEnabled := FALSE; + ELSE + eSlitPairState := E_SlitPairStates.eInit; + END_IF 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. + E_SlitPairStates.eResetCalibration: + IF checkResetCalibrationDone() THEN + eSlitPairState := E_SlitPairStates.eCheckHomeStatus; + ELSIF checkResetCalibrationFailed() THEN + eSlitPairState := E_SlitPairStates.eError; END_IF - E_SlitPairStates.ERROR: //ERROR STATE - resetCounterTimeout := 0; + E_SlitPairStates.eError: //ERROR STATE + nAutoErrorResetCounter := 0; bError := TRUE; bEnabled := FALSE; + actStopAxes(); IF bReset THEN bResetting := TRUE; - eSlitPairState := E_SlitPairStates.ERROR_GEAROUT; + eSlitPairState := E_SlitPairStates.eErrorGearOut; END_IF - E_SlitPairStates.ERROR_GEAROUT: //Try to clear issues + E_SlitPairStates.eErrorGearOut: //Try to clear issues actClearSlitGearing(); - eSlitPairState := E_SlitPairStates.ERROR_GEAROUT_CHECK; + eSlitPairState := E_SlitPairStates.eErrorGearOutCheck; - E_SlitPairStates.ERROR_GEAROUT_CHECK: + E_SlitPairStates.eErrorGearOutCheck: IF bBladesUncoupled THEN - eSlitPairState := E_SlitPairStates.ERROR_RESET_AXES; //Back to homing, this ensures the setpoint position of the axis is updated. + eSlitPairState := E_SlitPairStates.eErrorResetAxes; END_IF - E_SlitPairStates.ERROR_RESET_AXES: //RESET ALL AXES - GVL.astAxes[iBladeNegative].stControl.bReset := TRUE; - GVL.astAxes[iBladePositive].stControl.bReset := TRUE; - GVL.astAxes[iGapSize].stControl.bReset := TRUE; - GVL.astAxes[iGapCentre].stControl.bReset := TRUE; - resetCounterTimeout := resetCounterTimeout + 1; - eSlitPairState := E_SlitPairStates.ERROR_RESET_CHECK; - - E_SlitPairStates.ERROR_RESET_CHECK: - IF resetCounterTimeout > 10 THEN - eSlitPairState := E_SlitPairStates.ERROR; - bResetting := FALSE; - RETURN; - END_IF + E_SlitPairStates.eErrorResetAxes: //RESET ALL AXES + stBladeNegative.stControl.bReset := TRUE; + stBladePositive.stControl.bReset := TRUE; + stGapSize.stControl.bReset := TRUE; + stGapCentre.stControl.bReset := TRUE; + nAutoErrorResetCounter := nAutoErrorResetCounter + 1; + eSlitPairState := E_SlitPairStates.eErrorResetCheck; + + E_SlitPairStates.eErrorResetCheck: IF bAxisErrorsPresent THEN - eSlitPairState := E_SlitPairStates.ERROR_RESET_AXES; + //If the errors persists after 10 auto reset, then manual intervention is required + IF nAutoErrorResetCounter <= 10 THEN + eSlitPairState := E_SlitPairStates.eErrorResetAxes; + END_IF ELSE - eSlitPairState := E_SlitPairStates.INIT; + eSlitPairState := E_SlitPairStates.eInit; + nAutoErrorResetCounter := 0; bError := FALSE; bResetting := FALSE; END_IF END_CASE + bReset := FALSE; ]]> + + + = (stBladePositive.stStatus.fActPosition - fAnticollisionMargin); + + E_MotionFunctions.eMoveRelative: + stBladeNegative.stControl.bInterlockFwd := stBladeNegative.stControl.bExecute + AND (stBladeNegative.stControl.fPosition + stBladeNegative.stStatus.fActPosition) >= (stBladePositive.stStatus.fActPosition - fAnticollisionMargin); + + ELSE + stBladeNegative.stControl.bInterlockFwd := FALSE; + +END_CASE + +//Check if current position is outside the anticollision margin +stBladeNegative.stControl.bInterlockFwd := + (stBladeNegative.stControl.bInterlockFwd OR stBladeNegative.stStatus.fActPosition >= (stBladePositive.stStatus.fActPosition - fAnticollisionMargin)) + AND bBladesHomed + AND bBladesUncoupled + AND bAnticollisionEnable; + +//Positive Blade + +//If executing absolute / relative movement commands also check target position +CASE stBladePositive.stControl.eCommand OF + + E_MotionFunctions.eMoveAbsolute: + stBladePositive.stControl.bInterlockBwd := stBladePositive.stControl.bExecute + AND stBladePositive.stControl.fPosition <= (stBladeNegative.stStatus.fActPosition + fAnticollisionMargin); + + E_MotionFunctions.eMoveRelative: + stBladePositive.stControl.bInterlockBwd := stBladePositive.stControl.bExecute + AND (stBladePositive.stControl.fPosition + stBladePositive.stStatus.fActPosition) <= (stBladeNegative.stStatus.fActPosition + fAnticollisionMargin); + + ELSE + stBladePositive.stControl.bInterlockBwd := FALSE; + +END_CASE + +//Check if current position is outside the anticollision margin +stBladePositive.stControl.bInterlockBwd := + (stBladePositive.stControl.bInterlockBwd OR stBladePositive.stStatus.fActPosition <= (stBladeNegative.stStatus.fActPosition + fAnticollisionMargin)) + AND bBladesHomed + AND bBladesUncoupled + AND bAnticollisionEnable; +]]> + + + + + + + + + + + + @@ -206,77 +377,156 @@ IF bResetting THEN //ignore setting in error state if FB going through a reset RETURN; END_IF -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; +//RESET - Use the reset from the virtual axes in order to reset the slits +bReset := stGapCentre.stControl.bReset OR stGapSize.stControl.bReset; + +IF NOT bError AND bAxisErrorsPresent AND (stGapCentre.stStatus.bEnabled OR stGapSize.stStatus.bEnabled) THEN + eSlitPairState := E_SlitPairStates.eError; END_IF -IF (eSlitPairState <> E_SlitPairStates.INIT AND NOT bFunctionInErrorState) AND NOT bEnable THEN - eSlitPairState := E_SlitPairStates.ERROR; + +//Report error to virtual axes +IF eSlitPairState = E_SlitPairStates.eError THEN + stGapCentre.stStatus.bError := TRUE; + stGapSize.stStatus.bError := TRUE; END_IF + IF bEnabled AND NOT bBladesHomed THEN - eSlitPairState := E_SlitPairStates.ERROR; + eSlitPairState := E_SlitPairStates.eError; END_IF ]]> - - + - bAxesEnabled); -checkBladesHomed(bOutput => bBladesHomed); -checkVirtualHomed(bOutput => bGapHomed); -checkBladesCoupled(bOutput => bBladesCoupled); -checkBladesUncoupled(bOutput => bBladesUncoupled); -checkAllAxisErrors(bOutput => bAxisErrorsPresent); -checkErrorState(bOutput => bFunctionInErrorState); + - + + + + + + + + + + + - - @@ -285,145 +535,249 @@ END_IF - - + - - - - - - + - - - + + + + + + + - + + + + + + + + + + + + cParameters[iParamCheck].fValue THEN + sWarnMsg := CONCAT( + STR1 := 'Slit virtual axis Gap Size (AxisId=%d) has an invalid parameter of ', + STR2 := TO_STRING(cParameters[iParamCheck].eParam)); + + ADSLOGDINT( + msgCtrlMask := ADSLOG_MSGTYPE_WARN, + msgFmtStr := sWarnMsg, + dintArg := TO_DINT(iGapSize)); + END_IF + //Gap Centre + IF stGapCentre.stConfig.fReadAxisParameter <> cParameters[iParamCheck].fValue THEN + sWarnMsg := CONCAT( + STR1 := 'Slit virtual axis Gap Centre (AxisId=%d) has an invalid parameter of ', + STR2 := TO_STRING(cParameters[iParamCheck].eParam)); + + ADSLOGDINT( + msgCtrlMask := ADSLOG_MSGTYPE_WARN, + msgFmtStr := sWarnMsg, + dintArg := TO_DINT(iGapCentre)); + END_IF + bInvalidParamFound := TRUE; + + eParameterCheck := E_AxisParamCheckState.eNext; + + E_AxisParamCheckState.eNext: + IF iParamCheck = cMaxParams THEN + IF NOT bInvalidParamFound THEN + ADSLOGSTR( + msgCtrlMask := ADSLOG_MSGTYPE_LOG, + msgFmtStr := 'Slit all parameters of both virtual axes are valid', + strArg := ''); + END_IF + eParameterCheck := E_AxisParamCheckState.eFinish; + ELSE + ; + iParamCheck := iParamCheck + 1; + eParameterCheck := E_AxisParamCheckState.eSelectParam; + END_IF + + + E_AxisParamCheckState.eFinish: + ; + +END_CASE ]]>