using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Venus_Core; using Venus_RT.Devices; using Venus_RT.Devices.PreAligner; using Venus_RT.Modules.VCE; namespace Venus_RT.Modules.TM.VenusEntity { public class SEMFPickRoutine : ModuleRoutineBase, IRoutine { private enum PickStep { seWaitModuleReady, sePrepareModule, sePicking, seNotifyDone, } private HongHuTM _tm; private IPreAlign _vpa; private ITransferRobot _robot; private VceEntity _vceModule; private ModuleName _targetModule; private int _targetSlot; private int _pickingTimeout; public int currentStepNo; Hand _hand; /// /// 完整pick动作仅可vce vpa取片 /// /// /// /// public SEMFPickRoutine(HongHuTM tm, ITransferRobot robot, IPreAlign vpa) : base(ModuleName.SETM) { _tm = tm; _robot = robot; _vpa = vpa; } public RState Start(params object[] objs) { if (!_robot.IsHomed) { LOG.Write(eEvent.ERR_TM, Module, $"TM Robot is not homed, please home it first"); return RState.Failed; } //MoveItem pickItem = new MoveItem() { SourceModule = , }; var pickItem = (Queue)objs[0]; _targetModule = pickItem.Peek().SourceModule; _targetSlot = pickItem.Peek().SourceSlot; _hand = pickItem.Peek().RobotHand; //如果目标是Vce 否则是vpa if (ModuleHelper.IsVCE(_targetModule) && ModuleHelper.IsInstalled(_targetModule)) { _vceModule = Singleton.Instance.GetVCE(_targetModule); //如果vce有错误 报错 if (_vceModule.IsError) { LOG.Write(eEvent.ERR_TM, Module, $"Invalid target module : {_targetModule} is Error! Please solve Error first!"); return RState.Failed; } if (_targetSlot < 0) { LOG.Write(eEvent.ERR_TM, Module, $"VCE target slot cannot be {_targetSlot}. Please check it first."); return RState.Failed; } if (_tm.VCESlitDoorClosed) { LOG.Write(eEvent.ERR_TM, Module, $"cannot pick cause vce slitdoor not open."); return RState.Failed; } //如果VCE门是关闭的 说明还未进行pump 无法取片等 //if (_tm.VCESlitDoorClosed) //{ // LOG.Write(eEvent.ERR_TM, Module, $"Invalid target module : {_targetModule} slitdoor not open! Please pump down vce and open it first!"); // return RState.Failed; //} } //如果目标又不是VPA 报错 else if (!ModuleHelper.IsVPA(_targetModule)) { LOG.Write(eEvent.ERR_TM, Module, $"Invalid target module : {_targetModule} for pick action"); return RState.Failed; } //检查目标手臂上没有wafer if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, (int)_hand)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot pick as TM Robot Arm: {_hand} already has a wafer"); return RState.Failed; } //检查目标槽位上有wafer if (WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot pick as {_targetModule} Slot {_targetSlot + 1} has no wafer"); return RState.Failed; } //2023/10/13 朱永吉 atm mode的判断不允许自动pump vent 信号不满足手动pump vent //if (RouteManager.IsATMMode && _targetModule == ModuleName.VCE1) //{ // if (!_tm.IsVCEATM) // { // LOG.Write(eEvent.ERR_TM, Module, $"System in ATM Mode but VCE is not ATM!"); // return RState.Failed; // } // // if (!_tm.IsTMATM) // { // LOG.Write(eEvent.ERR_TM, Module, $"System in ATM Mode but TM is not ATM!"); // return RState.Failed; // } //} //else //{ // if (_tm.IsVCEATM) // { // LOG.Write(eEvent.ERR_TM, Module, $"System not in ATM Mode but VCE is ATM!"); // return RState.Failed; // } // // if (_tm.IsTMATM) // { // LOG.Write(eEvent.ERR_TM, Module, $"System not in ATM Mode but TM is ATM!"); // return RState.Failed; // } //} Reset(); _pickingTimeout = SC.GetValue("SETM.PickTimeout") * 1000; return Runner.Start(Module, $"Pick from {_targetModule}"); } public RState Monitor() { Runner.Wait(PickStep.seWaitModuleReady, CheckModuleReady, _delay_60s) .Run(PickStep.sePrepareModule, PrepareModule, CheckModuleReady) .Run (PickStep.sePicking, Picking, WaitPickDone, _pickingTimeout) .End (PickStep.seNotifyDone, NullFun, 500); return Runner.Status; } private bool PrepareModule() { switch (_targetModule) { case ModuleName.VCE1: return _vceModule.CheckToPostMessage((int)VceMSG.Goto, _targetSlot);//移动到目标槽位 case ModuleName.VPA: return true;//10/17暂时为true 后可能要求旋转到0 default: return false; } } private bool WaitPickDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { WaferManager.Instance.WaferMoved(_targetModule, _targetSlot, ModuleName.TMRobot, (int)_hand); return true; } else { Runner.Stop($"TM Robot Picking failed, {_robot.Status}"); return true; } } private bool Picking() { //到达目标点位 pick固定槽位点的wafer return _robot.Pick(_targetModule, 0, _hand); } private bool CheckModuleReady() { switch (_targetModule) { case ModuleName.VCE1: return _vceModule.IsIdle; case ModuleName.VPA: return _vpa.Status == RState.End; default: return false; } } public void Abort() { } } }