RobotCycleRoutine.cs 17 KB

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