PufSwapRoutine.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Device;
  4. using Aitex.Core.RT.Log;
  5. using Aitex.Core.RT.Routine;
  6. using Aitex.Core.Util;
  7. using MECF.Framework.Common.DBCore;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.Routine;
  10. using MECF.Framework.Common.SubstrateTrackings;
  11. using MECF.Framework.Common.Utilities;
  12. using MECF.Framework.Common.WaferHolder;
  13. using CyberX8_Core;
  14. using CyberX8_RT.Devices.AXIS;
  15. using CyberX8_RT.Devices.Loader;
  16. using CyberX8_RT.Devices.PUF;
  17. using CyberX8_RT.Modules.Loader;
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Reflection;
  22. using System.Text;
  23. using System.Threading.Tasks;
  24. namespace CyberX8_RT.Modules.PUF
  25. {
  26. public class PufSwapRoutine : RoutineBase, IRoutine
  27. {
  28. private enum SwapStep
  29. {
  30. CheckPreStatus,
  31. RotationLoaderPickup,
  32. RotationLoaderPickupWait,
  33. VerticalLoaderPickup,
  34. VerticalLoaderPickupWait,
  35. SideAVacuumOn,
  36. StickDistance,
  37. StickDistanceWait,
  38. StickDistanceCheck,
  39. VerticalFlip,
  40. WaitVerticalFlip,
  41. RotationFlip,
  42. WaitRotationFlip,
  43. FlipSideB,
  44. WaitFlipSideB,
  45. PlaceToLoader,
  46. PlaceToLoaderWait,
  47. End
  48. }
  49. #region 常量
  50. private const string CURRENT_STATION_LIST = "CurrentStationList";
  51. private const string WAFER_PRESENT = "WaferPresent";
  52. private const string SIDE_A = "SideA";
  53. #endregion
  54. #region 内部变量
  55. private LoaderEntity _loaderEntity;
  56. private JetAxisBase _flipAxis;
  57. private JetAxisBase _rotationAxis;
  58. private JetAxisBase _verticalAxis;
  59. private JetAxisBase _gantryAxis;
  60. private LoaderSideDevice _loaderSide;
  61. private PufVacuum _vacuum;
  62. private PufDistanceSensor _distanceSensor;
  63. private PufPlaceToLoaderRoutine _placeToLoaderRoutine;
  64. #endregion
  65. /// <summary>
  66. /// 构造函数
  67. /// </summary>
  68. /// <param name="module"></param>
  69. public PufSwapRoutine(string module) : base(module)
  70. {
  71. _placeToLoaderRoutine = new PufPlaceToLoaderRoutine(Module);
  72. }
  73. /// <summary>
  74. /// 中止
  75. /// </summary>
  76. public void Abort()
  77. {
  78. Runner.Stop("Manual Abort");
  79. }
  80. /// <summary>
  81. /// 监控
  82. /// </summary>
  83. /// <returns></returns>
  84. public RState Monitor()
  85. {
  86. Runner.Run(SwapStep.CheckPreStatus,CheckCondition,_delay_1ms)
  87. .Run(SwapStep.RotationLoaderPickup, ()=> { return AxisGotoPosition(_rotationAxis, "LoaderPickup",0); }, _delay_1ms)
  88. .WaitWithStopCondition(SwapStep.RotationLoaderPickupWait, () => { return _rotationAxis.Status == RState.End; },
  89. () => { return CheckRotationStopStatus(0); })
  90. .Run(SwapStep.VerticalLoaderPickup, () => { return AxisGotoPosition(_verticalAxis, "LoaderPickup", 0); }, _delay_1ms)
  91. .WaitWithStopCondition(SwapStep.VerticalLoaderPickupWait, () => { return _verticalAxis.Status == RState.End; },
  92. () => { return CheckVerticalStopStatus(0); })
  93. .Run(SwapStep.SideAVacuumOn, SideAVacuumOn, CheckSideAWaferPresent, 5000)
  94. .Run(SwapStep.StickDistance, StickDistance, 100)
  95. .WaitWithStopCondition(SwapStep.StickDistanceWait, () => { return _verticalAxis.Status == RState.End; },
  96. () => { return CheckVerticalStopStatus(0); })
  97. .Wait(SwapStep.StickDistanceCheck, CheckStickDistanceStatus, 1000)
  98. .Run(SwapStep.VerticalFlip, () => { return AxisGotoPosition(_verticalAxis,"Flip",1); }, _delay_1ms)
  99. .WaitWithStopCondition(SwapStep.WaitVerticalFlip, () => { return _verticalAxis.Status == RState.End; },
  100. () => { return CheckVerticalStopStatus(1); })
  101. .Run(SwapStep.RotationFlip, () => { return AxisGotoPosition(_rotationAxis,"Flip",1); }, _delay_1ms)
  102. .WaitWithStopCondition(SwapStep.WaitRotationFlip, () => { return _rotationAxis.Status == RState.End; },
  103. () => { return CheckRotationStopStatus(1); })
  104. .Run(SwapStep.FlipSideB, () => { return AxisGotoPosition(_flipAxis,"SideB", 1); }, _delay_1ms)
  105. .WaitWithStopCondition(SwapStep.WaitFlipSideB, () => { return _flipAxis.Status == RState.End; },
  106. () => { return CheckFlipStopStatus(1); })
  107. .Run(SwapStep.PlaceToLoader, () => _placeToLoaderRoutine.Start("SideB") == RState.Running, _delay_1ms)
  108. .WaitWithStopCondition(SwapStep.PlaceToLoaderWait, ()=>CommonFunction.CheckRoutineEndState(_placeToLoaderRoutine),
  109. CheckPlaceToRoutineStopStatus)
  110. .End(SwapStep.End, NullFun, _delay_1ms);
  111. return Runner.Status;
  112. }
  113. /// <summary>
  114. /// Side a打开真空
  115. /// </summary>
  116. /// <returns></returns>
  117. private bool SideAVacuumOn()
  118. {
  119. bool result= _vacuum.VacuumAOn();
  120. if (!result)
  121. {
  122. NotifyError(eEvent.ERR_PUF, "side A Vacuum on failed", 0);
  123. }
  124. return result;
  125. }
  126. /// <summary>
  127. /// 检验SideA是否存在Wafer
  128. /// </summary>
  129. /// <returns></returns>
  130. private bool CheckSideAWaferPresent()
  131. {
  132. bool result= _vacuum.ChuckAVacuumStatus == WAFER_PRESENT;
  133. if(result)
  134. {
  135. LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
  136. if(loaderEntity!=null)
  137. {
  138. WaferHolderInfo waferHolder = loaderEntity.WaferHolderInfo;
  139. if(_loaderSide.Name==SIDE_A)
  140. {
  141. if (WaferManager.Instance.CheckHasWafer(ModuleName.Loader1, 0))
  142. {
  143. WaferManager.Instance.WaferMoved(ModuleName.Loader1, 0, ModuleHelper.Converter(Module), 0);
  144. }
  145. else
  146. {
  147. NotifyError(eEvent.ERR_PUF, "Loader sideA has no wafer",0);
  148. return false;
  149. }
  150. }
  151. else
  152. {
  153. if (WaferManager.Instance.CheckHasWafer(ModuleName.Loader1, 1))
  154. {
  155. WaferManager.Instance.WaferMoved(ModuleName.Loader1, 1, ModuleHelper.Converter(Module), 0);
  156. }
  157. else
  158. {
  159. NotifyError(eEvent.ERR_PUF, "Loader sideA has no wafer", 0);
  160. return false;
  161. }
  162. }
  163. }
  164. }
  165. return result;
  166. }
  167. /// <summary>
  168. /// Stick Distance
  169. /// </summary>
  170. /// <returns></returns>
  171. private bool StickDistance()
  172. {
  173. bool result= _distanceSensor.GotoStickDistance();
  174. if(!result)
  175. {
  176. NotifyError(eEvent.ERR_PUF, "goto stick distance failed", 0);
  177. }
  178. return result;
  179. }
  180. /// <summary>
  181. /// Stick Distance检验结果
  182. /// </summary>
  183. /// <returns></returns>
  184. private bool CheckStickDistanceStatus()
  185. {
  186. bool result= _distanceSensor.CheckStickDistanceStatus();
  187. if (!result)
  188. {
  189. NotifyError(eEvent.ERR_PUF, "check stick distance failed", 0);
  190. }
  191. return result;
  192. }
  193. /// <summary>
  194. /// Axis goto position
  195. /// </summary>
  196. /// <param name="axis"></param>
  197. /// <param name="position"></param>
  198. /// <param name="index"></param>
  199. /// <returns></returns>
  200. private bool AxisGotoPosition(JetAxisBase axis,string position,int index)
  201. {
  202. bool result = axis.PositionStation(position);
  203. if(!result)
  204. {
  205. NotifyError(eEvent.ERR_PUF, $"{axis.Module} goto {position} failed",index);
  206. }
  207. return result;
  208. }
  209. /// <summary>
  210. /// 检验Flip异常状态
  211. /// </summary>
  212. /// <returns></returns>
  213. private bool CheckFlipStopStatus(int index)
  214. {
  215. bool result = _flipAxis.Status == RState.Failed || _flipAxis.Status == RState.Timeout;
  216. if (result)
  217. {
  218. NotifyError(eEvent.ERR_PUF, "flip motion failed", index);
  219. }
  220. return result;
  221. }
  222. /// <summary>
  223. /// 检验Rotation异常状态
  224. /// </summary>
  225. /// <returns></returns>
  226. private bool CheckRotationStopStatus(int index)
  227. {
  228. bool result = _rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout;
  229. if (result)
  230. {
  231. NotifyError(eEvent.ERR_PUF, "rotation motion failed", index);
  232. }
  233. return result;
  234. }
  235. /// <summary>
  236. /// 检验Vertical异常状态
  237. /// </summary>
  238. /// <returns></returns>
  239. private bool CheckVerticalStopStatus(int index)
  240. {
  241. bool result = _verticalAxis.Status == RState.Failed || _verticalAxis.Status == RState.Timeout;
  242. if (result)
  243. {
  244. NotifyError(eEvent.ERR_PUF, "vetical motion failed", index);
  245. }
  246. return result;
  247. }
  248. /// <summary>
  249. /// 检验PlaceToLoader异常状态
  250. /// </summary>
  251. /// <returns></returns>
  252. private bool CheckPlaceToRoutineStopStatus()
  253. {
  254. bool result = CommonFunction.CheckRoutineStopState(_placeToLoaderRoutine);
  255. if (result)
  256. {
  257. NotifyError(eEvent.ERR_PUF, "place wafer failed", 2);
  258. }
  259. return result;
  260. }
  261. /// <summary>
  262. /// 启动
  263. /// </summary>
  264. /// <param name="objs"></param>
  265. /// <returns></returns>
  266. public RState Start(params object[] objs)
  267. {
  268. InitializeParameters();
  269. return Runner.Start(Module, "Start Swap");
  270. }
  271. /// <summary>
  272. /// 初始化参数
  273. /// </summary>
  274. private void InitializeParameters()
  275. {
  276. _loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
  277. _flipAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Flip");
  278. _rotationAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Rotation");
  279. _verticalAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Vertical");
  280. _vacuum = DEVICE.GetDevice<PufVacuum>($"{Module}.Vacuum");
  281. _gantryAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Transporter2}.Gantry");
  282. _distanceSensor = DEVICE.GetDevice<PufDistanceSensor>($"{Module}.DistanceSensor");
  283. GetLoaderSide();
  284. }
  285. /// <summary>
  286. /// 检验条件
  287. /// </summary>
  288. /// <returns></returns>
  289. private bool CheckCondition()
  290. {
  291. //Loader1.Rotation 在LOADA
  292. bool isLoaderInstall = ModuleHelper.IsInstalled(ModuleName.Loader1);
  293. if (isLoaderInstall)
  294. {
  295. JetAxisBase loaderRotationAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.Rotation");
  296. double loaderRotationPosition = loaderRotationAxis.MotionData.MotorPosition;
  297. if (!loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "LOADA"))
  298. {
  299. NotifyError(eEvent.ERR_PUF, $"Loader Rotation {loaderRotationPosition} is not in LOADA",-1);
  300. return false;
  301. }
  302. if (Module == ModuleName.PUF1.ToString())
  303. {
  304. //Loader1.SwingA 在Open
  305. JetAxisBase loaderShuttleAAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.ShuttleA");
  306. double loaderShuttleAPosition = loaderShuttleAAxis.MotionData.MotorPosition;
  307. if (!loaderShuttleAAxis.CheckPositionIsInStation(loaderShuttleAPosition, "OPEN"))
  308. {
  309. NotifyError(eEvent.ERR_PUF, $"Loader ShuttleA {loaderShuttleAPosition} is not in OPEN",-1);
  310. return false;
  311. }
  312. //Loader1.TiltA 在HORI
  313. JetAxisBase loaderTiltAAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.TiltA");
  314. double loaderTiltAPosition = loaderTiltAAxis.MotionData.MotorPosition;
  315. if (!loaderTiltAAxis.CheckPositionIsInStation(loaderTiltAPosition, "HORI"))
  316. {
  317. NotifyError(eEvent.ERR_PUF, $"Loader TiltA {loaderTiltAPosition} is not in HORI",-1);
  318. return false;
  319. }
  320. }
  321. if (Module == ModuleName.PUF2.ToString())
  322. {
  323. //Loader1.SwingB 在Open
  324. JetAxisBase loaderShuttleBAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.ShuttleB");
  325. double loaderShuttleBPosition = loaderShuttleBAxis.MotionData.MotorPosition;
  326. if (!loaderShuttleBAxis.CheckPositionIsInStation(loaderShuttleBPosition, "OPEN"))
  327. {
  328. NotifyError(eEvent.ERR_PUF, $"Loader ShuttleB {loaderShuttleBPosition} is not in OPEN",-1);
  329. return false;
  330. }
  331. //Loader1.TiltB 在HORI
  332. JetAxisBase loaderTiltBAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.TiltB");
  333. double loaderTiltBPosition = loaderTiltBAxis.MotionData.MotorPosition;
  334. if (!loaderTiltBAxis.CheckPositionIsInStation(loaderTiltBPosition, "HORI"))
  335. {
  336. NotifyError(eEvent.ERR_PUF, $"Loader TiltB {loaderTiltBPosition} is not in HORI",-1);
  337. return false;
  338. }
  339. }
  340. //Loader Handle Wafer状态确认
  341. // Lip Seal Vacuum "ON"
  342. if (!_loaderSide.SideData.CRSVacuum)
  343. {
  344. NotifyError(eEvent.ERR_PUF, "Loader1 LS Vacuum is off",-1);
  345. return false;
  346. }
  347. //Bernoulli Bladder "ON",Retracted Green Light
  348. if (!_loaderSide.SideData.BernoulliBladder)
  349. {
  350. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli Bladder is off",-1);
  351. return false;
  352. }
  353. if (_loaderSide.SideData.BernoulliExtended)
  354. {
  355. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli Retracted is off",-1);
  356. return false;
  357. }
  358. //其他SideA/B均为OFF
  359. if (_loaderSide.SideData.BernoulliN2)
  360. {
  361. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli N2 is on",-1);
  362. return false;
  363. }
  364. if (!_loaderSide.SideData.DoorUnlock)
  365. {
  366. NotifyError(eEvent.ERR_PUF, "Loader1 Door is Locked",-1);
  367. return false;
  368. }
  369. //if (_loaderSide.SideData.WHBladder)
  370. //{
  371. // NotifyError(eEvent.ERR_PUF,, "Loader1 WS Bladder is on");
  372. // return false;
  373. //}
  374. if (_loaderSide.SideData.TransBladder)
  375. {
  376. NotifyError(eEvent.ERR_PUF, "Loader1 Translate Bladder is on",-1);
  377. return false;
  378. }
  379. if (_loaderSide.SideData.TransHigh)
  380. {
  381. NotifyError(eEvent.ERR_PUF, "Loader1 Translate High Pre is on",-1);
  382. return false;
  383. }
  384. }
  385. //Loader Transporter在Loader右侧
  386. bool loaderTransporterInstalled = ModuleHelper.IsInstalled(ModuleName.Transporter2);
  387. if (loaderTransporterInstalled && !_gantryAxis.JudgeCompareTargetStation("Loader", "Right"))
  388. {
  389. NotifyError(eEvent.ERR_PUF, "Loader Transporter is not in Loader right position",-1);
  390. return false;
  391. }
  392. double verticalPosition = _verticalAxis.MotionData.MotorPosition;
  393. if (!_verticalAxis.CheckPositionIsInStation(verticalPosition, "Park"))
  394. {
  395. NotifyError(eEvent.ERR_PUF, $"vertical axis {verticalPosition} is not at Park Station",-1);
  396. return false;
  397. }
  398. double rotaionPosition = _rotationAxis.MotionData.MotorPosition;
  399. if (_rotationAxis.CheckPositionIsEmpty(rotaionPosition))
  400. {
  401. NotifyError(eEvent.ERR_PUF, $"rotation axis {rotaionPosition} is not at Station",-1);
  402. return false;
  403. }
  404. double flipPosition = _flipAxis.MotionData.MotorPosition;
  405. if (_flipAxis.CheckPositionIsEmpty(flipPosition))
  406. {
  407. NotifyError(eEvent.ERR_PUF, $"flip axis {flipPosition} is not at Station",-1);
  408. return false;
  409. }
  410. //A面
  411. if (_loaderSide.Name == SIDE_A)
  412. {
  413. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 0))
  414. {
  415. NotifyError(eEvent.ERR_PUF, "loader side A has no wafer",-1);
  416. return false;
  417. }
  418. }
  419. else
  420. {
  421. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 1))
  422. {
  423. NotifyError(eEvent.ERR_PUF, "loader side B has no wafer",-1);
  424. return false;
  425. }
  426. }
  427. return true;
  428. }
  429. /// <summary>
  430. /// 获取LoaderSide
  431. /// </summary>
  432. private void GetLoaderSide()
  433. {
  434. if (Module == ModuleName.PUF1.ToString())
  435. {
  436. _loaderSide = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideA");
  437. }
  438. else
  439. {
  440. _loaderSide = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideB");
  441. }
  442. }
  443. /// <summary>
  444. /// 重试
  445. /// </summary>
  446. /// <param name="step"></param>
  447. public RState Retry(int step)
  448. {
  449. InitializeParameters();
  450. List<Enum> preStepIds = new List<Enum>();
  451. if (step == 0||step==-1)
  452. {
  453. return Runner.Retry(SwapStep.CheckPreStatus, preStepIds, Module, "Swap Retry");
  454. }
  455. else if (step == 1)
  456. {
  457. AddPreSteps(SwapStep.VerticalFlip, preStepIds);
  458. return Runner.Retry(SwapStep.VerticalFlip, preStepIds, Module, $"Swap step {SwapStep.VerticalFlip} Retry");
  459. }
  460. else
  461. {
  462. AddPreSteps(SwapStep.PlaceToLoader, preStepIds);
  463. return Runner.Retry(SwapStep.PlaceToLoader, preStepIds, Module, $"Swap step {SwapStep.PlaceToLoader} Retry");
  464. }
  465. }
  466. /// <summary>
  467. /// 忽略前
  468. /// </summary>
  469. /// <param name="step"></param>
  470. /// <param name="preStepIds"></param>
  471. private void AddPreSteps(SwapStep step, List<Enum> preStepIds)
  472. {
  473. for (int i = 0; i < (int)step; i++)
  474. {
  475. preStepIds.Add((SwapStep)i);
  476. }
  477. }
  478. /// <summary>
  479. /// 检验完成情况
  480. /// </summary>
  481. /// <returns></returns>
  482. public bool CheckCompleteCondition()
  483. {
  484. if (WaferManager.Instance.CheckHasWafer(Module, 1))
  485. {
  486. NotifyError(eEvent.ERR_PUF, "Side B has wafer", 0);
  487. return false;
  488. }
  489. if (Module == ModuleName.PUF1.ToString())
  490. {
  491. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 0))
  492. {
  493. NotifyError(eEvent.ERR_PUF, "Loader Side A has wafer", 0);
  494. return false;
  495. }
  496. }
  497. else
  498. {
  499. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 1))
  500. {
  501. NotifyError(eEvent.ERR_PUF, "Loader Side B has wafer", 0);
  502. return false;
  503. }
  504. }
  505. return true;
  506. }
  507. }
  508. }