using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using athosRT.Devices; using athosRT.Devices.PA; using athosRT.FSM; using athosRT.tool; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using static athosRT.Modules.FLP.FlipperEntity; using EV = athosRT.tool.EV; namespace athosRT.Modules.EFEMs.Routine { public class PlaceRoutine : ModuleRoutineBase, FSM.IRoutine { private string _routinename = "PlaceRoutine"; private string _errorhead = "cannot place for the reason:"; protected bool MultiWaferSize = Singleton.Instance.GetValue(nameof(MultiWaferSize)).GetValueOrDefault(); private SCConfigItem _scPlaceTimeout = (SCConfigItem)null; private int _timeout = 0; private int _axisTimeout = 0; private int _axisSpeed = 0; private int _alignerdelay = 0; private int _coolingdelay = 0; private int delaytime = 0; public LoadPort _lpDevice; private bool _skipWait; protected readonly bool HaveMotionAxis = Singleton.Instance.GetValue("MotionAxisInstalled").GetValueOrDefault(); RobotBaseDevice robot = null; protected Aligner aligner = null; protected IoCoolingBuffer buffer1 = null; protected IoCoolingBuffer buffer2 = null; protected PreAligner aligner1 = null; protected PreAligner aligner2 = null; protected LoadLockDevice ll1 = null; protected LoadLockDevice ll2 = null; protected IoCoolingBuffer _ioCoolBuffer; private int _existInterval = SC.GetValue("Robot.Robot.ExistInterval"); protected static readonly bool LoadLockDoorControlByStation = Singleton.Instance.GetValue("LLDoorControlByStation").GetValueOrDefault(); public ModuleName Station { get; set; } protected int OffsetX; protected int OffsetY; protected int OffsetZ; public int Slot { get; set; } private bool _isFlipper = false; public Hand Blade { get; set; } //放置 public PlaceRoutine(ModuleName module) : base(module) { robot = DEVICE.GetDevice("Robot"); _alignerdelay = SC.GetValue("System.AlignerPinDownDelay"); _coolingdelay = SC.GetValue("System.CoolingPinDownDelay"); _scPlaceTimeout = SC.GetConfigItem("Robot.TimeLimitForPlaceWafer"); aligner = DEVICE.GetDevice("Aligner"); buffer1 = DEVICE.GetDevice("CoolingBuffer1"); buffer2 = DEVICE.GetDevice("CoolingBuffer2"); aligner1 = DEVICE.GetDevice("Aligner1"); aligner2 = DEVICE.GetDevice("Aligner2"); if (!HaveMotionAxis) return; _axisTimeout = SC.GetValue("MotionAxis.MoveTimeout"); _axisSpeed = SC.GetValue("MotionAxis.AutoSpeed"); } public RState Start(params object[] objs) { Reset(); _isFlipper = false; _alignerdelay = SC.GetValue("System.AlignerPinDownDelay"); _coolingdelay = SC.GetValue("System.CoolingPinDownDelay"); _timeout = robot.RobotCommandTimeout * 1000; if (!Singleton.Instance.IsOnlineMode && (ModuleHelper.IsCoolingBuffer(this.Station) || ModuleHelper.IsAligner(this.Station))) { delaytime = !ModuleHelper.IsCoolingBuffer(Station) ? _alignerdelay * 1000 : _coolingdelay * 1000; } else { delaytime = 0; } if (WaferManager.Instance.CheckHasWafer(Station, Slot)) { LogObject.Error(Station.ToString(), "站点有wafer 无法Place"); return RState.Failed; } if (ModuleHelper.IsTurnOverStation(Station)) _isFlipper = true; //LogObject.Info("Place", "Place to Wa"); return Runner.Start(Module, "Place Routine"); } public enum PlaceStep { WaitForPlaceModuleIdle, CoolBufferMoveUP, CheckBladeWaferIsExist, CheckBeforePlace, PlaceWafer, LoadLockCloseAtmDoor, WaitForCoolBuffer, CoolBufferMoveDown, WaitCoolBufferMoveDown, CheckAfterPlace, NotifyFlipperPrepare, NotifyFlipperOver, } public RState Monitor() { if (_isFlipper) Runner .Wait(PlaceStep.WaitForPlaceModuleIdle, CheckFlipperIsIdle, _timeout) .Run(PlaceStep.NotifyFlipperPrepare, NotifyFlipperOpen, CheckFlipperOpen, _timeout) .Run(PlaceStep.CheckBeforePlace, NullFun, CheckBeforePlace, _timeout) .Run(PlaceStep.PlaceWafer, PlaceWafer, WaitRobotMotion) .Run(PlaceStep.NotifyFlipperOver, NotifyFlipperClose, CheckFlipperIsIdle, _timeout) .End(PlaceStep.CheckAfterPlace, NullFun, CheckAfterPlace, _timeout); else Runner .Run(PlaceStep.CoolBufferMoveUP,CoolBufferMoveUP, WaitCoolBufferMoveUp, _timeout) .Run(PlaceStep.CheckBladeWaferIsExist,CheckBladeWaferIsExist, WaitRobotMotion, _timeout) .Run(PlaceStep.CheckBeforePlace,NullFun,CheckBeforePlace, _timeout) .Run(PlaceStep.PlaceWafer,PlaceWafer, WaitRobotMotion) .Run(PlaceStep.LoadLockCloseAtmDoor,LoadLockCloseAtmDoor,LoadLockCloseAtmDoorOut,_timeout) .Delay(PlaceStep.WaitForCoolBuffer, delaytime) .Run(PlaceStep.CoolBufferMoveDown,CoolBufferMoveDown, WaitCoolBufferMoveDown, _timeout) .End(PlaceStep.CheckAfterPlace, NullFun,CheckAfterPlace, _timeout); //.Wait(PlaceStep.WaitCoolBufferMoveUp,WaitCoolBufferMoveUp,_timeout) //.Wait(PlaceStep.WaitRobotMotion,WaitRobotMotion,_timeout) //.Wait(PlaceStep.WaitRobotMotion, WaitRobotMotion, _timeout) //.Wait(PlaceStep.WaitRobotMotion,WaitRobotMotion,_timeout) //.Wait(PlaceStep.WaitCoolBufferMoveDown,WaitCoolBufferMoveDown,_timeout) return Runner.Status; } private bool CheckFlipperIsIdle() { return Singleton.Instance.GetFlipper().IsIdle; } private bool NotifyFlipperOpen() { Singleton.Instance.GetFlipper().PostMsg(FlipperMSG.PrepareTransfer); return true; } private bool NotifyFlipperClose() { Singleton.Instance.GetFlipper().PostMsg(FlipperMSG.EndTransfer); return true; } private bool CheckFlipperOpen() { return Singleton.Instance.GetFlipper().IsTransfer; } private bool CheckAfterPlace() { //"Check wafer information after wafer placed", this.Station, this.Slot, this.Blade //if (ModuleHelper.IsLoadLock(Station) && Singleton.Instance.IsOnlineMode) // Singleton.Instance.DeleteWafer(Station, Slot); switch (Blade) { case Hand.Blade1: if (!CheckSensorNoWafer(ModuleName.Robot, (int)Blade)) { LogObject.Error("Robot", "Wafer Is Still Detected on blade1 After Place!"); if (ModuleHelper.IsLoadPort(Station)) Singleton.Instance.GetLP(Station).PostMsg(268435443); EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend); return false; } break; case Hand.Blade2: for (int index = 0; index < robot.Blade2Slots; ++index) { if (!CheckSensorNoWafer(ModuleName.Robot, (int)(Blade + index))) { LogObject.Error("Robot", "Wafer Is Still Detected on blade2 After Place!"); if (ModuleHelper.IsLoadPort(Station)) Singleton.Instance.GetLP(Station).PostMsg(268435443); EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend); return false; } } break; default: for (int slot1 = 0; slot1 < this.robot.Blade2Slots + 1; ++slot1) { if (!CheckSensorNoWafer(ModuleName.Robot, slot1)) { if (ModuleHelper.IsLoadPort(Station)) Singleton.Instance.GetLP(Station).PostMsg(268435443); EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend); return false; } } break; } return true; } private bool WaitCoolBufferMoveDown() { if (!Singleton.Instance.IsOnlineMode && (ModuleHelper.IsCoolingBuffer(this.Station))) { IoCoolingBuffer device = GetCoolBuffer(Station); if (!device.Error) return device.CheckMovedDown() && !device.Busy; return false; } return true; } private bool CoolBufferMoveDown() { if (!Singleton.Instance.IsOnlineMode && (ModuleHelper.IsCoolingBuffer(this.Station))) { IoCoolingBuffer device = GetCoolBuffer(Station); string reason = ""; if (device.CheckPinDown() || device.Move(Singleton.Instance.GetWaferSize(Station, Slot), false, out reason)) return true; else LogObject.Error(_routinename, _errorhead+reason); return false; } if (ModuleHelper.IsAligner(this.Station)) { return true; } return true; } private bool CheckSensorNoWafer(ModuleName chamber, int slot) { if (SC.GetValue("System.IsSimulatorMode") || chamber != ModuleName.Robot) return Singleton.Instance.CheckNoWafer(chamber, slot); return slot == 0 ? !robot.IsWaferPresenceOnBlade1 : !robot.IsWaferPresenceOnBlade2; } private bool LoadLockCloseAtmDoor() { if (LoadLockDoorControlByStation && ModuleHelper.IsLoadLock(this.Station) && !Singleton.Instance.IsOnlineMode) { string _reason = string.Empty; if (LoadLockDevice.LoadLockAtmDoorState == LoadLockDoorState.Closed || LoadLockDevice.CloseAtmDoor(out _reason)) { LogObject.Info("LL","ATM Door Closed"); return true; } else { LogObject.Error("LL", $"ATM Door cannot Closed {_reason}"); return false; } } LogObject.Info("LL", "LL not has to control ATM"); return true; } private bool LoadLockCloseAtmDoorOut() { if (LoadLockDoorControlByStation && ModuleHelper.IsLoadLock(this.Station) && !Singleton.Instance.IsOnlineMode) { string _reason = string.Empty; if (LoadLockDevice.LoadLockAtmDoorState == LoadLockDoorState.Closed) { LogObject.Info("LL", "ATM Door Closed"); return true; } else { LogObject.Error("LL", "ATM Door not Closed"); return false; } } LogObject.Info("LL", "LL not has to control ATM"); return true; } private bool PlaceWafer() { //if (!ModuleHelper.IsLoadLock(Station)) { bool flag = OffsetX == 0 && OffsetY == 0 && OffsetZ == 0 ? robot.Place((RobotArmEnum)Blade, Station.ToString(), Slot) : this.robot.PlaceEx((RobotArmEnum)Blade, Station.ToString(), Slot, (float)OffsetX, (float)OffsetY, (float)OffsetZ); if (flag) { LogObject.Info("Place", $"执行成功:{Station}-{Slot}"); return true; } else { LogObject.Error("Place", "执行失败"); return false; } } //LogObject.Info("Place", "因是LL无法执行"); return true; } private bool CheckBeforePlace() { //this.Station, this.Slot, this.Blade string reason = ""; if (!CheckRobotMotionInterlock(Station,Slot,out reason)) { LogObject.Error("Place",$"cannot place for the reason:{reason}"); return false; } switch (Blade) { case Hand.Blade1: //检查 目标上有没有wafer 有就false if (!Singleton.Instance.CheckWafer(Station,Slot,WaferStatus.Empty)) { return false; } //检查robot上有没有wafer 没有就返回false if (!Singleton.Instance.CheckWafer(ModuleName.Robot, (int)Blade, WaferStatus.Normal)) { //EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend); return false; } if (!CheckSeneorHasWafer(ModuleName.Robot, (int)Blade)) { //EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend); return false; } //==debug //if (ModuleHelper.IsLoadPort(Station) && SC.GetStringValue("CarrierInfo.LowerThicknessType") != SC.GetStringValue(string.Format("CarrierInfo.{0}ThicknessType", (object)Station))) //{ // //EV.PostAlarmLog(ModuleName.System.ToString(), string.Format("The wafer thickness of the lower arm is different from {0}.", (object)Station)); // return false; //} break; case Hand.Blade2: default: bool flag1 = true; for (int index = 0; index < robot.Blade2Slots; ++index) { if (!Singleton.Instance.CheckWafer(Station, Slot + index, WaferStatus.Empty)) { //EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferPresentWithRecord, (object)string.Format("Target {0}{1:D2}", (object)Station.ToString(), (object)(Slot + index + 1))); return false; } flag1 &= Singleton.Instance.CheckWafer(ModuleName.Robot, (int)(Blade + index), WaferStatus.Normal); if (!this.CheckSeneorHasWafer(ModuleName.Robot, (int)(Blade + index))) { //EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend); return false; } } if (!flag1) { //EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend); return false; } //==debug== //if (ModuleHelper.IsLoadPort(Station) && SC.GetStringValue("CarrierInfo.UpperThicknessType") != SC.GetStringValue(string.Format($"CarrierInfo.{Station}ThicknessType"))) //{ // //EV.PostAlarmLog(ModuleName.System.ToString(), string.Format("The wafer thickness of the lower arm is different from {0}.", (object)Station)); // return false; //} break; } if (!ModuleHelper.IsCoolingBuffer(Station) || DEVICE.GetDevice(Station.ToString()).CheckPinUp()) { return true; } EV.PostWarningLog(Station.ToString(), "Can not place wafer to buffer, buffer isn't pick position."); return false; } private bool CheckSeneorHasWafer(ModuleName robot, int slot) { if (SC.GetValue("System.IsSimulatorMode") || robot != ModuleName.Robot) return Singleton.Instance.CheckHasWafer(robot, slot); return slot == 0 ? this.robot.IsWaferPresenceOnBlade1 : this.robot.IsWaferPresenceOnBlade2; } private bool CheckBladeWaferIsExist() { if (!robot.ReadParameter(new object[3] { "CheckWaferIsPresence", (Blade == Hand.Blade1 ? 0 : 1), _existInterval })) { //手臂上有wafer 无法pick LogObject.Error("Robot", "手臂上无片 无法place"); return false; } else { LogObject.Info("Robot", "手臂上有片 可以正常place"); return true; } } private bool WaitRobotMotion() { if (robot.IsReady()) { LogObject.Info("Robot", "robot is ready."); return true; } else { if (robot.IsError) { LogObject.Info("Robot", "Robot进入Error"); } return false; } } private bool WaitCoolBufferMoveUp() { //if (ModuleHelper.IsCoolingBuffer(Station) ) //{ // IoCoolingBuffer device = GetCoolBuffer(Station); // if (!device.Error) // return device.CheckMovedUp() && !device.Busy; // return false; //} if (ModuleHelper.IsAligner(Station)) { return true; } return true; } private bool CoolBufferMoveUP() { //if (ModuleHelper.IsCoolingBuffer(Station)) //{ // WaferSize size = Singleton.Instance.GetWaferSize(ModuleName.Robot,0); // IoCoolingBuffer device = GetCoolBuffer(Station); // string _reason = ""; // if (device.CheckPinUp() || device.Move(size, true, out _reason)) // { // return true; // } // else // { // LogObject.Error(_routinename, _errorhead + _reason); // return false; // } //} if (ModuleHelper.IsAligner(Station)) { return true; } return true; } public void Abort() { } public IoCoolingBuffer GetCoolBuffer(ModuleName coolbufferName) { switch (coolbufferName) { //case ModuleName.Aligner1: // _ioCoolBuffer = aligner1; // break; //case ModuleName.Aligner2: // this._ioCoolBuffer = aligner2; // break; case ModuleName.CoolingBuffer1: this._ioCoolBuffer = this.buffer1; break; case ModuleName.CoolingBuffer2: this._ioCoolBuffer = this.buffer2; break; } return _ioCoolBuffer; } protected bool CheckRobotMotionInterlock(ModuleName chamber, int slot, out string reason) { reason = string.Empty; if (robot.RobotState == RobotStateEnum.Error) { reason = "robot is error."; if (ModuleHelper.IsLoadPort(Station)) Singleton.Instance.GetLP(Station).PostMsg(268435443); return false; } if (!robot.IsReady()) { reason = string.Format("robot isn't Ready."); return false; } if (chamber == ModuleName.Aligner) { //if (aligner.Moving) //{ // reason = string.Format("aligner is moving."); // return false; //} if (robot.IsReady()) return true; reason = string.Format("aligner isn't Ready."); return false; } if (ModuleHelper.IsTurnOverStation(chamber)) { if (robot.IsReady()) return true; } if (ModuleHelper.IsLoadPort(chamber)) { LoadPortBaseDevice device = DEVICE.GetDevice(chamber.ToString()); if (!device.IsEnableTransferWafer(out reason)) { reason = string.Format($"{chamber} isn't Ready.The reason is {reason}"); return false; } if (device.MapError) { reason = string.Format("{0} Map has crossed error.", (object)chamber.ToString()); return false; } if (ModuleHelper.IsLoadPort(chamber) && !Singleton.Instance.GetLP(chamber).IsLoaded) { if (Singleton.Instance.GetLP(chamber).IsDoorOpen) { reason = string.Format("{0} SMIF1PODOPEN signal is Off.", (object)chamber.ToString()); return false; } if (Singleton.Instance.GetLP(chamber).IsPresent) { reason = string.Format("{0} SensorSMIF1PODPRESENT signal is Off,Foup is presence.", (object)chamber.ToString()); return false; } if (Singleton.Instance.GetLP(chamber).IsReady) { reason = string.Format("{0} SensorSMIF1READY signal is Off.", (object)chamber.ToString()); return false; } } return true; } if (ModuleHelper.IsLoadLock(chamber) || ModuleHelper.IsPm(chamber)) { if (WaferManager.Instance.CheckHasWafer(chamber, 0)) reason = "记录中该位置有wafer"; switch (chamber) { case ModuleName.LL1: case ModuleName.LLA: case ModuleName.PMA: if (!DeviceModel.LL1DoorIsOpen.Value) reason = $"{chamber}门信号未开启 无法传送"; return DeviceModel.LL1DoorIsOpen.Value && WaferManager.Instance.CheckNoWafer(chamber, 0); case ModuleName.LL2: case ModuleName.LLB: case ModuleName.PMB: if (!DeviceModel.LL2DoorIsOpen.Value) reason = $"{chamber}门信号未开启 无法传送"; return DeviceModel.LL2DoorIsOpen.Value && WaferManager.Instance.CheckNoWafer(chamber, 0); default: return true; } } if (ModuleHelper.IsCoolingBuffer(chamber) ) { IoCoolingBuffer device = DEVICE.GetDevice(chamber.ToString()); if (device.Busy) { reason = "buffer is not idle"; return false; } if (device.CheckPinUp()) return true; reason = "buffer pin not up position"; return false; } if (ModuleHelper.IsAligner(Station)) { //PreAligner device = DEVICE.GetDevice(Station.ToString()); //if (device.Busy) //{ // reason = "Aligner is not idle"; // return false; //} return true; } if (ModuleHelper.IsBuffer(Station)) { return true; } reason = "error target"; return false; } } }