using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Devices; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Mainframe.Devices; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HwAligner; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.EFEM; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using System; using static MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase.RobotBaseDevice; namespace Mainframe.EFEMs { public class EfemBaseRoutine : ModuleRoutine, IRoutine { private RobotBaseDevice _waferRobot = null; private RobotBaseDevice _trayRobot = null; private IEFEM _efemDevice; public IoSensor _loadTrayHomeSensor; //Tray定位 public IoSensor _loadWaferPlaced; //上下对射,检测Wafer有无 public IoSensor _loadTrayPresence; //检测托盘有无 public IoSensor _cassAL6Inch; //6寸检测 public IoSensor _cassAR6Inch; //6寸检测 public IoSensor _cassBL6Inch; //6寸检测 public IoSensor _cassALWaferConvex; //凸片检测 public IoSensor _cassARWaferConvex; //凸片检测 public IoSensor _cassBLWaferConvex; //凸片检测 private Mainframe.Devices.IoInterLock _tmIoInterLock; public IoLift4 _llLift; public IoClaw _loadWaferClaw; public IoLift4 _unLoadLift; public IoClaw _unLoadWaferClaw; private HwAlignerGuide _alignerDevice = null; protected RobotBaseDevice WaferRobot { get { return _waferRobot; } } protected RobotBaseDevice TrayRobot { get { return _trayRobot; } } protected IEFEM EfemDevice { get { return _efemDevice; } } public EfemBaseRoutine() { _waferRobot = DEVICE.GetDevice($"WaferRobot.WaferRobot"); _trayRobot = DEVICE.GetDevice($"TrayRobot.TrayRobot"); _efemDevice = DEVICE.GetDevice($"EFEM.EFEM"); _loadTrayHomeSensor = DEVICE.GetDevice($"TM.LoadTrayHomeSensor"); _alignerDevice = DEVICE.GetDevice($"TM.HiWinAligner"); _loadWaferPlaced = DEVICE.GetDevice($"TM.LLWaferPlaced"); _loadTrayPresence = DEVICE.GetDevice($"TM.LLTrayPresence"); _cassBLWaferConvex = DEVICE.GetDevice($"TM.CassBLWaferConvexSensor"); _cassALWaferConvex = DEVICE.GetDevice($"TM.CassALWaferConvexSensor"); _cassARWaferConvex = DEVICE.GetDevice($"TM.CassARWaferConvexSensor"); _cassAL6Inch = DEVICE.GetDevice($"TM.CassALInch6Sensor"); _cassAR6Inch = DEVICE.GetDevice($"TM.CassARInch6Sensor"); _cassBL6Inch = DEVICE.GetDevice($"TM.CassBLInch6Sensor"); _tmIoInterLock = DEVICE.GetDevice("TM.IoInterLock"); _llLift= DEVICE.GetDevice($"LoadLock.LLLift"); _unLoadLift= DEVICE.GetDevice($"UnLoad.UnLoadLift"); _loadWaferClaw = DEVICE.GetDevice($"LoadLock.LLWaferClaw"); _unLoadWaferClaw = DEVICE.GetDevice($"UnLoad.UnLoadWaferClaw"); } public virtual Result Start(params object[] objs) { return Result.DONE; } public virtual Result Monitor() { return Result.DONE; } public virtual void Abort() { } protected void CheckTraySensor(int id) { Tuple ret = Execute(id, () => { if (SC.GetValue($"System.IsSimulatorMode")) { return true; } return _loadTrayPresence.Value; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Sensor[DI-32] check no tray"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void ClearRobortExtendToDO(int id) { Tuple ret = Execute(id, () => { Notify("Clear RobortExtendTO DO"); _tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false; _tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false; _tmIoInterLock.DoATMRobotExtendUnloadEnable = false; return true; }); } protected void Pick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Pick from {source} {slot + 1} use Blade1 "); if (!robot.Pick(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Pick failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("pick timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void ExtendForPick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"ExtendForPick from {source} {slot + 1} use Blade1 "); if (!robot.CheckToPostMessage(RobotMsg.ExtendForPick, RobotArmEnum.Blade1, source.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"ExtendForPick failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("ExtendForPick timeout, can not complete in {0} seconds", timeout)); robot.Abort(); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void ExtendForPlace(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"ExtendForPlace to {source} {slot + 1} use Blade1 "); if (!robot.CheckToPostMessage(RobotMsg.ExtendForPlace, MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"ExtendForPlace failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("ExtendForPlace timeout, can not complete in {0} seconds", timeout)); robot.Abort(); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void RobotActionComplete(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Robot Action Complete "); if (!robot.CheckToPostMessage(RobotMsg.ActionDone)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Robot Action failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("Robot Action timeout, can not complete in {0} seconds", timeout)); robot.Abort(); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void Place(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Place wafer to {source} {slot + 1} use Blade1 "); if (!robot.Place(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckWaferStatuBeforePick(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check Wafer Status Before Pick"); if (!robot.ExecuteCommand(new object[] { true })) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) { if (WaferManager.Instance.CheckHasWafer(robot.Name, 0)) { EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Wafer!"); return null; } return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckWaferStatuAfterPlace(int id, RobotBaseDevice robot,int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check Wafer Status After Place"); if (!robot.ExecuteCommand(new object[] { true})) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) { if (WaferManager.Instance.CheckHasWafer(robot.Name, 0)) { EV.PostWarningLog(ModuleName.EFEM.ToString(), "Place Finished and Robot Check Has Wafer!"); return null; } return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckTrayStatuBeforePick(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check Tray Status Before Pick"); if (!robot.ExecuteCommand(new object[] { true })) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) { if (WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Name), 0)) { EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Tray!"); return null; } return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void Map(int id, RobotBaseDevice robot, ModuleName source, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Mapping wafer {source}"); if (!robot.WaferMapping(source)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Mapping failed, error {robot.ErrorCode}"); robot.Abort(); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop(string.Format("Mapping timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckRobotReady(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{robot.Name} Check robot ready"); return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) { robot.Abort(); Stop($"{robot.Name} timeout, can not complete in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotHomeExcute(int id, RobotBaseDevice robot, int timeout) { Tuple ret = Execute(id, () => { Notify($"{robot.Name} Execute home"); if (!robot.Home(null)) { EV.PostAlarmLog(Module, $"{robot.Name} Can not home robot"); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { robot.Abort(); Stop($"{robot.Name} home timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CloseVacuum(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Close Vacuum"); _alignerDevice.CloseVaccum(); return true; }, () => { //return !_alignerDevice.IsBusy; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Aligner Close Vacuum Timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void SetWaferRobortExtendToDO(int id, ModuleName target, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Set RobortExtendTO DO"); _tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false; _tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false; _tmIoInterLock.DoATMRobotExtendUnloadEnable = false; if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { if (!_tmIoInterLock.SetWaferRobotExtendLoadEnable(true, out string reasen)) { Notify(reasen); return false; } } else if (target == ModuleName.UnLoad) { if (!_tmIoInterLock.SetWaferRobotExtendUnLoadEnable(true, out string reasen)) { Notify(reasen); return false; } } return true; }, () => { if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { return _tmIoInterLock.DiATMRobotExtendLoadLSideEnableFB; } else if (target == ModuleName.UnLoad) { return _tmIoInterLock.DiATMRobotExtendUnloadEnableFB; } return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set Robot extend to Do timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void SetTrayRobortExtendToDO(int id, ModuleName target, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Set RobortExtendTO DO"); _tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false; _tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false; _tmIoInterLock.DoATMRobotExtendUnloadEnable = false; if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { if (!_tmIoInterLock.SetTrayRobotExtendLoadEnable(true, out string reasen)) { Notify(reasen); return false; } } return true; }, () => { if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { return _tmIoInterLock.DiATMRobotExtendLoadRSideEnableFB; } return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set Robot extend to Do timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckLoadTrayPresence(int id) { Tuple ret = Execute(id, () => { if (SC.GetValue("LoadLock.TrayPresenceCheckEnable")) { if (!_loadTrayPresence.Value) { EV.PostAlarmLog(Module, $"check load Tray Presence sensor false,no Tray in load"); return false; } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }