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.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.Loader; 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 CyberX8_RT.Devices.Metal; using CyberX8_RT.Devices.Rinse; namespace CyberX8_RT.Modules.Transporter { public class TransporterPickDownToRoutine : RoutineBase, IRoutine { private enum PutDownStep { CheckPreStatus, TargetCellUnclamp, TargetCellUnclampWait, ElevatorUp, ElevatorUpWait, ImmobilizeExtend, ImmobilizeExtendWait, SafeMoveTo, CheckMoveToStatus, GantryPosition, GantryPositiolWait, CalculatePlaceSpeed, PlaceDelay, ImmobilizeRetract, ImmobilizeRetractWait, ElevatorPosition, ElevatorPositionWait, UnlockClamp, UnlockClampWait, ElevatorLow, ElevatorLowWait, ConfirmWHPresent, LockClamp, LockClampWait, UpdateWaferHolder, GantryPositionPark, GantryPositionParkWait, End } #region 内部变量 private string _cellName; private JetAxisBase _gantryAxis; private JetAxisBase _elevatorAxis; private LoaderEntity _loaderEntity; private JetAxisBase _loaderRotationAxis; private SystemFacilities _facilities; private TransporterUnlockRoutine _unlockRoutine; private TransporterLockRoutine _lockRoutine; private TransporterCommon _transporterCommon; private TransporterExtendRoutine _extendRoutine; private TransporterRetractRoutine _retractRoutine; private TransporterConflictRoutine _conflictRoutine; private LoaderPreTransferUnclampRoutine _preTransferUnclampRoutine; ProcessLayoutCellItem _cellItem; private int _placeTime; private int _placeDelayTime; private int _velocity; private int _acceleration; #endregion /// /// 构造函数 /// /// public TransporterPickDownToRoutine(string module) : base(module) { } /// /// 中止 /// public void Abort() { Runner.Stop("Manual Abort"); } /// /// 监控 /// /// public RState Monitor() { Runner.Run(PutDownStep.CheckPreStatus,CheckStartPreConfition,_delay_1ms) .Run(PutDownStep.TargetCellUnclamp, TargetCellUnclamp, _delay_1ms) .WaitWithStopCondition(PutDownStep.TargetCellUnclampWait,TargetCellUnclampEndStatus,TargetCellUnclampStopStatus) //1.1 Elevator Position Up .Run(PutDownStep.ElevatorUp, ElevatorGotoUp, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorUpWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop) //1.2 Immobilized Extend .Run(PutDownStep.ImmobilizeExtend, () => { return _extendRoutine.Start(null) == RState.Running; }, NullFun, _delay_1ms) .WaitWithStopCondition(PutDownStep.ImmobilizeExtendWait, () => { return CommonFunction.CheckRoutineEndState(_extendRoutine); }, CheckImmobilizeRoutineStopStatus) //1.3 Move to 安全 .Run(PutDownStep.SafeMoveTo, SafeMoveTo, _delay_1ms) .WaitWithStopCondition(PutDownStep.CheckMoveToStatus, () => CommonFunction.CheckRoutineEndState(_conflictRoutine), CheckSafeMoveToStopStatus) //1.3 Gantry 移动 .Run(PutDownStep.GantryPosition, GantryPositionToCell, _delay_1ms) .WaitWithStopCondition(PutDownStep.GantryPositiolWait, CheckGantryPositionStatus, CheckGantryPositionRunStop) //1.4 确认Place 速度和加速度 .Run(PutDownStep.CalculatePlaceSpeed, CalculatePownDownSpeed, _delay_1ms) //1.5 Pickup delay .Delay(PutDownStep.PlaceDelay, _placeDelayTime * 1000) //1.6 Immobilize Retract .Run(PutDownStep.ImmobilizeRetract, () => { return _retractRoutine.Start(null) == RState.Running; }, NullFun, _delay_1ms) .WaitWithStopCondition(PutDownStep.ImmobilizeRetractWait, ()=> CommonFunction.CheckRoutineEndState(_retractRoutine), CheckRetractStopStatus) //.WaitWithStopCondition(PutDownStep.CellRetractedWait, CheckCellRetractRoutineEndState, CheckCellRetractRoutineStopState) //1.7 Elevator 移动至cell .Run(PutDownStep.ElevatorPosition, () => { return VerticalPositionToCell(); }, NullFun, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorPositionWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop) //1.8 Unlock clamp .Run(PutDownStep.UnlockClamp, () => { return _unlockRoutine.Start(null) == RState.Running; },_delay_1ms) .WaitWithStopCondition(PutDownStep.UnlockClampWait,()=>CommonFunction.CheckRoutineEndState(_unlockRoutine), CheckUnlockRoutineStopStatus) //1.9 Elevator Position Low .Run(PutDownStep.ElevatorLow, ElevatorGotoLow, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorLowWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop) //2.0 确认WhPresent信号 .Wait(PutDownStep.ConfirmWHPresent,ConfirmWHPresentSensorOff,_delay_2s) //2.1 Lock clamp .Run(PutDownStep.LockClamp, () => { return _lockRoutine.Start(null) == RState.Running; },_delay_1ms) .WaitWithStopCondition(PutDownStep.LockClampWait,()=>CommonFunction.CheckRoutineEndState(_lockRoutine), CheckLockRoutineStopStatus) //2.2 Wafer Holder location update .Run(PutDownStep.UpdateWaferHolder,WaferHolderTransfer,_delay_1ms) //2.3 Gantry Position To Park .Run(PutDownStep.GantryPositionPark,GantryBackToPark,_delay_1ms) .WaitWithStopCondition(PutDownStep.GantryPositionParkWait,CheckGantryParkPositionStatus,CheckGantryParkPositionRunStop) .End(PutDownStep.End,NullFun,100); return Runner.Status; } /// /// 目标cell unclamp /// /// private bool TargetCellUnclamp() { if (_cellName == "Loader") { bool result= _preTransferUnclampRoutine.Start() == RState.Running; if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "Loader Unclamp failed", 0); } return result; } else { _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); if (_cellItem != null) { if (Enum.TryParse(_cellItem.ModuleName, out ModuleName cellModuleName)) { if (ModuleHelper.IsRinse(cellModuleName)) { RinseDevice rinseDevice = DEVICE.GetDevice(_cellItem.ModuleName); if (rinseDevice != null) { bool result = rinseDevice.WaferHolderClampValveOff(); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellItem.ModuleName} Clamp off failed", 0); } return result; } } else if (ModuleHelper.IsMetal(cellModuleName)) { MetalCellDevice metalCellDevice = DEVICE.GetDevice(_cellItem.ModuleName); if (metalCellDevice != null) { bool result = metalCellDevice.WaferHolderClampOff(); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellItem.ModuleName} Clamp off failed", 0); } return result; } } } } } return true; } /// /// 目标Cell Unclamp状态 /// /// private bool TargetCellUnclampEndStatus() { if(_cellName=="Loader") { return CommonFunction.CheckRoutineEndState(_preTransferUnclampRoutine); } else { _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); if (_cellItem != null) { if (Enum.TryParse(_cellItem.ModuleName, out ModuleName cellModuleName)) { if (ModuleHelper.IsRinse(cellModuleName)) { RinseDevice rinseDevice = DEVICE.GetDevice(_cellItem.ModuleName); if (rinseDevice != null) { return rinseDevice.RinseData.WaferHolderClamp==false; } } else if (ModuleHelper.IsMetal(cellModuleName)) { MetalCellDevice metalCellDevice = DEVICE.GetDevice(_cellItem.ModuleName); if (metalCellDevice != null) { return metalCellDevice.ClampOff; } } } } } return true; } /// /// 目标Cell Unclamp运行中止状态 /// /// private bool TargetCellUnclampStopStatus() { if (_cellName == "Loader") { bool result = CommonFunction.CheckRoutineStopState(_preTransferUnclampRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "Loader Unclamp failed", 0); } return result; } return false; } /// /// Elevator goto Up /// /// private bool ElevatorGotoUp() { bool result= _elevatorAxis.PositionStation("UP", false); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto up failed", 0); } return result; } /// /// 检验前置条件 /// /// 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; } /// /// 安全避障移动 /// /// private bool SafeMoveTo() { _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); string stationName = _cellName; if (_cellItem != null) { if (_cellName.ToLower() != "loader" && _cellName.ToLower() != "park") { stationName = $"Cell{_cellItem.CellId}"; } } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } var result = _gantryAxis.GetPositionByStation(stationName); if (result.success) { bool isPositive = false; if (_gantryAxis.MotionData.MotorPosition < result.position) { isPositive = true; } return _conflictRoutine.Start(result.position, isPositive) == RState.Running; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in station list",0); return false; } } /// /// 检验安全避让异常结束状态 /// /// private bool CheckSafeMoveToStopStatus() { bool result = CommonFunction.CheckRoutineStopState(_conflictRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "Safe Move failed", 0); } return result; } /// /// Gantry Position To cell /// /// private bool GantryPositionToCell() { _cellItem= ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); bool result = false; if (_cellItem != null) { if (_cellName.ToLower() != "loader"&&_cellName.ToLower()!="park") { result= _gantryAxis.PositionStation($"Cell{_cellItem.CellId}",false); } else { result = _gantryAxis.PositionStation(_cellName,false); } if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry axis motion failed", 0); } return result; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } } /// /// Elevator Position to cell /// /// private bool VerticalPositionToCell() { bool result= false; if( _cellItem != null ) { if (_cellName.ToLower()!="loader") { result= _elevatorAxis.PositionStation($"Cell{_cellItem.CellId}",false,_velocity,_acceleration,_acceleration); } else { result= _elevatorAxis.PositionStation(_cellName,false,_velocity,_acceleration,_acceleration); } if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed", 0); } return result; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } } /// /// 检验Vertical移动状态 /// /// private bool CheckVerticalPositionStatus() { return _elevatorAxis.Status == RState.End; } /// /// 检验Vertical是否还在运动 /// /// private bool CheckVerticalPositionRunStop() { bool result= _elevatorAxis.Status == RState.Failed||_elevatorAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed", 0); } return result; } /// /// 检验Immobile异常状态 /// /// private bool CheckImmobilizeRoutineStopStatus() { bool result= CommonFunction.CheckRoutineStopState(_extendRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "extend failed", 0); } return result; } /// /// 检验unlock异常状态 /// /// private bool CheckUnlockRoutineStopStatus() { bool result = CommonFunction.CheckRoutineStopState(_unlockRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "unlock failed", 0); } return result; } /// /// Elevator goto low /// /// private bool ElevatorGotoLow() { bool result= _elevatorAxis.PositionStation("LOW", false); if(!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto low failed", 0); } return result; } /// /// 检验Gantry移动状态 /// /// private bool CheckGantryPositionStatus() { return _gantryAxis.Status == RState.End; } /// /// 检验Gantry是否还在运动 /// /// private bool CheckGantryPositionRunStop() { bool result= _gantryAxis.Status == RState.Failed||_gantryAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry axis motion failed", 0); } return result; } /// /// 计算放下速度 /// /// private bool CalculatePownDownSpeed() { if(_placeTime==0) { return true; } BeckhoffStationAxis stationAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(Module, "Elevator", 0); Station upStation = stationAxis.Stations.Find(O => O.Name.EndsWith("UP")); Station cellStation = null; if (_cellName == "Loader") { cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith("Loader")); } else { cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith($"Cell{_cellItem.CellId}")); } if (upStation==null) { NotifyError(eEvent.ERR_TRANSPORTER, "UP is not in Station List",0); return false; } if(cellStation==null) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} is not in Station List",0); return false; } if(!double.TryParse(cellStation.Position,out double cellStationPosition)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid",0); return false; } if (!double.TryParse(upStation.Position, out double upStationPosition)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid",0); return false; } int distance =(int)(Math.Round(Math.Abs(cellStationPosition - upStationPosition))); double tmpVelocity = (double) distance/ _placeTime; _velocity = _elevatorAxis.CalculateMultiplySpeedRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpVelocity)); double tmpAccelaration = (double)(2 * distance) / Math.Pow(_placeTime, 2); _acceleration = _elevatorAxis.CalculateMultiplyAccelerationRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpAccelaration)); LOG.WriteBackgroundLog(eEvent.INFO_TRANSPORTER, Module, "adjust profile speed"); return true; } /// /// 检验Retract 异常状态 /// /// private bool CheckRetractStopStatus() { bool result = CommonFunction.CheckRoutineStopState(_retractRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "retract failed", 0); } return result; } /// /// 更新WaferHolder移动信息 /// /// private bool WaferHolderTransfer() { bool result= WaferHolderManager.Instance.TransferWaferHolder(Module,Module, _cellName); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "tranfer waferHolder message failed", 0); } else { if (Singleton.Instance.IsAutoRunning) { WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(_cellName); if (waferHolderInfo != null) { string strTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); waferHolderInfo.SchedulerModules.Add($"{strTime} {Module} => {_cellName}"); } } } return result; } /// /// 确认WH Present Sensor off /// /// private bool ConfirmWHPresentSensorOff() { bool result= !_transporterCommon.TransporterData.WhPresent1 &&!_transporterCommon.TransporterData.WhPresent2; if(!result) { NotifyError(eEvent.ERR_TRANSPORTER, "confirm WS Present sensor failed",0); } return result; } /// /// 检验Lock异常状态 /// /// private bool CheckLockRoutineStopStatus() { bool result = CommonFunction.CheckRoutineStopState(_lockRoutine); if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "lock failed", 0); } return result; } /// /// Gabtry是否需要回到 /// /// private bool NeedGantryBackToPark() { switch(_cellName) { case "Loader": case "Prewet": return true; default: return false; } } /// /// Gantry 回至Park /// /// private bool GantryBackToPark() { if (NeedGantryBackToPark()) { bool result= _gantryAxis.PositionStation("Park", false); if(!result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry back to park failed",0); } return result; } else { return true; } } /// /// 检验Gantry Park移动状态 /// /// private bool CheckGantryParkPositionStatus() { if (NeedGantryBackToPark()) { return _gantryAxis.Status == RState.End; } else { return true; } } /// /// 检验Gantry Park是否还在运动 /// /// private bool CheckGantryParkPositionRunStop() { if (NeedGantryBackToPark()) { bool result = _gantryAxis.Status == RState.Failed||_gantryAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry motion failed", 0); } return result; } else { return false; } } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _cellName = objs[0].ToString(); _velocity = 0; _acceleration = 0; InitializeParameters(); string preConfig = SC.GetConfigPreContent(_cellName); if (SC.ContainsItem($"{preConfig}.PlaceTimeSeconds")) { _placeTime = SC.GetValue($"{preConfig}.PlaceTimeSeconds"); } if (SC.ContainsItem($"{preConfig}.PlaceDelaySeconds")) { _placeDelayTime = SC.GetValue($"{preConfig}.PlaceDelaySeconds"); } return Runner.Start(Module, $"Pun Down To {_cellName}"); } /// /// 初始化参数 /// 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"); _unlockRoutine = new TransporterUnlockRoutine(Module); _lockRoutine = new TransporterLockRoutine(Module); _extendRoutine = new TransporterExtendRoutine(Module); _retractRoutine = new TransporterRetractRoutine(Module); _conflictRoutine = new TransporterConflictRoutine(Module); _transporterCommon = DEVICE.GetDevice($"{Module}.Common"); _preTransferUnclampRoutine = new LoaderPreTransferUnclampRoutine(ModuleName.Loader1.ToString()); } /// /// 启动校验条件 /// /// private bool CheckStartPreConfition() { bool result = CheckPreCondition(); if(!result) { return false; } double elevatorPosition = _elevatorAxis.MotionData.MotorPosition; if (!_elevatorAxis.CheckPositionIsInStation(elevatorPosition, "Up")) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis {elevatorPosition} is not int Up station",-1); return false; } if (!_loaderEntity.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} is not homed", -1); return false; } if (_cellName == "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} does not has wafer Shuttle",-1); return false; } if (WaferHolderManager.Instance.HasWaferHolder(_cellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell {_cellName} already has wafer Shuttle", -1); return false; } //检验Facilities var faciltiesResult = _facilities.CheckCDA(); if (!faciltiesResult.result) { NotifyError(eEvent.ERR_TRANSPORTER, faciltiesResult.reason, -1); return false; } //检验Lock和WH Present Sensor if (!_transporterCommon.TransporterData.Locked1) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} lock1 sensor is off ", -1); return false; } if (!_transporterCommon.TransporterData.Locked2) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} lock2 sensor is off ",-1); return false; } if (!_transporterCommon.TransporterData.WhPresent1) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} WS Present1 sensor is off ", -1); return false; } if (!_transporterCommon.TransporterData.WhPresent2) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} WS Present2 sensor is off ",-1); return false; } return true; } /// /// 重试 /// /// public RState Retry(int step) { InitializeParameters(); List preStepIds = new List(); return Runner.Retry(PutDownStep.CheckPreStatus, preStepIds, Module, "PickUp Moveto Retry"); } /// /// 检验前面Unload完成状态 /// /// 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(_cellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} does not have waferholder", index); return false; } return true; } } }