using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using System; namespace FurnaceRT.Equipments.CarrierRobots { public class CarrierRobotHome : ModuleRoutine, IRoutine { enum RoutineStep { SetCommunication, RobotReset, RobotSetServoOn, SetLoadArm1, SetLoadArm2, Home, DoorClose, CheckLoad, SetSpeed, RobotRequestCassettePresent, UpdateWaferInfoByRobotSensor, } private CarrierRobotModule _cassetteRobotModule; private int _timeout = 0; private int _speed = 1; public CarrierRobotHome(CarrierRobotModule cassetteModule) { _cassetteRobotModule = cassetteModule; Module = cassetteModule.Module; Name = "Home"; } public Result Start(params object[] objs) { Reset(); _timeout = SC.GetValue($"{Module}.HomeTimeout"); _speed = SC.GetValue($"{Module}.RobotSpeed"); _cassetteRobotModule.RobotHomeFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.RobotHomeTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.SetSpeedFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.SetSpeedTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.RequestCassettePresentFailAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.RequestCassettePresentTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; _cassetteRobotModule.ShutterCloseTimeoutAlarm.RetryMessage = (int)CarrierRobotModule.MSG.Home; Notify($"Start"); return Result.RUN; } public void Abort() { } public override Result Monitor() { try { PauseRountine(_cassetteRobotModule.CarrierRobotDevice.IsPause); if (_cassetteRobotModule.CarrierRobotDevice.IsPause) return Result.RUN; //RobotReset((int)RoutineStep.RobotReset, _timeout); //RobotSetServoOn((int)RoutineStep.RobotSetServoOn, true, _timeout); RobotHome((int)RoutineStep.Home, _timeout); SaferDoorOpen((int)RoutineStep.DoorClose, false, _timeout); //RobotCheckLoad((int)RoutineStep.CheckLoad, Hand.Blade1, _timeout); RobotSetSpeed((int)RoutineStep.SetSpeed, _speed, _timeout); RobotRequestCassettePresent((int)RoutineStep.RobotRequestCassettePresent, Hand.Blade1, _timeout); UpdateCassetteInfoByRobotSensor((int)RoutineStep.UpdateWaferInfoByRobotSensor); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException ex) { return Result.FAIL; } _cassetteRobotModule.ResetRobotActionCommand(); Notify("Finished"); return Result.DONE; } private void RobotReset(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set robot reset"); _cassetteRobotModule.SetCassetteRobotReset(); return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady()) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _cassetteRobotModule.RobotHomeTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void RobotSetServoOn(int id, Robot robot, bool isOn, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set servo {(isOn ? "on" : "off")}"); if (!robot.SetServoOnOff(isOn, out string reason)) { //_cassetteRobotModule.SetServoOnFailAlarm.Description = reason; _cassetteRobotModule.SetServoOnFailAlarm.Set(reason); return false; } return true; }, () => { if (!robot.Busy) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.CheckLoadTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.CheckLoadTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotSetCommunication(int id, Robot robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Set default communication"); if (!robot.SetCommunication(out string reason)) { Stop(reason); return false; } return true; }, () => { if (!robot.Busy) { 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($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotSetLoad(int id, Robot robot, Hand hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set default load {hand}"); if (!robot.SetLoad(hand, out string reason)) { Stop(reason); return false; } return true; }, () => { if (!robot.Busy) { 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($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotHome(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Execute home"); if (!_cassetteRobotModule.SetCassetteRobotHome(out string reason)) { //_cassetteRobotModule.RobotHomeFailAlarm.Description = reason; _cassetteRobotModule.RobotHomeFailAlarm.Set(reason); return false; } return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.RobotHomeTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.RobotHomeTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void UpdateCassetteInfoByRobotSensor(int id) { Tuple ret = Execute(id, () => { Notify($"Update cassette info by robot cassette present sensor"); if (SC.GetValue("System.IsSimulatorMode")) return true; if (_cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade1 && !CarrierManager.Instance.CheckHasCarrier(ModuleHelper.Converter(_cassetteRobotModule.Module), 0)) { EV.PostInfoLog(Module, "Cassette Robot sensor found cassette on blade 1"); CarrierManager.Instance.CreateCarrier(_cassetteRobotModule.Module); } if (!_cassetteRobotModule.CarrierRobotDevice.IsWaferPresenceOnBlade1 && !CarrierManager.Instance.CheckNoCarrier(ModuleHelper.Converter(_cassetteRobotModule.Module), 0)) { EV.PostInfoLog(Module, "Cassette Robot sensor no cassette on blade 1"); CarrierManager.Instance.DeleteCarrier(_cassetteRobotModule.Module); } return true; }); if (ret.Item1) { throw (new RoutineBreakException()); } } public void RobotSetSpeed(int id, int speed, int timeout) { Tuple ret = ExecuteAndWait(id, () => { if (speed > 100) speed = 100; if (speed < 1) speed = 1; Notify($"set speed to {speed}"); if (!_cassetteRobotModule.SetSpeed(speed, out string reason)) { //_cassetteRobotModule.SetSpeedFailAlarm.Description = reason; _cassetteRobotModule.SetSpeedFailAlarm.Set(reason); return false; } return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.SetSpeedTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.SetSpeedTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void RobotRequestCassettePresent(int id, Hand hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("request cassette present"); if (!_cassetteRobotModule.RequestCassettePresent(hand, out string reason)) { //_cassetteRobotModule.RequestCassettePresentFailAlarm.Description = reason; _cassetteRobotModule.RequestCassettePresentFailAlarm.Set(reason); return false; } return true; }, () => { if (_cassetteRobotModule.CarrierRobotDevice.IsReady() && !_cassetteRobotModule.CarrierRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_cassetteRobotModule.RequestCassettePresentTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _cassetteRobotModule.RequestCassettePresentTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckCassetteInfoByRobotSensor(int id, RobotBaseDevice robot, Hand hand, bool isAfterPick) { Tuple ret = Execute(id, () => { Notify($"check wafer info by robot RQ present"); if (SC.GetValue("System.IsSimulatorMode")) return true; if (hand == Hand.Blade1 || hand == Hand.Both) { if (!isAfterPick && robot.IsWaferPresenceOnBlade1) { EV.PostWarningLog(Module, "Cassette Robot sensor found cassette on blade 1"); return false; } if (isAfterPick && !robot.IsWaferPresenceOnBlade1) { EV.PostInfoLog(Module, "Cassette Robot sensor no cassette on blade 1"); return false; } } if (hand == Hand.Blade2 || hand == Hand.Both) { if (!isAfterPick && robot.IsWaferPresenceOnBlade2) { EV.PostWarningLog(Module, "Cassette Robot sensor found cassette on blade 2"); return false; } if (isAfterPick && !robot.IsWaferPresenceOnBlade2) { EV.PostInfoLog(Module, "Cassette Robot sensor no cassette on blade 2"); return false; } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"check cassette info failed."); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void SaferDoorOpen(int id, bool isOpen, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Shutter Door {(isOpen ? "Open" : "Close")}"); if (isOpen) _cassetteRobotModule.DoorDevice.Open(); else _cassetteRobotModule.DoorDevice.Close(); return true; }, () => { return isOpen ? _cassetteRobotModule.DoorDevice.OpenCloseStatus == Devices.DeviceStatus.Open : _cassetteRobotModule.DoorDevice.OpenCloseStatus == Devices.DeviceStatus.Close; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } else if (ret.Item2 == Result.TIMEOUT) //timeout { if (isOpen) _cassetteRobotModule.ShutterOpenTimeoutAlarm.Set($"timeout over {timeout} seconds"); else _cassetteRobotModule.ShutterCloseTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw new RoutineBreakException(); } } } }