PlaceRoutine.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Device.Unit;
  4. using Aitex.Core.RT.Event;
  5. using Aitex.Core.RT.Routine;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.Util;
  8. using Aitex.Sorter.Common;
  9. using EFEM.RT.Devices;
  10. using MECF.Framework.Common.Equipment;
  11. using MECF.Framework.Common.SubstrateTrackings;
  12. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
  13. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase;
  14. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
  15. using System;
  16. namespace EFEM.RT.Routines
  17. {
  18. public class PlaceRoutine : CommonRoutine, IRoutine, IEfemPlaceRoutine
  19. {
  20. private enum Place
  21. {
  22. QueryState,
  23. OpenLoadLockDoor,
  24. CoolBufferMoveUP,
  25. WaitCoolBufferMoveUP,
  26. CheckBeforePlace,
  27. QueryRobotParameter,
  28. RobotServoOff,
  29. WaitRobotServoOff,
  30. SetWaferSizeParameter0000,
  31. SetWaferSizeParameter0114,
  32. RobotServoOn,
  33. WaitRobotServoOn,
  34. PlaceWafer,
  35. WaitPlace,
  36. CloseLoadLockDoor,
  37. CoolBufferMoveDown,
  38. WaitCoolBufferMoveDown,
  39. CheckAfterPlace,
  40. XMove,
  41. PostMessage,
  42. RobotBusytoSimifOn,
  43. RobotBusytoSimifOff,
  44. PinDown,
  45. CheckWaferPrecense,
  46. WaitCheckWaferPrecense,
  47. CheckWaferPrecenseAfterPlace,
  48. QuerySignalStatus,
  49. RobotBladeGrip,
  50. NotifyFlipperPrepare,
  51. NotifyFlipperOver
  52. }
  53. protected bool MultiWaferSize = DeviceDefineManager.Instance.GetValue<bool>("MultiWaferSize") ?? false;
  54. protected bool EnableMoveInDiffSlotsNumLP
  55. {
  56. get
  57. {
  58. if (SC.ContainsItem("System.IsEnableMoveInDiffSlotsNumLP"))
  59. return SC.GetValue<bool>("System.IsEnableMoveInDiffSlotsNumLP");
  60. return false;
  61. }
  62. }
  63. private SCConfigItem _scPlaceTimeout = null;
  64. private int _timeout = 0;
  65. private int _axisTimeout = 0;
  66. private int _axisSpeed = 0;
  67. private int _alignerdelay = 0;
  68. private int _coolingdelay = 0;
  69. private int delaytime = 0;
  70. public PlaceRoutine(string module, string name)
  71. {
  72. Module = module; Name = name;
  73. _alignerdelay = SC.GetValue<int>("System.AlignerPinDownDelay");
  74. _coolingdelay = SC.GetValue<int>("System.CoolingPinDownDelay");
  75. _scPlaceTimeout = SC.GetConfigItem(SorterCommon.ScPathName.Robot_TimeLimitForPlaceWafer);
  76. if (HaveMotionAxis)
  77. {
  78. _axisTimeout = SC.GetValue<int>("MotionAxis.MoveTimeout");
  79. _axisSpeed = SC.GetValue<int>("MotionAxis.AutoSpeed");
  80. }
  81. }
  82. public bool Initalize()
  83. {
  84. IsStopped = true;
  85. return true;
  86. }
  87. public ModuleName Station { get; set; }
  88. public int Slot { get; set; }
  89. public Hand Blade { get; set; }
  90. public LoadPort _lpDevice;
  91. private bool _skipWait;
  92. public Result Start(params object[] objs)
  93. {
  94. IsStopped = false;
  95. Name = "Place";
  96. Reset();
  97. _timeout = robot.RobotCommandTimeout;
  98. if (ModuleHelper.IsCoolingBuffer(Station))
  99. delaytime = _coolingdelay * 1000;
  100. else delaytime = _alignerdelay * 1000;
  101. EV.PostMessage(ModuleName.System.ToString(), EventEnum.PuttingWaferToChamberBegins, string.Format("{0}{1:D2} by {2}", Station.ToString(), Slot + 1, Blade.ToString()));
  102. return Result.RUN;
  103. }
  104. public Result Monitor()
  105. {
  106. try
  107. {
  108. if (IsStopped) return Result.DONE;
  109. if (ModuleHelper.IsCoolingBuffer(Station) || ModuleHelper.IsAligner(Station))
  110. {
  111. var dev = GetCoolBuffer(Station);
  112. if (dev != null)
  113. {
  114. //QueryCoolBufferState((int)Place.QueryState, GetCoolBuffer(Station));
  115. CoolBufferMoveUP((int)Place.CoolBufferMoveUP, GetCoolBuffer(Station), WaferManager.Instance.GetWaferSize(ModuleName.Robot, 0), _timeout, Notify, Stop);
  116. WaitCoolBufferMoveUp((int)Place.WaitCoolBufferMoveUP, GetCoolBuffer(Station), "Wait CoolingBuffer Move Up...", _timeout, Notify, Stop);
  117. }
  118. }
  119. else if (ModuleHelper.IsFlipper(Station))
  120. {
  121. FlipperPrepare((int)Place.NotifyFlipperPrepare, GetFlipper(), "Flipper Prepare Transfer...", _timeout, Notify, Stop);
  122. }
  123. CheckBladeWaferIsExist((int)Place.CheckWaferPrecense, robot, Blade, _timeout);
  124. // RobotSignalStatus((int)Place.QuerySignalStatus, robot, _timeout);
  125. WaitRobotMotion((int)Place.WaitCheckWaferPrecense, robot, "Wait finish check wafer", _timeout, Notify, Stop);
  126. CheckBeforePlace((int)Place.CheckBeforePlace, "Check wafer before place", Station, Slot, Blade, Notify, Stop);
  127. //GripRobotBlade((int)Place.RobotBladeGrip, Blade, robot, _timeout);
  128. if (!ModuleHelper.IsLoadLock(Station))
  129. {
  130. PlaceWafer((int)Place.PlaceWafer, "Place wafer", Station, Slot, Blade, OffsetX, OffsetY, OffsetZ, Notify, Stop);
  131. this.WaitRobotMotion((int)Place.WaitPlace, robot, "Wait wafer placed", _timeout, Notify, Stop);
  132. }
  133. if (LoadLockDoorControlByStation && ModuleHelper.IsLoadLock(Station) && !Singleton<EfemEntity>.Instance.IsOnlineMode)
  134. {
  135. LoadLockCloseAtmDoor((int)Place.CloseLoadLockDoor, DEVICE.GetDevice<LoadLockDevice>(Station.ToString()), "Wait Atm Door Close", _timeout, Notify, Stop);
  136. }
  137. //为了提高上位机调度效率,机械手放片在上面就认为place指令完成。pin落下的时间和指令从上位机发送
  138. //为了保持兼容性,暂时判断了是否上位机控制,需要等cycle功能做好,这里都统一成外部控制lift pin
  139. if (!Singleton<EfemEntity>.Instance.IsOnlineMode)
  140. {
  141. if (ModuleHelper.IsCoolingBuffer(Station) || ModuleHelper.IsAligner(Station))
  142. {
  143. var dev = GetCoolBuffer(Station);
  144. if (dev != null)
  145. {
  146. TimeDelay((int)Place.PinDown, delaytime);
  147. CoolBufferMoveDown((int)Place.CoolBufferMoveDown, GetCoolBuffer(Station), WaferManager.Instance.GetWaferSize(Station, Slot), _timeout, Notify, Stop);
  148. WaitCoolBufferMoveDown((int)Place.WaitCoolBufferMoveDown, GetCoolBuffer(Station), "Wait CoolingBuffer Move Down...", _timeout, Notify, Stop);
  149. }
  150. }
  151. }
  152. if (ModuleHelper.IsFlipper(Station))
  153. {
  154. FlipperComplete((int)Place.NotifyFlipperOver, GetFlipper(), "Flipper Complete Transfer...", _timeout, Notify, Stop);
  155. }
  156. PostMessage((int)Place.PostMessage, string.Format("{0}{1:D2} by {2}", Station.ToString(), Slot + 1, Blade.ToString()));
  157. //CheckBladeWaferIsExist((int)Place.CheckWaferPrecenseAfterPlace, robot, Blade, _timeout);
  158. CheckAfterPlace((int)Place.CheckAfterPlace, "Check wafer information after wafer placed", Station, Slot, Blade, Notify, Stop);
  159. }
  160. catch (RoutineBreakException)
  161. {
  162. if (!IsActived(TokenId) && !_skipWait)
  163. {
  164. _skipWait = true;
  165. return Monitor();
  166. }
  167. return Result.RUN;
  168. }
  169. catch (RoutineFaildException)
  170. {
  171. IsStopped = true;
  172. return Result.FAIL;
  173. }
  174. IsStopped = true;
  175. return Result.DONE;
  176. }
  177. protected override void Notify(string message)
  178. {
  179. EV.PostMessage(Module, EventEnum.GeneralInfo, String.Format("Place sequence:{0}", message));
  180. }
  181. /// <summary>
  182. /// prepare process failed
  183. /// </summary>
  184. /// <param name="failReason"></param>
  185. /// <param name="reactor"></param>
  186. protected override void Stop(string failReason)
  187. {
  188. string reason = String.Empty;
  189. EV.PostMessage(ModuleName.System.ToString(), EventEnum.PlaceWaferFailed, Station.ToString(), Slot + 1, Blade.ToString(), failReason);
  190. }
  191. public void PlaceWafer(int id, string name, ModuleName chamber, int slot, Hand blade, Action<string> notify, Action<string> error)
  192. {
  193. Tuple<bool, Result> ret = Execute(id, () =>
  194. {
  195. notify(String.Format("Place wafer to {0}", chamber.ToString()));
  196. string reason = string.Empty;
  197. return robot.Place((RobotArmEnum)(int)blade, chamber.ToString(), slot);
  198. });
  199. if (ret.Item1)
  200. {
  201. if (ret.Item2 == Result.FAIL)
  202. {
  203. throw (new RoutineFaildException());
  204. }
  205. }
  206. }
  207. public void CheckBeforePlace(int id, string name, ModuleName chamber, int slot, Hand blade, Action<string> notify, Action<string> error)
  208. {
  209. Tuple<bool, Result> ret = Execute(id, () =>
  210. {
  211. notify(String.Format("Check {0}{1:D2} wafer information before place wafer", chamber.ToString(), slot));
  212. string reason = string.Empty;
  213. if (!CheckRobotMotionInterlock(chamber, slot, out reason))
  214. {
  215. EV.PostMessage(ModuleName.System.ToString(), EventEnum.TransferPrepareFailed, String.Format("Target {0}{1:D2},{2}", chamber.ToString(), slot + 1, reason));
  216. return false;
  217. }
  218. if (blade == Hand.Blade1)
  219. {
  220. bool bNoWafer = WaferManager.Instance.CheckWafer(chamber, slot, WaferStatus.Empty);
  221. if (!bNoWafer)
  222. {
  223. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferPresentWithRecord, String.Format("Target {0}{1:D2}", chamber.ToString(), slot + 1));
  224. return false;
  225. }
  226. bool bHasWafer = WaferManager.Instance.CheckWafer(ModuleName.Robot, (int)blade, WaferStatus.Normal);
  227. if (!bHasWafer)
  228. {
  229. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  230. return false;
  231. }
  232. bHasWafer = CheckSeneorHasWafer(ModuleName.Robot, (int)blade); //check sensor
  233. if (!bHasWafer)
  234. {
  235. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  236. return false;
  237. }
  238. if (IsEnableIdentifyThickness)
  239. {
  240. if (ModuleHelper.IsLoadPort(chamber))
  241. {
  242. if (SC.GetStringValue($"CarrierInfo.LowerThicknessType") != SC.GetStringValue($"CarrierInfo.{chamber}ThicknessType"))
  243. {
  244. EV.PostAlarmLog(ModuleName.System.ToString(), $"The wafer thickness of the lower arm is different from {chamber}.");
  245. return false;
  246. }
  247. }
  248. }
  249. }
  250. else if (blade == Hand.Blade2)
  251. {
  252. bool bHasWafer = true;
  253. for (int i = 0; i < robot.Blade2Slots; i++)
  254. {
  255. bool bNoWafer = WaferManager.Instance.CheckWafer(chamber, slot + i, WaferStatus.Empty);
  256. if (!bNoWafer)
  257. {
  258. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferPresentWithRecord, String.Format("Target {0}{1:D2}", chamber.ToString(), slot + i + 1));
  259. return false;
  260. }
  261. bHasWafer &= WaferManager.Instance.CheckWafer(ModuleName.Robot, (int)blade + i, WaferStatus.Normal);
  262. bool bSensorWafer = CheckSeneorHasWafer(ModuleName.Robot, (int)blade + i); //check sensor
  263. if (!bSensorWafer)
  264. {
  265. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  266. return false;
  267. }
  268. }
  269. if (!bHasWafer)
  270. {
  271. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  272. return false;
  273. }
  274. if (IsEnableIdentifyThickness)
  275. {
  276. if (ModuleHelper.IsLoadPort(chamber))
  277. {
  278. if (SC.GetStringValue($"CarrierInfo.UpperThicknessType") != SC.GetStringValue($"CarrierInfo.{chamber}ThicknessType"))
  279. {
  280. EV.PostAlarmLog(ModuleName.System.ToString(), $"The wafer thickness of the lower arm is different from {chamber}.");
  281. return false;
  282. }
  283. }
  284. }
  285. }
  286. else
  287. {
  288. bool bHasWafer = true;
  289. for (int i = 0; i < robot.Blade2Slots + 1; i++)
  290. {
  291. bool bNoWafer = WaferManager.Instance.CheckWafer(chamber, slot + i, WaferStatus.Empty);
  292. if (!bNoWafer)
  293. {
  294. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferPresentWithRecord, String.Format("Target {0}{1:D2}", chamber.ToString(), slot + i + 1));
  295. return false;
  296. }
  297. bHasWafer &= WaferManager.Instance.CheckWafer(ModuleName.Robot, (int)Hand.Blade1 + i, WaferStatus.Normal);
  298. bool bSensorWafer = CheckSeneorHasWafer(ModuleName.Robot, (int)Hand.Blade1 + i); //check sensor
  299. if (!bSensorWafer)
  300. {
  301. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  302. return false;
  303. }
  304. if (ModuleHelper.IsLoadPort(chamber))
  305. {
  306. string arm = i == 0 ? "Lower" : "Upper";
  307. if (SC.GetStringValue($"CarrierInfo.{arm}ThicknessType") != SC.GetStringValue($"CarrierInfo.{chamber}ThicknessType"))
  308. {
  309. EV.PostAlarmLog(ModuleName.System.ToString(), $"The wafer thickness of the {arm} arm is different from {chamber}.");
  310. return false;
  311. }
  312. }
  313. }
  314. if (!bHasWafer)
  315. {
  316. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferNotDetectedBeforeSend);
  317. return false;
  318. }
  319. }
  320. if (ModuleHelper.IsCoolingBuffer(chamber))
  321. {
  322. IoCoolingBuffer buffer = DEVICE.GetDevice<IoCoolingBuffer>(chamber.ToString());
  323. if (buffer == null)
  324. {
  325. EV.PostWarningLog("System", String.Format("{0} Device is Null", chamber.ToString()));
  326. return false;
  327. }
  328. if (!buffer.CheckPinUp())
  329. {
  330. EV.PostWarningLog(chamber.ToString(), "Can not place wafer to buffer, buffer isn't pick position.");
  331. return false;
  332. }
  333. }
  334. if (ModuleHelper.IsLoadPort(chamber))
  335. {
  336. //WaferSize size = WaferManager.Instance.GetWaferSize(ModuleName.Robot, (blade == Hand.Both) ? 0 : (int)blade);
  337. WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.Robot, (blade == Hand.Both) ? 0 : (int)blade);
  338. LoadPortBaseDevice lp = DEVICE.GetDevice<LoadPortBaseDevice>(chamber.ToString());
  339. LoadPortBaseDevice lp1 = DEVICE.GetDevice<LoadPortBaseDevice>(((ModuleName)wafer.OriginStation).ToString());
  340. if (!EnableMoveInDiffSlotsNumLP && lp1 != null && lp1.ValidSlotsNumber != lp.ValidSlotsNumber)
  341. {
  342. EV.PostWarningLog(chamber.ToString(), "Can not place wafer to loadport, SlotsNumber is unmatch.");
  343. return false;
  344. }
  345. if (IsEnableMultiWaferSize)
  346. {
  347. //因为此手臂只有一个手抓
  348. WaferSize size = WaferManager.Instance.GetWaferSize(ModuleName.Robot, (blade == Hand.Both) ? 0 : (int)blade);
  349. lp = DEVICE.GetDevice<LoadPortBaseDevice>(chamber.ToString());
  350. if (size != lp.GetCurrentWaferSize())
  351. {
  352. EV.PostWarningLog(chamber.ToString(), "Can not place wafer to loadport, size is unmatch.");
  353. return false;
  354. }
  355. }
  356. }
  357. return true;
  358. });
  359. if (ret.Item1)
  360. {
  361. if (ret.Item2 == Result.FAIL)
  362. {
  363. error(String.Format("Check wafer information failed, can not place."));
  364. throw (new RoutineFaildException());
  365. }
  366. }
  367. }
  368. public void CheckAfterPlace(int id, string name, ModuleName chamber, int slot, Hand blade, Action<string> notify, Action<string> error)
  369. {
  370. Tuple<bool, Result> ret = Execute(id, () =>
  371. {
  372. notify(name);
  373. //if (ModuleHelper.IsLoadLock(chamber) && Singleton<EfemEntity>.Instance.IsOnlineMode)
  374. //{
  375. // //online mode, DeleteWafer in LoadLock
  376. // WaferManager.Instance.DeleteWafer(chamber, slot);
  377. //}
  378. //if (ModuleHelper.IsBuffer(chamber) && Singleton<EfemEntity>.Instance.IsOnlineMode)
  379. //{
  380. // //online mode, DeleteWafer in LoadLock
  381. // WaferManager.Instance.DeleteWafer(chamber, slot);
  382. //}
  383. if (blade == Hand.Blade1)
  384. {
  385. bool bNoWafer = CheckSensorNoWafer(ModuleName.Robot, (int)blade);
  386. if (!bNoWafer)
  387. {
  388. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend);
  389. return false;
  390. }
  391. }
  392. else if (blade == Hand.Blade2)
  393. {
  394. for (int i = 0; i < robot.Blade2Slots; i++)
  395. {
  396. bool bNoWafer = CheckSensorNoWafer(ModuleName.Robot, (int)blade + i);
  397. if (!bNoWafer)
  398. {
  399. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend);
  400. return false;
  401. }
  402. }
  403. }
  404. else
  405. {
  406. for (int i = 0; i < robot.Blade2Slots + 1; i++)
  407. {
  408. bool bNoWafer = CheckSensorNoWafer(ModuleName.Robot, (int)Hand.Blade1 + i);
  409. if (!bNoWafer)
  410. {
  411. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDetectedAfterSend);
  412. return false;
  413. }
  414. }
  415. }
  416. return true;
  417. });
  418. if (ret.Item1)
  419. {
  420. if (ret.Item2 == Result.FAIL)
  421. {
  422. error(String.Format("Failed to check wafer information"));
  423. throw (new RoutineFaildException());
  424. }
  425. }
  426. }
  427. }
  428. }