using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Beckhoff.Station; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Layout; using MECF.Framework.Common.Routine; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.Common.Utilities; using MECF.Framework.Common.WaferHolder; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.AXIS.CANOpen; using CyberX8_RT.Devices.Facilities; using CyberX8_RT.Devices.TransPorter; using CyberX8_RT.Modules.Loader; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.RT.Fsm; namespace CyberX8_RT.Modules.Transporter { public class TransporterTransferRoutine : RoutineBase, IRoutine { private enum TransferStep { CheckPreCondition, PickUpFrom, PickUpFromWait, MoveTo, MoveToWait, Place, PlaceWait, End } #region 内部变量 private string _fromCellName; private string _toCellName; private JetAxisBase _gantryAxis; private JetAxisBase _elevatorAxis; private LoaderEntity _loaderEntity; private JetAxisBase _loaderRotationAxis; private SystemFacilities _facilities; private TransporterPickUpFromRoutine _pickUpRoutine; private TransporterMoveToRoutine _moveToRoutine; private TransporterPickDownToRoutine _placeRoutine; #endregion /// /// 构造函数 /// /// public TransporterTransferRoutine(string module) : base(module) { _pickUpRoutine=new TransporterPickUpFromRoutine(module); _moveToRoutine = new TransporterMoveToRoutine(module); _placeRoutine=new TransporterPickDownToRoutine(module); } /// /// 中止 /// public void Abort() { Runner.Stop("Manual Abort"); } /// /// 监控 /// /// public RState Monitor() { Runner.Run(TransferStep.CheckPreCondition,CheckStartPreConfition,_delay_1ms) //1.1 PickupFrom .Run(TransferStep.PickUpFrom, () => { return _pickUpRoutine.Start(_fromCellName) == RState.Running; }, _delay_1ms) .WaitWithStopCondition(TransferStep.PickUpFromWait, ()=>CommonFunction.CheckRoutineEndState(_pickUpRoutine), ()=> CheckRoutineStopStatus(_pickUpRoutine,"PickUp Routine", _pickUpRoutine.ErrorMsg,0)) //1.2 Move to .Run(TransferStep.MoveTo, () => { return _moveToRoutine.Start(_toCellName) == RState.Running; }, _delay_1ms) .WaitWithStopCondition(TransferStep.MoveToWait, ()=>CommonFunction.CheckRoutineEndState(_moveToRoutine), ()=> CheckRoutineStopStatus(_moveToRoutine,"MoveTo Routine",_moveToRoutine.ErrorMsg,1)) //1.3 Place .Run(TransferStep.Place, () => { return _placeRoutine.Start(_toCellName) == RState.Running; },_delay_1ms) .WaitWithStopCondition(TransferStep.PlaceWait, () => CommonFunction.CheckRoutineEndState(_placeRoutine), ()=> CheckRoutineStopStatus(_placeRoutine,"Place Routine",_placeRoutine.ErrorMsg,2)) .End(TransferStep.End,LastChangeWafer,100); return Runner.Status; } /// /// 检验Routine异常结束状态 /// /// /// private bool CheckRoutineStopStatus(IRoutine routine,string routineName,string errorMsg,int step) { RState ret = routine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { NotifyError(eEvent.ERR_TRANSPORTER, $"Transfer WaferHolder Routine\r\n{routineName}\\r\n{errorMsg}",step); return true; } return false; } /// /// 检验前置条件 /// /// private bool CheckPreCondition() { if(!_gantryAxis.IsSwitchOn) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not switch on ",-1); return false; } if (!_gantryAxis.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not homed ", -1); return false; } if (!_elevatorAxis.IsSwitchOn) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not switch on ",-1); return false; } if (!_elevatorAxis.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not homed ", -1); return false; } return true; } /// /// 最后交换Wafer /// /// private bool LastChangeWafer() { ModuleName sourceModule; if (_fromCellName.ToLower() == "loader") { sourceModule = ModuleName.Loader1; } else { sourceModule = (ModuleName)Enum.Parse(typeof(ModuleName), _fromCellName); } ModuleName destModule; if (_toCellName.ToLower() == "loader") { destModule = ModuleName.Loader1; } else { destModule = (ModuleName)Enum.Parse(typeof(ModuleName), _toCellName); } if (WaferManager.Instance.CheckHasWafer(sourceModule, 0)) { WaferManager.Instance.WaferMoved(sourceModule, 0, destModule, 0); } if (WaferManager.Instance.CheckHasWafer(sourceModule, 1)) { WaferManager.Instance.WaferMoved(sourceModule, 1, destModule, 1); } return true; } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _fromCellName = objs[0].ToString(); _toCellName = objs[1].ToString(); InitializeParameters(); return Runner.Start(Module, $"Transfer from {_fromCellName} to {_toCellName}"); } /// /// 初始化参数 /// private void InitializeParameters() { _elevatorAxis = DEVICE.GetDevice($"{Module}.Elevator"); _gantryAxis = DEVICE.GetDevice($"{Module}.Gantry"); _loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString()); _loaderRotationAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Rotation"); _facilities = DEVICE.GetDevice("System.Facilities"); } /// /// 启动校验条件 /// /// private bool CheckStartPreConfition() { if(!CheckPreCondition()) { return false; } double elevatorPosition = _elevatorAxis.MotionData.MotorPosition; if (!_elevatorAxis.CheckPositionIsInStation(elevatorPosition, "Up") && !_elevatorAxis.CheckPositionIsInStation(elevatorPosition,"Low")) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis {elevatorPosition} is not in Up or Low station",-1); return false; } if (!_loaderEntity.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} is not homed", -1); return false; } if (_toCellName == "Loader" || _fromCellName == "Loader") { double loaderRotationPosition = _loaderRotationAxis.MotionData.MotorPosition; if (!_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPA") && !_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPB")) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} rotation axis {loaderRotationPosition} is not int TRNPA or TRNPB station", -1); return false; } } if (WaferHolderManager.Instance.HasWaferHolder(Module)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} has wafer shuttle", -1); return false; } if (!WaferHolderManager.Instance.HasWaferHolder(_fromCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_fromCellName} does not has wafer shuttle", -1); return false; } if (WaferHolderManager.Instance.HasWaferHolder(_toCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_toCellName} already has wafer shuttle",-1); return false; } //检验Facilities var faciltiesResult = _facilities.CheckCDA(); if (!faciltiesResult.result) { NotifyError(eEvent.ERR_TRANSPORTER, faciltiesResult.reason, -1); return false; } return true; } /// /// 重试 /// /// public RState Retry(int step) { InitializeParameters(); if(string.IsNullOrEmpty(_fromCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, "source cell is empty", step); return RState.Failed; } if (string.IsNullOrEmpty(_toCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, "target cell is empty", step); return RState.Failed; } List preStepIds = new List(); if (step == 0 || step == -1) { return Runner.Retry(TransferStep.CheckPreCondition, preStepIds, Module, "Transfer Retry"); } else if(step==1) { AddPreSteps(TransferStep.MoveTo, preStepIds); return Runner.Retry(TransferStep.MoveTo, preStepIds, Module, $"Transfer step {TransferStep.MoveTo} Retry"); } else { AddPreSteps(TransferStep.Place, preStepIds); return Runner.Retry(TransferStep.Place, preStepIds, Module, $"Transfer step {TransferStep.Place} Retry"); } } /// /// 忽略前 /// /// /// private void AddPreSteps(TransferStep step, List preStepIds) { for (int i = 0; i < (int)step; i++) { preStepIds.Add((TransferStep)i); } } /// /// 检验前面完成状态 /// /// public bool CheckCompleteCondition(int index) { TransporterEntity transporterEntity = Singleton.Instance.GetModule(Module); if (transporterEntity.WaferHolderInfo != null) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} has waferholder", index); return false; } if(!WaferHolderManager.Instance.HasWaferHolder(_toCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_toCellName} does not have waferholder", index); return false; } double gantryPosition = _gantryAxis.MotionData.MotorPosition; if (!_gantryAxis.CheckPositionIsInStation(gantryPosition, _toCellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry {gantryPosition} not in {_toCellName}", index); return false; } return true; } } }