EfemPickRoutine.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. using Aitex.Core.RT.Routine;
  2. using Aitex.Core.RT.SCCore;
  3. using Aitex.Sorter.Common;
  4. using PunkHPX8_RT.Devices;
  5. using MECF.Framework.Common.Routine;
  6. using MECF.Framework.Common.Equipment;
  7. using MECF.Framework.Common.SubstrateTrackings;
  8. using PunkHPX8_Core;
  9. using Aitex.Core.RT.Log;
  10. using Aitex.Core.Util;
  11. using MECF.Framework.Common.Schedulers;
  12. using System.Collections.Generic;
  13. using PunkHPX8_RT.Devices.EFEM;
  14. using PunkHPX8_RT.Modules.LPs;
  15. using PunkHPX8_RT.Modules.SRD;
  16. using System.Runtime.InteropServices;
  17. using Aitex.Core.RT.Device;
  18. using PunkHPX8_RT.Devices.AXIS;
  19. using MECF.Framework.Common.Utilities;
  20. using PunkHPX8_RT.Modules.Transporter;
  21. using System;
  22. using Aitex.Core.UI.ControlDataContext;
  23. using Aitex.Core.Common;
  24. using PunkHPX8_RT.Devices.PlatingCell;
  25. using PunkHPX8_RT.Modules.PlatingCell;
  26. namespace PunkHPX8_RT.Modules.EFEM
  27. {
  28. class EfemPickRoutine : RoutineBase, IRoutine
  29. {
  30. private enum PickStep
  31. {
  32. WaitModuleReady,
  33. PufVacuumOff,
  34. Picking1,
  35. Picking2,
  36. End,
  37. }
  38. private int _moveTimeout = 20 * 1000;
  39. private ModuleName _targetModule = ModuleName.System;
  40. int _targetSlot;
  41. int _targetSlot2;
  42. string _targetPufSlot;
  43. Hand _hand;
  44. Hand _hand2;
  45. Flip _flip;
  46. EfemBase _efem;
  47. bool _bDoublePick = false;
  48. private SRDEntity _srdModule;
  49. private Queue<MoveItem> _moveQueue;
  50. public EfemPickRoutine(EfemBase efem) : base(ModuleName.EfemRobot.ToString())
  51. {
  52. _efem = efem;
  53. }
  54. public RState Start(params object[] objs)
  55. {
  56. _bDoublePick = false;
  57. _moveQueue = (Queue<MoveItem>)objs[0];
  58. MoveItem moveItem = _moveQueue.Peek();
  59. _targetModule = moveItem.SourceModule;
  60. _targetSlot = moveItem.SourceSlot;
  61. _hand = moveItem.RobotHand;
  62. _flip = moveItem.PickRobotFlip;
  63. if(_moveQueue.Count >= 2)
  64. {
  65. _bDoublePick = true;
  66. }
  67. if (!CheckPreCondition())
  68. {
  69. return RState.Failed;
  70. }
  71. _moveTimeout = SC.GetValue<int>($"EFEM.MotionTimeout") * 1000;
  72. return Runner.Start(Module, $"Pick from {_targetModule}");
  73. }
  74. private Loadport GetLoadPort(ModuleName station)
  75. {
  76. LoadPortModule loadPortModule = Singleton<RouteManager>.Instance.EFEM.GetLoadportModule(station - ModuleName.LP1);
  77. return loadPortModule.LPDevice;
  78. }
  79. private bool CheckPreCondition()
  80. {
  81. //LoadPort状态判断
  82. if (ModuleHelper.IsLoadPort(_targetModule) && ModuleHelper.IsInstalled(_targetModule))
  83. {
  84. Loadport loadPort=GetLoadPort(_targetModule);
  85. if (loadPort == null)
  86. {
  87. return false;
  88. }
  89. if (!loadPort.IsLoaded)
  90. {
  91. NotifyError(eEvent.ERR_EFEM_ROBOT, $"LoadPort not load, cannot do the pick action",-1);
  92. return false;
  93. }
  94. }
  95. if (ModuleHelper.IsDummy(_targetModule)||ModuleHelper.IsAligner(_targetModule)|| ModuleHelper.IsLoadPort(_targetModule))
  96. {
  97. if (_hand == Hand.Blade2)
  98. {
  99. NotifyError(eEvent.ERR_EFEM_ROBOT, $"cannot use upper arm to pick from {_targetModule}", -1);
  100. return false;
  101. }
  102. }
  103. if (ModuleHelper.IsPlatingCell(_targetModule))
  104. {
  105. if (_hand == Hand.Blade1)
  106. {
  107. NotifyError(eEvent.ERR_EFEM_ROBOT, $"cannot use lower arm to pick from {_targetModule}", -1);
  108. return false;
  109. }
  110. PlatingCellDevice platingCellDevice = DEVICE.GetDevice<PlatingCellDevice>(_targetModule.ToString());
  111. if (platingCellDevice == null)
  112. {
  113. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} entity is null, can not pick", -1);
  114. return false;
  115. }
  116. if (platingCellDevice != null&&platingCellDevice.PlatingCellDeviceData.ClamShellClosed)
  117. {
  118. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} clamshell closed, can not pick", -1);
  119. return false;
  120. }
  121. string vertical = ModuleMatcherManager.Instance.GetPlatingVerticalByCell(_targetModule.ToString());
  122. PlatingCellVerticalEntity verticalEntity = Singleton<RouteManager>.Instance.GetModule<PlatingCellVerticalEntity>(vertical);
  123. if (verticalEntity == null)
  124. {
  125. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} vertical entity is null, can not pick", -1);
  126. return false;
  127. }
  128. if (verticalEntity != null&&!verticalEntity.IsInLoad)
  129. {
  130. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} vertical is not in load, can not pick", -1);
  131. return false;
  132. }
  133. }
  134. if (_hand == Hand.Blade1 && _flip == Flip.Down)
  135. {
  136. NotifyError(eEvent.ERR_EFEM_ROBOT, $"lower arm cannot flip", -1);
  137. return false;
  138. }
  139. if (ModuleHelper.IsSRD(_targetModule) && ModuleHelper.IsInstalled(_targetModule))
  140. {
  141. _srdModule = Singleton<RouteManager>.Instance.GetModule<SRDEntity>(_targetModule.ToString());
  142. if (!_srdModule.IsHomed)
  143. {
  144. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} is not homed, please home it first",-1);
  145. return false;
  146. }
  147. //判断arm是否在home位置上
  148. //JetAxisBase jetAxisBase = DEVICE.GetDevice<JetAxisBase>($"{_targetModule}.Arm");
  149. //double position = jetAxisBase.MotionData.MotorPosition;
  150. //bool result = jetAxisBase.CheckPositionIsInStation(position, "Home");
  151. //if (!result)
  152. //{
  153. // NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} armaxis {position} is not in homed place",-1);
  154. // return false;
  155. //}
  156. if (_srdModule.IsSrdDoorClosed)
  157. {
  158. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} door closed, can not pick",-1);
  159. return false;
  160. }
  161. if (_srdModule.IsSrdChuckVacuum)
  162. {
  163. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} Vacuum on, can not pick",-1);
  164. return false;
  165. }
  166. if (_hand == Hand.Blade2)
  167. {
  168. NotifyError(eEvent.ERR_EFEM_ROBOT, $"cannot use upper hand to pick from loadport", -1);
  169. return false;
  170. }
  171. }
  172. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand))
  173. {
  174. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Efem robot arm{_hand} already has a wafer, cannot do the pick action",-1);
  175. return false;
  176. }
  177. if (WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot))
  178. {
  179. NotifyError(eEvent.ERR_EFEM_ROBOT, $"The target slot: {_targetModule}.{_targetSlot + 1} has no wafer, cannot do the pick action",-1);
  180. return false;
  181. }
  182. else
  183. {
  184. WaferInfo waferInfo = WaferManager.Instance.GetWafer(_targetModule, _targetSlot);
  185. if(waferInfo.Status!=WaferStatus.Normal)
  186. {
  187. NotifyError(eEvent.ERR_EFEM_ROBOT, $"The target slot: {_targetModule}.{_targetSlot + 1} wafer status is {waferInfo.Status}, cannot do the pick action", -1);
  188. return false;
  189. }
  190. }
  191. if (_moveQueue.Count >= 2)
  192. {
  193. if (!ModuleHelper.IsLoadPort(_targetModule))
  194. {
  195. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Wrong double pick command, target is not loadport",-1);
  196. return false;
  197. }
  198. _hand2 = _hand != Hand.Blade1 ? Hand.Blade1 : Hand.Blade2;
  199. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand2))
  200. {
  201. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Efem robot arm{_hand2} already has a wafer, cannot do the double pick action",-1);
  202. return false;
  203. }
  204. _targetSlot2 = _moveQueue.ToArray()[1].SourceSlot;
  205. if (WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot2))
  206. {
  207. NotifyError(eEvent.ERR_EFEM_ROBOT, $"The target slot: {_targetModule}.{_targetSlot2 + 1} has no wafer, cannot do the double pick action",-1);
  208. return false;
  209. }
  210. }
  211. return true;
  212. }
  213. public RState Monitor()
  214. {
  215. if(_bDoublePick)
  216. {
  217. Runner.Wait(PickStep.WaitModuleReady, WaitModuleReady)
  218. .Run(PickStep.Picking1, Pick1, Pick1Done, _moveTimeout)
  219. .Run(PickStep.Picking2, Pick2, Pick2Done, _moveTimeout)
  220. .End(PickStep.End, ActionDone);
  221. }
  222. else
  223. {
  224. Runner.Wait(PickStep.WaitModuleReady, WaitModuleReady)
  225. .Run(PickStep.Picking1, Pick1, Pick1Done, _moveTimeout)
  226. .End(PickStep.End, ActionDone);
  227. }
  228. return Runner.Status;
  229. }
  230. public void Abort()
  231. {
  232. _efem.Halt();
  233. }
  234. private bool WaitModuleReady()
  235. {
  236. if (_efem.IsInPauseStatus)
  237. {
  238. return false;
  239. }
  240. return _efem.Status == RState.End;
  241. }
  242. private bool Pick1()
  243. {
  244. return _efem.Pick(_targetModule, _targetSlot, _hand,_flip);
  245. }
  246. private bool Pick1Done()
  247. {
  248. if (_efem.Status == RState.End)
  249. {
  250. WaferManager.Instance.WaferMoved(_targetModule, _targetSlot, ModuleName.EfemRobot, (int)_hand);
  251. return true;
  252. }
  253. else if (_efem.Status == RState.Failed)
  254. {
  255. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Efem robot picking failed: {_efem.Status}",-1);
  256. return true;
  257. }
  258. return false;
  259. }
  260. private bool Pick2()
  261. {
  262. return _efem.Pick(_targetModule, _targetSlot2, _hand2, _flip);
  263. }
  264. private bool Pick2Done()
  265. {
  266. if (_efem.Status == RState.End)
  267. {
  268. WaferManager.Instance.WaferMoved(_targetModule, _targetSlot2, ModuleName.EfemRobot, (int)_hand2);
  269. return true;
  270. }
  271. else if (_efem.Status == RState.Failed)
  272. {
  273. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Efem robot picking failed: {_efem.Status}",-1);
  274. return true;
  275. }
  276. return false;
  277. }
  278. private bool ActionDone()
  279. {
  280. return true;
  281. }
  282. /// <summary>
  283. /// 重试
  284. /// </summary>
  285. /// <param name="step"></param>
  286. public RState Retry(int step)
  287. {
  288. if(!CheckPreCondition())
  289. {
  290. return RState.Failed;
  291. }
  292. _efem.Reset();
  293. List<Enum> preStepIds = new List<Enum>();
  294. AddPreSteps(PickStep.PufVacuumOff, preStepIds);
  295. return Runner.Retry(PickStep.PufVacuumOff, preStepIds, Module, "Pick Retry");
  296. }
  297. /// <summary>
  298. /// 忽略前
  299. /// </summary>
  300. /// <param name="step"></param>
  301. /// <param name="preStepIds"></param>
  302. private void AddPreSteps(PickStep step, List<Enum> preStepIds)
  303. {
  304. for (int i = 0; i < (int)step; i++)
  305. {
  306. preStepIds.Add((PickStep)i);
  307. }
  308. }
  309. /// <summary>
  310. /// 检验前面完成状态
  311. /// </summary>
  312. /// <returns></returns>
  313. public bool CheckCompleteCondition(int index)
  314. {
  315. if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)_hand))
  316. {
  317. NotifyError(eEvent.ERR_EFEM_ROBOT, $"Efem robot arm{_hand} has no wafer", -1);
  318. return false;
  319. }
  320. if (WaferManager.Instance.CheckHasWafer(_targetModule, _targetSlot))
  321. {
  322. NotifyError(eEvent.ERR_EFEM_ROBOT, $"{_targetModule} Slot{_targetSlot} has no wafer", -1);
  323. return false;
  324. }
  325. return true;
  326. }
  327. }
  328. }