RobotCycleRoutine.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using Aitex.Sorter.Common;
  7. using CyberX8_Core;
  8. using CyberX8_RT.Devices.EFEM;
  9. using CyberX8_RT.Modules.LPs;
  10. using MECF.Framework.Common.Beckhoff.Station;
  11. using MECF.Framework.Common.Equipment;
  12. using MECF.Framework.Common.Schedulers;
  13. using MECF.Framework.Common.SubstrateTrackings;
  14. using MECF.Framework.Common.Utilities;
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Threading.Tasks;
  20. namespace CyberX8_RT.Modules.EFEM
  21. {
  22. public class RobotCycleRoutine : ModuleRoutineBase, IRoutine
  23. {
  24. private enum RobotCycleStep
  25. {
  26. LPCycleStrat,
  27. PickFromLP,
  28. PickFromLPCheck,
  29. PlaceToAligner,
  30. PlaceToAlignerCheck,
  31. PickFromAligner,
  32. PickFromAlignerCheck,
  33. PlaceToDummy,
  34. PlaceToDummyCheck,
  35. PickFromDummy,
  36. PickFromDummyCheck,
  37. PlaceToSrd,
  38. PlaceToSrdCheck,
  39. PickFromSrd,
  40. PickFromSrdCheck,
  41. PlaceToLP,
  42. PlaceToLPCheck,
  43. LPCycleEnd,
  44. End
  45. }
  46. EfemBase _efem;
  47. /// <summary>
  48. /// 当前Cycle选中的LP里面的Wafer数量
  49. /// </summary>
  50. private int _waferCount;
  51. private EfemPickRoutine _efemPickRoutine;
  52. private EfemPlaceRoutine _efemPlaceRoutine;
  53. private ModuleName _targetLP;
  54. private ModuleName _targetAligner;
  55. private ModuleName _targetDummy;
  56. private ModuleName _targetSrd;
  57. private Queue<MoveItem> _lpToAlignerMoveItem = new Queue<MoveItem>();
  58. private Queue<MoveItem> _alignerToDummyMoveItem = new Queue<MoveItem>();
  59. private Queue<MoveItem> _alignerToSrdMoveItem = new Queue<MoveItem>();
  60. private Queue<MoveItem> _dummyToLpMoveItem = new Queue<MoveItem>();
  61. private Queue<MoveItem> _dummyToSrdMoveItem = new Queue<MoveItem>();
  62. private Queue<MoveItem> _srdToLpMoveItem = new Queue<MoveItem>();
  63. private Queue<int> _lpWaferIndex = new Queue<int>(); //记录有LP有Wafer的slot号
  64. private int _moveTimeout = 20 * 1000;
  65. private int _dummySlotNumber = 0;
  66. public RobotCycleRoutine(EfemBase efem) : base(ModuleName.EfemRobot)
  67. {
  68. _efem = efem;
  69. _efemPickRoutine = new EfemPickRoutine(efem);
  70. _efemPlaceRoutine = new EfemPlaceRoutine(efem);
  71. }
  72. public RState Start(params object[] objs)
  73. {
  74. _lpWaferIndex.Clear();//初始化LP 有wafer的slot号
  75. _waferCount = 0; //初始化wafercount的数量
  76. if (objs.Length >= 5)
  77. {
  78. _targetLP = (ModuleName)objs[0];
  79. _targetAligner = (ModuleName)objs[1];
  80. _targetDummy = (ModuleName)objs[2];
  81. _targetSrd = (ModuleName)objs[3];
  82. }
  83. else
  84. {
  85. return RState.Failed;
  86. }
  87. if (!CheckPreCondition()) //检验前提条件
  88. {
  89. return RState.Failed;
  90. }
  91. _moveTimeout = SC.GetValue<int>($"EFEM.MotionTimeout") * 1000;
  92. MoveItem lpToAlignerMoveItem = new MoveItem //LP To Aligner
  93. {
  94. SourceModule = _targetLP,
  95. SourceSlot = _lpWaferIndex.Dequeue(),
  96. DestinationModule = ModuleName.Aligner1,
  97. DestinationSlot = 0,
  98. RobotHand = 0 //表示blade1
  99. };
  100. _lpToAlignerMoveItem.Enqueue(lpToAlignerMoveItem);
  101. MoveItem alignerToDummyMoveItem = new MoveItem //Aligner To Dummy
  102. {
  103. SourceModule = ModuleName.Aligner1,
  104. SourceSlot = 0,
  105. DestinationModule = _targetDummy,
  106. DestinationSlot = 0,
  107. RobotHand = 0
  108. };
  109. _alignerToDummyMoveItem.Enqueue(alignerToDummyMoveItem);
  110. MoveItem alignerToSrdMoveItem = new MoveItem //Aligner To Srd
  111. {
  112. SourceModule = ModuleName.Aligner1,
  113. SourceSlot = 0,
  114. DestinationModule = _targetSrd,
  115. DestinationSlot = 0,
  116. RobotHand = 0
  117. };
  118. _alignerToSrdMoveItem.Enqueue(alignerToSrdMoveItem);
  119. MoveItem dummyToLpMoveItem = new MoveItem //Dummy To LP
  120. {
  121. SourceModule = _targetDummy,
  122. SourceSlot = 0,
  123. DestinationModule = _targetLP,
  124. DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置
  125. RobotHand = 0
  126. };
  127. _dummyToLpMoveItem.Enqueue(dummyToLpMoveItem);
  128. MoveItem dummyToSrdMoveItem = new MoveItem //Dummy To Srd
  129. {
  130. SourceModule = _targetDummy,
  131. SourceSlot = 0,
  132. DestinationModule = _targetSrd,
  133. DestinationSlot = 0,
  134. RobotHand = 0
  135. };
  136. _dummyToSrdMoveItem.Enqueue(dummyToSrdMoveItem);
  137. MoveItem srdToLpMoveItem = new MoveItem //SRD To LP
  138. {
  139. DestinationModule = _targetLP,
  140. DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置
  141. RobotHand = 0
  142. };
  143. _srdToLpMoveItem.Enqueue(srdToLpMoveItem);
  144. return Runner.Start(Module, "Robot Cycle start");
  145. }
  146. public RState Monitor()
  147. {
  148. Runner.LoopStart(RobotCycleStep.LPCycleStrat, "LP Cycle Start", _waferCount, NullFun, _delay_1ms)
  149. .LoopRun(RobotCycleStep.PickFromLP, () => { return _efemPickRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms)
  150. .LoopRunWithStopStatus(RobotCycleStep.PickFromLPCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
  151. () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from LP failed"))
  152. .LoopRun(RobotCycleStep.PlaceToAligner, () => { return _efemPlaceRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms)
  153. .LoopRunWithStopStatus(RobotCycleStep.PlaceToAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  154. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to aligner failed"))
  155. .LoopRun(RobotCycleStep.PickFromAligner, () => { return _efemPickRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms)
  156. .LoopRunWithStopStatus(RobotCycleStep.PickFromAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
  157. () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from aligner failed"))
  158. //从Aligner到dummy
  159. .LoopRunIf(RobotCycleStep.PlaceToDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms)
  160. .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  161. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to dummy failed"))
  162. .LoopRunIf(RobotCycleStep.PickFromDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms)
  163. .LoopRunIfWithStopStatus(RobotCycleStep.PickFromDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
  164. () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from dummy failed"))
  165. //从Aligner到SRD的
  166. .LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy==ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms)
  167. .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  168. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed"))
  169. .LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return _efemPickRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms)
  170. .LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
  171. () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed"))
  172. //从dummy到SRD的
  173. .LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms)
  174. .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  175. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed"))
  176. .LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms)
  177. .LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
  178. () => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed"))
  179. //从Dummy回LP
  180. .LoopRunIf(RobotCycleStep.PlaceToLP, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms)
  181. .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  182. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed"))
  183. //从SRD回LP
  184. .LoopRunIf(RobotCycleStep.PlaceToLP, _targetSrd != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_srdToLpMoveItem) == RState.Running; }, _delay_1ms)
  185. .LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetSrd != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
  186. () => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed"))
  187. .LoopEnd(RobotCycleStep.LPCycleEnd, UpdateMoveItem, _delay_1ms)
  188. .End(RobotCycleStep.End, ClearMoveItem, _delay_1ms);
  189. return Runner.Status;
  190. }
  191. public void Abort()
  192. {
  193. _efem.Halt();
  194. }
  195. #region 功能方法
  196. private bool CheckPreCondition()
  197. {
  198. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0))
  199. {
  200. Stop($"Efem robot arm already has a wafer, cannot do the RobotCycle action");
  201. return false;
  202. }
  203. //LoadPort状态判断
  204. if (ModuleHelper.IsLoadPort(_targetLP) && ModuleHelper.IsInstalled(_targetLP))
  205. {
  206. Loadport loadPort = GetLoadPort(_targetLP);
  207. if (loadPort == null)
  208. {
  209. Stop($"{_targetLP} is null");
  210. return false;
  211. }
  212. if (!loadPort.IsLoaded)
  213. {
  214. Stop($"{_targetLP} is not load");
  215. return false;
  216. }
  217. WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetLP);
  218. for (int i = 0; i < waferInfos.Length; i++)
  219. {
  220. if (waferInfos[i] != null && !waferInfos[i].IsEmpty)
  221. {
  222. _waferCount++;
  223. _lpWaferIndex.Enqueue(i);
  224. }
  225. }
  226. if (_waferCount < 1)
  227. {
  228. Stop($"there is no wafer in {_targetLP}");
  229. return false;
  230. }
  231. }
  232. //Aligner状态判断
  233. //if (!ModuleHelper.IsInstalled(_targetAligner))
  234. //{
  235. // Stop($"{_targetAligner} is not installed");
  236. // return false;
  237. //}
  238. //Dummy状态判断
  239. if (!ModuleHelper.IsInstalled(_targetDummy))
  240. {
  241. Stop($"{_targetDummy} is not installed");
  242. return false;
  243. }
  244. //若dummy存在wafer,需要人工处理
  245. DummyDevice dummyDevice = Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(_targetDummy - ModuleName.Dummy1);
  246. if(dummyDevice != null)
  247. {
  248. if (!dummyDevice.HasCassette)
  249. {
  250. Stop($"{_targetDummy} dose not have cassette");
  251. }
  252. WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetDummy);
  253. if(waferInfos.Length > 0)
  254. {
  255. _dummySlotNumber = waferInfos.Length;
  256. foreach (var item in waferInfos)
  257. {
  258. if (item != null && !item.IsEmpty)
  259. {
  260. Stop($"There are wafers inside the {_targetDummy},cannot do the RobotCycle action");
  261. return false;
  262. }
  263. }
  264. }
  265. }
  266. return true;
  267. }
  268. private Loadport GetLoadPort(ModuleName station)
  269. {
  270. LoadPortModule loadPortModule = Singleton<RouteManager>.Instance.EFEM.GetLoadportModule(station - ModuleName.LP1);
  271. return loadPortModule.LPDevice;
  272. }
  273. private bool CheckRoutineStopStatus(IRoutine routine, string error)
  274. {
  275. bool result = CommonFunction.CheckRoutineStopState(routine);
  276. if (result)
  277. {
  278. Stop( $"{error}");
  279. }
  280. return result;
  281. }
  282. //更新取放dummy的位置
  283. private bool UpdateMoveItem()
  284. {
  285. if (_lpWaferIndex.Count > 0)
  286. {
  287. _lpToAlignerMoveItem.Peek().SourceSlot = _lpWaferIndex.Dequeue(); //更新从LP取片的位置
  288. if (_targetDummy != ModuleName.Unknown)
  289. {
  290. _alignerToDummyMoveItem.Peek().DestinationSlot = (_alignerToDummyMoveItem.Peek().DestinationSlot + 1) % _dummySlotNumber; //更新放到Dummy的位置
  291. _dummyToLpMoveItem.Peek().SourceSlot = (_dummyToLpMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber; //更新从dummy取片的位置,送回LP
  292. _dummyToSrdMoveItem.Peek().SourceSlot = (_dummyToSrdMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber;//更新从dummy取片的位置,送到Srd
  293. }
  294. _dummyToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从dummy放回LP的位置。
  295. _srdToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从srd放回LP的位置。
  296. }
  297. return true;
  298. }
  299. //清除MoveItem
  300. private bool ClearMoveItem()
  301. {
  302. _lpToAlignerMoveItem.Clear();
  303. _alignerToDummyMoveItem.Clear();
  304. _alignerToSrdMoveItem.Clear();
  305. _dummyToLpMoveItem.Clear();
  306. _dummyToSrdMoveItem.Clear();
  307. _srdToLpMoveItem.Clear();
  308. return true;
  309. }
  310. #endregion
  311. }
  312. }