using System; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using Mainframe.Devices; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using SicPM.Devices; namespace Mainframe.TMs { public class TMRobotPickRoutine : TMBaseRoutine { enum RoutineStep { WaitOpenSlitValveInterlock, OpenSlitValve, CheckBeforePick, PrepareTransfer, PrepareTransferNotWait, Pick, QueryOffset, Extend, Handoff, HandoffDelay, Retract, UpdateWaferInfoByHandoff, RequestWaferPresent, BeforePickRequestWaferPresent, AfterPickRequestWaferPresent, RequestAWCData, CheckWaferInfoByRobotSensor, BeforePickCheckWaferInfoByRobotSensor, AfterPickCheckWaferInfoByRobotSensor, WaitCloseSlitValveInterlock, CloseSlitValve, SetRobortExtendToDo, ClearRobortExtendToDo, WaitPMSensor, PostTransfer, OpenShutter, CloseShutter, Delay1, Delay2, VceMoveToSlot, RobotGotoNotWait, CheckRobotReady, CheckTransferPrepared, SetConfinementRingUp, TimeDelay1, TimeDelay20, TimeDelay50, } private ModuleName _target; private int _targetSlot; private RobotArmEnum _blade; private int _pickTimeout; private bool _autoHand; private int _postTransferTimeout; private double _shutterAndSlitValveMotionInterval; private bool _requestAWCData; private SicTM _tm; private TMSlitValveRoutine _openSlitValveRoutine = new TMSlitValveRoutine(); private TMSlitValveRoutine _closeSlitValveRoutine = new TMSlitValveRoutine(); // private VCEMoveToSlotRoutine _vceMoveToSlotRoutine; private bool _isShutterAndSlitValveMotionOneByOne; private bool _pmPostTrasferEnableHeat =true; private IoConfinementRing _confinementRing; public TMRobotPickRoutine() { Module = "TMRobot"; Name = "Pick"; _tm = DEVICE.GetDevice($"{ ModuleName.System.ToString()}.{ ModuleName.TM.ToString()}"); } public void Init(ModuleName source, int sourceSlot, RobotArmEnum blade) { Init(source, sourceSlot, blade, false); } public void Init(ModuleName source, int sourceSlot, int blade) { Init(source, sourceSlot, blade == 0 ? RobotArmEnum.Blade1 : RobotArmEnum.Blade2, false); } public void Init(ModuleName source, int sourceSlot) { Init(source, sourceSlot, RobotArmEnum.Blade1, true); } private void Init(ModuleName source, int sourceSlot, RobotArmEnum blade, bool autoHand) { _autoHand = autoHand; _target = source; _targetSlot = sourceSlot; _blade = blade; _openSlitValveRoutine.Init(source.ToString(), true, _pmPostTrasferEnableHeat); _closeSlitValveRoutine.Init(source.ToString(), false, _pmPostTrasferEnableHeat); _confinementRing = DEVICE.GetDevice("PM1.ConfinementRing"); } public void Init(ModuleName source, int sourceSlot, int blade, bool autoHand,bool pmPostTrasferEnableHeat) { _pmPostTrasferEnableHeat = pmPostTrasferEnableHeat; Init(source, sourceSlot, RobotArmEnum.Blade1, autoHand); } public override Result Start(params object[] objs) { Reset(); if (RobotDevice.RobotState != RobotStateEnum.Idle) { EV.PostWarningLog(Module, $"Can not pick, TMRobot Is Not IDLE"); return Result.FAIL; } _pickTimeout = SC.GetValue("TMRobot.PickTimeout"); //if (ModuleHelper.IsPm(_target)) //{ // _postTransferTimeout = SC.GetValue($"{_target}.PostTransferTimeout"); // _shutterAndSlitValveMotionInterval = SC.GetValue($"{_target}.ShutterAndSlitValveMotionInterval"); // _isShutterAndSlitValveMotionOneByOne = SC.GetValue($"{_target}.ShutterAndSlitValveMotionOneByOne"); // //CoralPM pm = DEVICE.GetDevice(_target.ToString()); // if (!pm.PickPlaceCheck(out string reason, false)) // { // EV.PostWarningLog(Module, $"Can not place, {reason}"); // return Result.FAIL; // } //} _requestAWCData = SC.GetValue("System.RequestAWCDataAfterPick"); if (!WaferManager.Instance.CheckHasWafer(_target, _targetSlot)) { EV.PostWarningLog(Module, $"Can not pick, No wafer at {_target}, {_targetSlot + 1}"); return Result.FAIL; } if (_autoHand) { if (WaferManager.Instance.CheckNoWafer(Module, 0)) { _blade = RobotArmEnum.Blade1; } else if (WaferManager.Instance.CheckNoWafer(Module, 1)) { _blade = RobotArmEnum.Blade2; } else { EV.PostWarningLog(Module, $"Can not pick, Robot both arm has wafer"); return Result.FAIL; } } int slot = _blade == RobotArmEnum.Blade1 ? 0 : 1; if (!WaferManager.Instance.CheckNoWafer(Module, slot)) { EV.PostWarningLog(Module, $"Can not pick, Robot arm {slot + 1} has wafer"); return Result.FAIL; } //Pick之前先,根据Sensor检测是否有盘 if (!SC.GetValue("System.IsSimulatorMode")) { if (ModuleHelper.IsLoadLock(_target) && !SensorLLWaferPresence.Value) { EV.PostWarningLog(Module, $"Can not pick, LoadLock sensor check no wafer"); return Result.FAIL; } if (ModuleHelper.IsBuffer(_target) && !SensorBufferWaferPresence.Value) { EV.PostWarningLog(Module, $"Can not pick,Buffer sensor check no wafer"); return Result.FAIL; } } //if (ModuleHelper.IsVCE(_target)) //{ // var vce = DEVICE.GetDevice(_target.ToString()); // if (!vce.CheckEnableTransfer(EnumTransferType.Pick)) // { // EV.PostWarningLog(Module, $"can not pick, {_target} not ready for transfer"); // return Result.FAIL; // } // _vceMoveToSlotRoutine = new VCEMoveToSlotRoutine(_target.ToString()); // _vceMoveToSlotRoutine.Init(_targetSlot); //} //if (ModuleHelper.IsPm(_target)) //{ // SicPM pm = DEVICE.GetDevice(_target.ToString()); // if (!pm.CheckEnableTransfer(EnumTransferType.Pick, out string reason)) // { // EV.PostWarningLog(Module, $"can not pick, {_target} not ready for transfer"); // return Result.FAIL; // } //} Notify($"Start, Pick from {_target} slot {_targetSlot + 1}, by {(_blade == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); IsPicking = false; return Result.RUN; } public override void Abort() { _tm.CloseAllVentPumpValue(); if (!IsPicking) { RobotDevice.Stop(); } Notify("Abort"); } public override Result Monitor() { try { WaitSlitValveOpenInterlock((int)RoutineStep.WaitOpenSlitValveInterlock, TMDevice.GetSlitValve(_target), _pickTimeout); /// if (ModuleHelper.IsPm(_target)) { RobotGotoNotWait((int)RoutineStep.RobotGotoNotWait, RobotDevice, _target, _targetSlot, _blade, _pickTimeout); if (_isShutterAndSlitValveMotionOneByOne) { Delay((int)RoutineStep.Delay1, _shutterAndSlitValveMotionInterval); ExecuteRoutine((int)RoutineStep.OpenSlitValve, _openSlitValveRoutine); } else { ExecuteRoutine((int)RoutineStep.OpenSlitValve, _openSlitValveRoutine); } CheckRobotReady((int)RoutineStep.CheckRobotReady, RobotDevice, _pickTimeout); } if (_target == ModuleName.VCEA || _target == ModuleName.VCEB) ExecuteRoutine((int)RoutineStep.OpenSlitValve, _openSlitValveRoutine); CheckBeforePick((int)RoutineStep.CheckBeforePick, _target, _targetSlot, _blade); RobotRequestWaferPresent((int)RoutineStep.BeforePickRequestWaferPresent, RobotDevice, _blade, _pickTimeout); CheckWaferInfoByRobotRQ((int)RoutineStep.AfterPickCheckWaferInfoByRobotSensor, RobotDevice, _blade, 1000); WaitPMReadySensor((int)RoutineStep.WaitPMSensor, _target, 5); SetRobortExtendToDO((int)RoutineStep.SetRobortExtendToDo, _target, 2); CheckRobotReady((int)RoutineStep.CheckRobotReady, RobotDevice, _pickTimeout); Pick((int)RoutineStep.Pick, RobotDevice, _target, _targetSlot, _blade, _pickTimeout); IsPicking = false; TimeDelay((int)RoutineStep.TimeDelay1, 1); RobotRequestWaferPresent((int)RoutineStep.RequestWaferPresent, RobotDevice, _blade, _pickTimeout); CheckWaferInfoByRobotRQ((int)RoutineStep.CheckWaferInfoByRobotSensor, RobotDevice, _blade, 1000); if (_requestAWCData) { RobotRequestWaferAWCData((int)RoutineStep.RequestAWCData, RobotDevice, _pickTimeout); } ClearRobortExtendToDO((int)RoutineStep.ClearRobortExtendToDo); ExecuteRoutine((int)RoutineStep.CloseSlitValve, _closeSlitValveRoutine); //if (ModuleHelper.IsPm(_target)) //{ // PostTransfer((int)RoutineStep.PostTransfer, Singleton.Instance.GetPMEntity(_target), DEVICE.GetDevice(_target.ToString()), EnumTransferType.Pick, _postTransferTimeout); //} } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException ex) { LOG.Error(ex.ToString()); RobotDevice.Stop(); return Result.FAIL; } Notify($"Finished, Pick from {_target} slot {_targetSlot + 1}, by {_blade}"); return Result.DONE; } public void SetConfinementRingUp(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set Confinement RingUp"); OP.DoOperation($"{_target}.ServoUp"); return true; }, () => { return _confinementRing.IsUp; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set Confinement RingUp timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }