| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 | 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;        /// <summary>        /// 当前Cycle选中的LP里面的Wafer数量        /// </summary>        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<MoveItem> _lpToAlignerMoveItem = new Queue<MoveItem>();        private Queue<MoveItem> _alignerToDummyMoveItem = new Queue<MoveItem>();        private Queue<MoveItem> _alignerToSrdMoveItem = new Queue<MoveItem>();        private Queue<MoveItem> _dummyToLpMoveItem = new Queue<MoveItem>();        private Queue<MoveItem> _dummyToSrdMoveItem = new Queue<MoveItem>();        private Queue<MoveItem> _srdToLpMoveItem = new Queue<MoveItem>();                private Queue<int> _lpWaferIndex = new Queue<int>(); //记录有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的数量            int platType = SC.GetValue<int>("EFEM.Aligner1.AlignerPlatType");            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];                alignerParamater[3] = platType;            }            else            {                return RState.Failed;            }            if (!CheckPreCondition()) //检验前提条件            {                return RState.Failed;            }            _moveTimeout = SC.GetValue<int>($"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<RouteManager>.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<RouteManager>.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    }}
 |