using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.Util; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.EFEM; using CyberX8_RT.Modules.LPs; using CyberX8_RT.Modules.Rinse; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.Common.Utilities; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CyberX8_RT.Modules.EFEM { public class CycleRobotCycleNewRoutine : ModuleRoutineBase, IRoutine { private enum CycleRobotCycleStep { LoopStart, LoopRunRobotCycle, LoopRunRobotCycleWait, LoopEnd, End } /// /// Cycle次数 /// private int _cycleTimes; /// /// 当前处于第几次Cycle /// private int _currentCycle; private RobotCycleMoveRoutine _cycleMoveRoutine; private List _sequences; private int _alignerAngle; private List _actions; private int _dummySlotNumber = 25; //当前cycle中的dummy slot 数量 public CycleRobotCycleNewRoutine(EfemBase efem) : base(ModuleName.EfemRobot) { _cycleMoveRoutine = new RobotCycleMoveRoutine(efem); } public RState Start(params object[] objs) { _currentCycle = 0; string str = objs[0].ToString(); _sequences = new List(); foreach(string item in str.Split('-')) { _sequences.Add((ModuleName)Enum.Parse(typeof(ModuleName), item)); } if(!CheckRobotCyclePreCondiction(_sequences)) { return RState.Failed; } _cycleTimes=(int)objs[1]; _alignerAngle = (int)objs[2]; _actions = new List(); GenerateCycleAction(); if (_cycleTimes < 1) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Input Robot Cycle Times{_cycleTimes} error"); return RState.Failed; } return Runner.Start(Module, "Start CycleRobotCycleRoutine"); } private void GenerateCycleAction() { if (!ModuleHelper.IsLoadPort(_sequences[0])) { return; } WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_sequences[0]); int count = 0; foreach (WaferInfo item in waferInfos) { if (item.IsEmpty) { continue; } _actions.AddRange(GenerateCycle(_sequences[0], item.Slot, _sequences[1], ModuleHelper.IsDummy(_sequences[1]) ? count : 0)); for (int i = 1; i < _sequences.Count; i++) { if (i == 1) { _actions.AddRange(GenerateCycle(_sequences[i], ModuleHelper.IsDummy(_sequences[i]) ? count : 0, _sequences[i + 1], ModuleHelper.IsDummy(_sequences[i + 1]) ? count : 0)); } else if (i == _sequences.Count - 1) { _actions.AddRange(GenerateCycle(_sequences[i], ModuleHelper.IsDummy(_sequences[i]) ? count : 0, _sequences[0], item.Slot)); } if (ModuleHelper.IsDummy(_sequences[i])) { WaferInfo[] dummywaferInfos = WaferManager.Instance.GetWafers(_sequences[i]); if (dummywaferInfos != null) { _dummySlotNumber = dummywaferInfos.Length; } } } count++; if(count >= _dummySlotNumber) { count = 0; } } } private List GenerateCycle(ModuleName source,int sourceSlot,ModuleName destModule,int destSlot) { List actions = new List(); if (source == ModuleName.Aligner1) { EfemCycleAction action = new EfemCycleAction(); action.Action = "Align"; action.Parameter = _alignerAngle; actions.Add(action); } EfemCycleAction pick = new EfemCycleAction(); MoveItem pickMoveItem = new MoveItem(); pickMoveItem.SourceModule = source; pickMoveItem.SourceSlot = sourceSlot; pick.Parameter = pickMoveItem; pick.Action = "Pick"; actions.Add(pick); EfemCycleAction place = new EfemCycleAction(); MoveItem placeMoveItem = new MoveItem(); placeMoveItem.DestinationModule = destModule; placeMoveItem.DestinationSlot = destSlot; place.Parameter = placeMoveItem; place.Action = "Place"; actions.Add(place); return actions; } public RState Monitor() { Runner.LoopStart(CycleRobotCycleStep.LoopStart, "Loop StartCycleRobotCycleRoutine", _cycleTimes, NullFun, _delay_1ms) .LoopRun(CycleRobotCycleStep.LoopRunRobotCycle, () => _cycleMoveRoutine.Start(_actions) == RState.Running,_delay_1ms) .LoopRunWithStopStatus(CycleRobotCycleStep.LoopRunRobotCycleWait, () => { return CommonFunction.CheckRoutineEndState(_cycleMoveRoutine); }, () => CheckRoutineStopStatus(_cycleMoveRoutine, "CycleRobotCycleRoutine failed"), 86400000)//24小时 .LoopEnd(CycleRobotCycleStep.LoopEnd, UpdateCycleCount, _delay_1ms) .End(CycleRobotCycleStep.End, AchievedCycleCount, _delay_1ms); return Runner.Status; } private bool CheckRoutineStopStatus(IRoutine routine, string error) { bool result = CommonFunction.CheckRoutineStopState(routine); if (result) { Stop($"{error}"); } return result; } /// /// Abort /// public void Abort() { Runner.Stop("CycleRobotCycleRoutine Abort"); } /// /// 统计完成的Cycle次数 /// /// private bool UpdateCycleCount() { _currentCycle += 1; return true; } /// /// /// /// private bool AchievedCycleCount() { _currentCycle -= 1; return true; } /// /// 获取当前Cycle次数 /// /// public int GetCurrentCycle() { return _currentCycle; } private bool CheckRobotCyclePreCondiction(List lists) { bool result = true; //Robot if (!CheckRobotStatus()) { return false; } //LP if(lists.Contains(ModuleName.LP1)) { if (!CheckLoadPortStatus(ModuleName.LP1)) { return false; }; } else if (lists.Contains(ModuleName.LP2)) { if (!CheckLoadPortStatus(ModuleName.LP2)) { return false; }; } else { if (!CheckLoadPortStatus(ModuleName.LP2)) { return false; }; } //Dummy if (lists.Contains(ModuleName.Dummy1)) { if (!CheckDummyStatus(ModuleName.Dummy1)) { return false; }; } else if(lists.Contains(ModuleName.Dummy2)) { if (!CheckDummyStatus(ModuleName.Dummy2)) { return false; }; } //Puf if (lists.Contains(ModuleName.PUF1) && !CheckPufStatus(ModuleName.PUF1)) { return false ; } //Srd if (lists.Contains(ModuleName.SRD1)) { if (!CheckSrdStatus(ModuleName.SRD1)) { return false; }; } else if(lists.Contains(ModuleName.SRD2)) { if (!CheckSrdStatus(ModuleName.SRD2)) { return false; }; } return result; } //检查robot状态 private bool CheckRobotStatus() { bool result = true; if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)) { Stop($"Efem robot arm already has a wafer, cannot do the RobotCycle action"); result = false; } return result; } //检查loadport状态 private bool CheckLoadPortStatus(ModuleName loadpoartName) { bool result = true; if (ModuleHelper.IsInstalled(loadpoartName)) { Loadport loadPort = GetLoadPort(loadpoartName); if (loadPort == null) { Stop($"{loadpoartName} is null"); return false; } WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(loadpoartName); if (waferInfos.Length < 1) { Stop($"there is no wafer in {loadpoartName}"); return false; } } else { Stop($"{loadpoartName} is not installed"); return false; } return result; } private Loadport GetLoadPort(ModuleName station) { LoadPortModule loadPortModule = Singleton.Instance.EFEM.GetLoadportModule(station - ModuleName.LP1); return loadPortModule.LPDevice; } //Dummy状态判断 private bool CheckDummyStatus(ModuleName dummyName) { bool result = true; if (!ModuleHelper.IsInstalled(dummyName)) { Stop($"{dummyName} is not installed"); return false; } //若dummy存在wafer,需要人工处理 DummyDevice dummyDevice = Singleton.Instance.EFEM.GetDummyDevice(dummyName - ModuleName.Dummy1); if (dummyDevice != null) { if (!dummyDevice.HasCassette) { Stop($"{dummyName} dose not have cassette"); return false; } WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(dummyName); if (waferInfos.Length > 0) { foreach (var item in waferInfos) { if (item != null && !item.IsEmpty) { Stop($"There are wafers inside the {dummyName},cannot do the RobotCycle action"); return false; } } } } return result; } //检查puf private bool CheckPufStatus(ModuleName pufName) { bool result = true; if (!ModuleHelper.IsInstalled(pufName)) { Stop($"{pufName} is not install"); return false; } JetAxisBase puf1RotationAxis = DEVICE.GetDevice($"{ModuleName.PUF1}.Rotation"); if (puf1RotationAxis == null) { Stop("Puf1 Rotation Axis is null"); return false; } double puf1RotationPosition = puf1RotationAxis.MotionData.MotorPosition; if ( !puf1RotationAxis.CheckPositionIsInStation(puf1RotationPosition, "Robot")) { Stop($"PUF1 Rotation {puf1RotationPosition} is not in Robot"); return false; } return result; } //检查srd private bool CheckSrdStatus(ModuleName SrdName) { bool result = true; if (!ModuleHelper.IsInstalled(SrdName)) { Stop($"{SrdName} is not install"); return false; } return result; } } }