using System; using Aitex.Core.RT.Event; 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 MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.LogicUnits; using MECF.Framework.RT.ModuleLibrary.PMModules; using MECF.Framework.RT.ModuleLibrary.SystemModules; namespace FutureEfemLib.Efems { public class EfemPlaceRoutine : ModuleRoutine, IRoutine { enum RoutineStep { QuerySourceState, CheckBeforePlace, PlaceWafer, CheckBeforePlace2, PlaceWafer2, PlaceDelay, PostTransfer, PrepareTransfer, PlaceRetract, PlaceExtend, LiftUp, LiftDown, } private int _timeout; private ModuleName _source; private int _sourceSlot; private Hand _hand; private bool _autoHand; private EfemModule _robotModule; private ITransferTarget _target; private int _postTransferTimeout; public EfemPlaceRoutine(EfemModule robotModule) { Module = "EfemRobot"; Name = "Place"; _robotModule = robotModule; } public Result Start(params object[] objs) { _timeout = SC.GetValue("EFEM.EfemRobot.PlaceTimeout"); Reset(); if (_autoHand) { if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)) { _hand = Hand.Blade1; } else if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1)) { _hand = Hand.Blade2; } else { EV.PostWarningLog(Module, $"Can not place, Robot both arm no wafer"); return Result.FAIL; } } if (_hand == Hand.Both) { if (!SC.GetValueOrDefault("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Lower Blade is Disabled"); return Result.FAIL; } if (!SC.GetValueOrDefault("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Upper Blade is Disabled"); return Result.FAIL; } if (WaferManager.Instance.GetWafers(_source).Length < 2) { EV.PostWarningLog(Module, $"Can not place use both arm, Only one slot at {_source}"); return Result.FAIL; } if (!WaferManager.Instance.CheckNoWafer(_source, _sourceSlot)) { EV.PostWarningLog(Module, $"Can not place, should no wafer at {_source}, {_sourceSlot + 1}"); return Result.FAIL; } if (!WaferManager.Instance.CheckNoWafer(_source, _sourceSlot + 1)) { EV.PostWarningLog(Module, $"Can not place, should no wafer at {_source}, {_sourceSlot + 1 + 1}"); return Result.FAIL; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade1)) { EV.PostWarningLog(Module, $"Can not place, Robot arm 1 no wafer"); return Result.FAIL; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade2)) { EV.PostWarningLog(Module, $"Can not place, Robot arm 2 no wafer"); return Result.FAIL; } } else { if (_hand == Hand.Blade1 && !SC.GetValueOrDefault("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Lower Blade is Disabled"); return Result.FAIL; } if (_hand == Hand.Blade2 && !SC.GetValueOrDefault("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Upper Blade is Disabled"); return Result.FAIL; } if (!WaferManager.Instance.CheckNoWafer(_source, _sourceSlot)) { EV.PostWarningLog(Module, $"Can not place, should no wafer at {_source}, {_sourceSlot + 1}"); return Result.FAIL; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand)) { EV.PostWarningLog(Module, $"Can not place, Robot arm {(int)_hand + 1} no wafer"); return Result.FAIL; } } if (ModuleHelper.IsLoadPort(_source)) { if (WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)_hand).Size != CarrierManager.Instance.GetCarrier(_source).CarrierWaferSize) { EV.PostWarningLog(Module, $"Can not place, Carrier Size and Wafer Size not matched"); return Result.FAIL; } } Notify($"Start, Place to {_source} slot {_sourceSlot + 1}, by {_hand}"); return Result.RUN; } //public Result Start(params object[] objs) //{ // return Start((ModuleName)objs[0], (int)objs[1], (Hand)objs[2]); //} public void Init(ModuleName source, int slot, Hand hand) { _autoHand = false; _source = source; _sourceSlot = slot; _hand = hand; _target = EquipmentManager.Modules[source] as ITransferTarget; if (ModuleHelper.IsPm(source)) _postTransferTimeout = SC.GetValue($"PM.PostTransferTimeout"); } public void Init(ModuleName source, int slot) { _autoHand = true; _source = source; _sourceSlot = slot; _target = EquipmentManager.Modules[source] as ITransferTarget; if (ModuleHelper.IsPm(source)) _postTransferTimeout = SC.GetValue($"PM.PostTransferTimeout"); } public void Abort() { if (_target != null) { _target.NoteTransferStop(ModuleName.EfemRobot, Hand.Blade1, 0, EnumTransferType.Place); } _target = null; Notify("Abort"); } public Result Monitor() { try { if (ModuleHelper.IsPm(_source)) { if (!_target.CheckReadyForTransfer(ModuleName.EfemRobot, _hand, _sourceSlot, EnumTransferType.Pick, out _)) { PrepareTransfer((int)RoutineStep.PrepareTransfer, _target as PMModuleBase, EnumTransferType.Place, _postTransferTimeout); } } if (_hand == Hand.Both) { CheckBeforePlace((int)RoutineStep.CheckBeforePlace, _source, _sourceSlot, Hand.Blade1); PlaceWafer((int)RoutineStep.PlaceWafer, _source, _sourceSlot, Hand.Blade1, _timeout); CheckBeforePlace((int)RoutineStep.CheckBeforePlace2, _source, _sourceSlot + 1, Hand.Blade2); PlaceWafer((int)RoutineStep.PlaceWafer2, _source, _sourceSlot + 1, Hand.Blade2, _timeout); } else { CheckBeforePlace((int)RoutineStep.CheckBeforePlace, _source, _sourceSlot, _hand); if (ModuleHelper.IsPm(_source)) { RobotExtend((int)RoutineStep.PlaceExtend, _source, _sourceSlot, _hand, RobotPostionEnum.PlaceExtendUp, _timeout); MovePinUp((int)RoutineStep.LiftUp, _target as PMModuleBase, EnumTransferType.Extend, _timeout); RobotRetract((int)RoutineStep.PlaceRetract, _source, _sourceSlot, _hand, RobotPostionEnum.PlaceRetract, _timeout); //提高产能,放到process //LiftPinDown((int)RoutineStep.LiftDown, _target as PMModuleBase, EnumTransferType.Retract, _timeout); } else { PlaceWafer((int)RoutineStep.PlaceWafer, _source, _sourceSlot, _hand, _timeout); } } if (ModuleHelper.IsPm(_source)) { PostTransfer((int)RoutineStep.PostTransfer, _target as PMModuleBase, EnumTransferType.Place, _postTransferTimeout); } } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { return Result.FAIL; } _target.NoteTransferStop(ModuleName.EfemRobot, Hand.Blade1, 0, EnumTransferType.Place); Notify($"Finish, Place to {_source} slot {_sourceSlot + 1}, by {_hand}"); return Result.DONE; } public void CheckBeforePlace(int id, ModuleName source, int slot, Hand blade) { Tuple ret = Execute(id, () => { Notify("Check place condition"); string reason = string.Empty; if (!_target.CheckReadyForTransfer(ModuleName.EfemRobot, _hand, _sourceSlot, EnumTransferType.Place, out reason)) { Stop(reason); return false; } if (blade == Hand.Blade1) { if (!WaferManager.Instance.CheckNoWafer(source, slot)) { Stop("Source has wafer"); return false; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)) { Stop("Blade 1 no wafer"); return false; } } else if (blade == Hand.Blade2) { if (!WaferManager.Instance.CheckNoWafer(source, slot)) { Stop("Source has wafer"); return false; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1)) { Stop("Blade no wafer"); return false; } } else { for (int i = 0; i < 2; i++) { if (!WaferManager.Instance.CheckNoWafer(source, slot + i)) { Stop("Source has wafer"); return false; } if (!WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, i)) { Stop("Blade no wafer"); return false; } } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } } public void PlaceWafer(int id, ModuleName chamber, int slot, Hand hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("robot start execute place command"); string reason; _target.NoteTransferStart(ModuleName.EfemRobot, Hand.Blade1, 0, EnumTransferType.Place); if (!_robotModule.RobotDevice.Place(chamber, hand, slot, out reason)) { Stop(reason); return false; } return true; }, () => { if (_robotModule.RobotDevice.IsError) return null; if (_robotModule.RobotDevice.IsIdle) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void PostTransfer(int id, PMModuleBase pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{pm.Name} post transfer "); if (!pm.PostTransfer(ModuleName.EfemRobot, Hand.Blade1, 0, type, out string reason)) { Stop(reason); return false; } return true; }, () => { if (pm.IsError) { return null; } return pm.IsReady; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"{pm.Name} error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} post transfer timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void PrepareTransfer(int id, PMModuleBase pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{pm.Name} Prepare transfer "); if (!pm.PrepareTransfer(ModuleName.EfemRobot, Hand.Blade1, 0, type, 0, 0, false, out string reason)) { Stop(reason); return false; } return true; }, () => { if (pm.IsError) { return null; } return pm.IsReady; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"{pm.Name} error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} Prepare transfer timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotExtend(int id, ModuleName chamber, int slot, Hand hand, RobotPostionEnum robotPostion, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("robot execute goto command"); //string reason; //if (!_robotModule.RobotDevice.GotoRE(chamber, hand, slot, robotPostion, out reason)) //{ // Stop(reason); // return false; //} return true; }, () => { if (_robotModule.RobotDevice.IsError) return null; if (_robotModule.RobotDevice.IsIdle) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotRetract(int id, ModuleName chamber, int slot, Hand hand, RobotPostionEnum robotPostion, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("robot execute goto command"); //string reason; //if (!_robotModule.RobotDevice.GotoRE(chamber, hand, slot, robotPostion, out reason)) //{ // Stop(reason); // return false; //} return true; }, () => { if (_robotModule.RobotDevice.IsError) return null; if (_robotModule.RobotDevice.IsIdle) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void MovePinUp(int id, PMModuleBase pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{pm.Name} lift pin up "); //if (!pm.ChamberLiftPin.MoveUp(out string reason)) //{ // Stop(reason); // return false; //} return true; }, () => { //if (pm.ChamberLiftPin.IsUp) // return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} move lift pin up timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void LiftPinDown(int id, PMModuleBase pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{pm.Name} lift pin down"); //if (!pm.ChamberLiftPin.MoveDown(out string reason)) //{ // Stop(reason); // return false; //} return true; }, () => { //if (pm.ChamberLiftPin.IsDown) // return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} move down lift pin timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }