using Aitex.Core.Common; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using CyberX8_Core; using CyberX8_RT.Devices.EFEM; using CyberX8_RT.Modules.LPs; using MECF.Framework.Common.Beckhoff.Station; using MECF.Framework.Common.Equipment; 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 RobotCycleRoutine : ModuleRoutineBase, IRoutine { private enum RobotCycleStep { LPCycleStrat, PickFromLP, PickFromLPCheck, PlaceToAligner, PlaceToAlignerCheck, AlignAction, AlignCompleteCheck, PickFromAligner, PickFromAlignerCheck, PlaceToDummy, PlaceToDummyCheck, PickFromDummy, PickFromDummyCheck, PlaceToSrd, PlaceToSrdCheck, PickFromSrd, PickFromSrdCheck, PlaceToLP, PlaceToLPCheck, LPCycleEnd, End } EfemBase _efem; /// /// 当前Cycle选中的LP里面的Wafer数量 /// private int _waferCount; private EfemPickRoutine _efemPickRoutine; private EfemPlaceRoutine _efemPlaceRoutine; private EFEMAlignRoutine _efemAlignRoutine; private ModuleName _targetLP; private ModuleName _targetAligner; private ModuleName _targetDummy; private ModuleName _targetSrd; private Queue _lpToAlignerMoveItem = new Queue(); private Queue _alignerToDummyMoveItem = new Queue(); private Queue _alignerToSrdMoveItem = new Queue(); private Queue _dummyToLpMoveItem = new Queue(); private Queue _dummyToSrdMoveItem = new Queue(); private Queue _srdToLpMoveItem = new Queue(); private Queue _lpWaferIndex = new Queue(); //记录有LP有Wafer的slot号 private int _moveTimeout = 20 * 1000; private int _dummySlotNumber = 0; private object[] alignerParamater; public RobotCycleRoutine(EfemBase efem) : base(ModuleName.EfemRobot) { _efem = efem; _efemPickRoutine = new EfemPickRoutine(efem); _efemPlaceRoutine = new EfemPlaceRoutine(efem); _efemAlignRoutine = new EFEMAlignRoutine(efem); } public RState Start(params object[] objs) { _lpWaferIndex.Clear();//初始化LP 有wafer的slot号 _waferCount = 0; //初始化wafercount的数量 alignerParamater = new object[3];//初始化Align参数 alignerParamater[0] = ModuleName.Aligner1; alignerParamater[1] = 0; if (objs.Length >= 6) { _targetLP = (ModuleName)objs[0]; _targetAligner = (ModuleName)objs[1]; _targetDummy = (ModuleName)objs[2]; _targetSrd = (ModuleName)objs[3]; alignerParamater[2] = (int)objs[5]; } else { return RState.Failed; } if (!CheckPreCondition()) //检验前提条件 { return RState.Failed; } _moveTimeout = SC.GetValue($"EFEM.MotionTimeout") * 1000; MoveItem lpToAlignerMoveItem = new MoveItem //LP To Aligner { SourceModule = _targetLP, SourceSlot = _lpWaferIndex.Dequeue(), DestinationModule = ModuleName.Aligner1, DestinationSlot = 0, RobotHand = 0 //表示blade1 }; _lpToAlignerMoveItem.Enqueue(lpToAlignerMoveItem); MoveItem alignerToDummyMoveItem = new MoveItem //Aligner To Dummy { SourceModule = ModuleName.Aligner1, SourceSlot = 0, DestinationModule = _targetDummy, DestinationSlot = 0, RobotHand = 0 }; _alignerToDummyMoveItem.Enqueue(alignerToDummyMoveItem); MoveItem alignerToSrdMoveItem = new MoveItem //Aligner To Srd { SourceModule = ModuleName.Aligner1, SourceSlot = 0, DestinationModule = _targetSrd, DestinationSlot = 0, RobotHand = 0 }; _alignerToSrdMoveItem.Enqueue(alignerToSrdMoveItem); MoveItem dummyToLpMoveItem = new MoveItem //Dummy To LP { SourceModule = _targetDummy, SourceSlot = 0, DestinationModule = _targetLP, DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置 RobotHand = 0 }; _dummyToLpMoveItem.Enqueue(dummyToLpMoveItem); MoveItem dummyToSrdMoveItem = new MoveItem //Dummy To Srd { SourceModule = _targetDummy, SourceSlot = 0, DestinationModule = _targetSrd, DestinationSlot = 0, RobotHand = 0 }; _dummyToSrdMoveItem.Enqueue(dummyToSrdMoveItem); MoveItem srdToLpMoveItem = new MoveItem //SRD To LP { DestinationModule = _targetLP, DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置 RobotHand = 0 }; _srdToLpMoveItem.Enqueue(srdToLpMoveItem); return Runner.Start(Module, "Robot Cycle start"); } public RState Monitor() { Runner.LoopStart(RobotCycleStep.LPCycleStrat, "LP Cycle Start", _waferCount, NullFun, _delay_1ms) .LoopRun(RobotCycleStep.PickFromLP, () => { return _efemPickRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms) .LoopRunWithStopStatus(RobotCycleStep.PickFromLPCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); }, () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from LP failed")) .LoopRun(RobotCycleStep.PlaceToAligner, () => { return _efemPlaceRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms) .LoopRunWithStopStatus(RobotCycleStep.PlaceToAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to aligner failed")) .LoopRun(RobotCycleStep.AlignAction, () => { return _efemAlignRoutine.Start(alignerParamater) == RState.Running; }, _delay_1ms) .LoopRunWithStopStatus(RobotCycleStep.AlignCompleteCheck, () => { return CommonFunction.CheckRoutineEndState(_efemAlignRoutine); }, () => CheckRoutineStopStatus(_efemAlignRoutine, "Efem aligner Action failed")) .LoopRun(RobotCycleStep.PickFromAligner, () => { return _efemPickRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms) .LoopRunWithStopStatus(RobotCycleStep.PickFromAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); }, () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from aligner failed")) //从Aligner到dummy .LoopRunIf(RobotCycleStep.PlaceToDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to dummy failed")) .LoopRunIf(RobotCycleStep.PickFromDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PickFromDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); }, () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from dummy failed")) //从Aligner到SRD的 .LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy==ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed")) .LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return _efemPickRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); }, () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed")) //从dummy到SRD的 .LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed")) .LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); }, () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed")) //从Dummy回LP .LoopRunIf(RobotCycleStep.PlaceToLP, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed")) //从SRD回LP .LoopRunIf(RobotCycleStep.PlaceToLP, _targetSrd != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_srdToLpMoveItem) == RState.Running; }, _delay_1ms) .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetSrd != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); }, () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed")) .LoopEnd(RobotCycleStep.LPCycleEnd, UpdateMoveItem, _delay_1ms) .End(RobotCycleStep.End, ClearMoveItem, _delay_1ms); return Runner.Status; } public void Abort() { _efem.Halt(); } #region 功能方法 private bool CheckPreCondition() { if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)) { Stop($"Efem robot arm already has a wafer, cannot do the RobotCycle action"); return false; } //LoadPort状态判断 if (ModuleHelper.IsLoadPort(_targetLP) && ModuleHelper.IsInstalled(_targetLP)) { Loadport loadPort = GetLoadPort(_targetLP); if (loadPort == null) { Stop($"{_targetLP} is null"); return false; } WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetLP); for (int i = 0; i < waferInfos.Length; i++) { if (waferInfos[i] != null && !waferInfos[i].IsEmpty) { _waferCount++; _lpWaferIndex.Enqueue(i); } } if (_waferCount < 1) { Stop($"there is no wafer in {_targetLP}"); return false; } } else if(ModuleHelper.IsLoadPort(_targetLP) && !ModuleHelper.IsInstalled(_targetLP)) { Stop($"{_targetLP} is not installed"); return false; } //Aligner状态判断 //if (!ModuleHelper.IsInstalled(_targetAligner)) //{ // Stop($"{_targetAligner} is not installed"); // return false; //} //Dummy状态判断 if (!ModuleHelper.IsInstalled(_targetDummy)) { Stop($"{_targetDummy} is not installed"); return false; } //若dummy存在wafer,需要人工处理 DummyDevice dummyDevice = Singleton.Instance.EFEM.GetDummyDevice(_targetDummy - ModuleName.Dummy1); if(dummyDevice != null) { if (!dummyDevice.HasCassette) { Stop($"{_targetDummy} dose not have cassette"); return false; } WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetDummy); if(waferInfos.Length > 0) { _dummySlotNumber = waferInfos.Length; foreach (var item in waferInfos) { if (item != null && !item.IsEmpty) { Stop($"There are wafers inside the {_targetDummy},cannot do the RobotCycle action"); return false; } } } } return true; } private Loadport GetLoadPort(ModuleName station) { LoadPortModule loadPortModule = Singleton.Instance.EFEM.GetLoadportModule(station - ModuleName.LP1); return loadPortModule.LPDevice; } private bool CheckRoutineStopStatus(IRoutine routine, string error) { bool result = CommonFunction.CheckRoutineStopState(routine); if (result) { Stop( $"{error}"); } return result; } //更新取放dummy的位置 private bool UpdateMoveItem() { if (_lpWaferIndex.Count > 0) { _lpToAlignerMoveItem.Peek().SourceSlot = _lpWaferIndex.Dequeue(); //更新从LP取片的位置 if (_targetDummy != ModuleName.Unknown) { _alignerToDummyMoveItem.Peek().DestinationSlot = (_alignerToDummyMoveItem.Peek().DestinationSlot + 1) % _dummySlotNumber; //更新放到Dummy的位置 _dummyToLpMoveItem.Peek().SourceSlot = (_dummyToLpMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber; //更新从dummy取片的位置,送回LP _dummyToSrdMoveItem.Peek().SourceSlot = (_dummyToSrdMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber;//更新从dummy取片的位置,送到Srd } _dummyToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从dummy放回LP的位置。 _srdToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从srd放回LP的位置。 } return true; } //清除MoveItem private bool ClearMoveItem() { _lpToAlignerMoveItem.Clear(); _alignerToDummyMoveItem.Clear(); _alignerToSrdMoveItem.Clear(); _dummyToLpMoveItem.Clear(); _dummyToSrdMoveItem.Clear(); _srdToLpMoveItem.Clear(); return true; } #endregion } }