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.Devices.VCE; using Venus_RT.Modules.VCE; namespace Venus_RT.Modules.TM.VenusEntity { public class SEMFPlaceRoutine : ModuleRoutineBase, IRoutine { private enum PlaceStep { seWaitModuleReady, sePrepareModule, sePlacing, seNotifyDone } private HongHuTM _tm; private ITransferRobot _robot; private IPreAlign _vpa; private VceEntity _vceModule; private ModuleName _targetModule; private int _targetSlot; private int _placingTimeout; public int currentStepNo; Hand _hand; public SEMFPlaceRoutine(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 placeItem = (MoveItem)objs[0]; var placeItem = (Queue)objs[0]; _targetModule = placeItem.Peek().DestinationModule; _targetSlot = placeItem.Peek().DestinationSlot; _hand = placeItem.Peek().RobotHand; //如果目标是Vce 获取vce 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 place 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 placing action"); return RState.Failed; } //检查目标手臂上有wafer if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, (int)_hand)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot place as TM Robot Arm: {_hand} has no wafer"); return RState.Failed; } //检查目标槽位上没有wafer if (WaferManager.Instance.CheckHasWafer(_targetModule, _targetSlot)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot place as {_targetModule} Slot {_targetSlot + 1} has a 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(); _placingTimeout = SC.GetValue($"SETM.PlaceTimeout") * 1000; return Runner.Start(Module, $"Place to {_targetModule}"); } public RState Monitor() { Runner.Wait(PlaceStep.seWaitModuleReady, CheckModuleReady, _delay_60s) .Run(PlaceStep.sePrepareModule, PrepareModule, CheckModuleReady) .Run(PlaceStep.sePlacing, Placing, WaitPlaceDone, _placingTimeout) .End(PlaceStep.seNotifyDone, NullFun, 500); return Runner.Status; } private bool PrepareModule() { switch (_targetModule) { case ModuleName.VCE1: _vceModule.PostMsg(VceMSG.Goto, _targetSlot); return true;//移动到目标槽位 case ModuleName.VPA: return true;//10/17暂时为true 后可能要求旋转 default: return false; } } private bool WaitPlaceDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { WaferManager.Instance.WaferMoved(ModuleName.TMRobot, (int)_hand, _targetModule, _targetSlot); return true; } // timeout failed else { Runner.Stop($"TM Robot Placing failed, {_robot.Status}"); return true; } } private bool Placing() { return _robot.Place(_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() { } } }