PufSwapRoutine.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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. //Loader Handle Wafer状态确认
  322. // Lip Seal Vacuum "ON"
  323. if (!_loaderSide.SideData.CRSVacuum)
  324. {
  325. NotifyError(eEvent.ERR_PUF, "Loader1 LS Vacuum is off",-1);
  326. return false;
  327. }
  328. //Bernoulli Bladder "ON",Retracted Green Light
  329. if (!_loaderSide.SideData.BernoulliBladder)
  330. {
  331. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli Bladder is off",-1);
  332. return false;
  333. }
  334. if (_loaderSide.SideData.BernoulliExtended)
  335. {
  336. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli Retracted is off",-1);
  337. return false;
  338. }
  339. //其他SideA/B均为OFF
  340. if (_loaderSide.SideData.BernoulliN2)
  341. {
  342. NotifyError(eEvent.ERR_PUF, "Loader1 Bernoulli N2 is on",-1);
  343. return false;
  344. }
  345. if (!_loaderSide.SideData.DoorUnlock)
  346. {
  347. NotifyError(eEvent.ERR_PUF, "Loader1 Door is Locked",-1);
  348. return false;
  349. }
  350. //if (_loaderSide.SideData.WHBladder)
  351. //{
  352. // NotifyError(eEvent.ERR_PUF,, "Loader1 WS Bladder is on");
  353. // return false;
  354. //}
  355. if (_loaderSide.SideData.TransBladder)
  356. {
  357. NotifyError(eEvent.ERR_PUF, "Loader1 Translate Bladder is on",-1);
  358. return false;
  359. }
  360. if (_loaderSide.SideData.TransHigh)
  361. {
  362. NotifyError(eEvent.ERR_PUF, "Loader1 Translate High Pre is on",-1);
  363. return false;
  364. }
  365. }
  366. //Loader Transporter在Loader右侧
  367. bool loaderTransporterInstalled = ModuleHelper.IsInstalled(ModuleName.Transporter2);
  368. if (loaderTransporterInstalled && !_gantryAxis.JudgeCompareTargetStation("Loader", "Right"))
  369. {
  370. NotifyError(eEvent.ERR_PUF, "Loader Transporter is not in Loader right position",-1);
  371. return false;
  372. }
  373. double verticalPosition = _verticalAxis.MotionData.MotorPosition;
  374. if (!_verticalAxis.CheckPositionIsInStation(verticalPosition, "Park"))
  375. {
  376. NotifyError(eEvent.ERR_PUF, $"vertical axis {verticalPosition} is not at Park Station",-1);
  377. return false;
  378. }
  379. double rotaionPosition = _rotationAxis.MotionData.MotorPosition;
  380. if (_rotationAxis.CheckPositionIsEmpty(rotaionPosition))
  381. {
  382. NotifyError(eEvent.ERR_PUF, $"rotation axis {rotaionPosition} is not at Station",-1);
  383. return false;
  384. }
  385. double flipPosition = _flipAxis.MotionData.MotorPosition;
  386. if (_flipAxis.CheckPositionIsEmpty(flipPosition))
  387. {
  388. NotifyError(eEvent.ERR_PUF, $"flip axis {flipPosition} is not at Station",-1);
  389. return false;
  390. }
  391. //A面
  392. if (_loaderSide.Name == SIDE_A)
  393. {
  394. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 0))
  395. {
  396. NotifyError(eEvent.ERR_PUF, "loader side A has no wafer",-1);
  397. return false;
  398. }
  399. }
  400. else
  401. {
  402. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 1))
  403. {
  404. NotifyError(eEvent.ERR_PUF, "loader side B has no wafer",-1);
  405. return false;
  406. }
  407. }
  408. return true;
  409. }
  410. /// <summary>
  411. /// 获取LoaderSide
  412. /// </summary>
  413. private void GetLoaderSide()
  414. {
  415. if (Module == ModuleName.PUF1.ToString())
  416. {
  417. _loaderSide = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideA");
  418. }
  419. else
  420. {
  421. _loaderSide = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideB");
  422. }
  423. }
  424. /// <summary>
  425. /// 重试
  426. /// </summary>
  427. /// <param name="step"></param>
  428. public RState Retry(int step)
  429. {
  430. InitializeParameters();
  431. List<Enum> preStepIds = new List<Enum>();
  432. if (step == 0||step==-1)
  433. {
  434. return Runner.Retry(SwapStep.CheckPreStatus, preStepIds, Module, "Swap Retry");
  435. }
  436. else if (step == 1)
  437. {
  438. AddPreSteps(SwapStep.VerticalFlip, preStepIds);
  439. return Runner.Retry(SwapStep.VerticalFlip, preStepIds, Module, $"Swap step {SwapStep.VerticalFlip} Retry");
  440. }
  441. else
  442. {
  443. AddPreSteps(SwapStep.PlaceToLoader, preStepIds);
  444. return Runner.Retry(SwapStep.PlaceToLoader, preStepIds, Module, $"Swap step {SwapStep.PlaceToLoader} Retry");
  445. }
  446. }
  447. /// <summary>
  448. /// 忽略前
  449. /// </summary>
  450. /// <param name="step"></param>
  451. /// <param name="preStepIds"></param>
  452. private void AddPreSteps(SwapStep step, List<Enum> preStepIds)
  453. {
  454. for (int i = 0; i < (int)step; i++)
  455. {
  456. preStepIds.Add((SwapStep)i);
  457. }
  458. }
  459. /// <summary>
  460. /// 检验完成情况
  461. /// </summary>
  462. /// <returns></returns>
  463. public bool CheckCompleteCondition()
  464. {
  465. if (WaferManager.Instance.CheckHasWafer(Module, 1))
  466. {
  467. NotifyError(eEvent.ERR_PUF, "Side B has wafer", 0);
  468. return false;
  469. }
  470. if (Module == ModuleName.PUF1.ToString())
  471. {
  472. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 0))
  473. {
  474. NotifyError(eEvent.ERR_PUF, "Loader Side A has wafer", 0);
  475. return false;
  476. }
  477. }
  478. else
  479. {
  480. if (WaferManager.Instance.CheckNoWafer(ModuleName.Loader1, 1))
  481. {
  482. NotifyError(eEvent.ERR_PUF, "Loader Side B has wafer", 0);
  483. return false;
  484. }
  485. }
  486. return true;
  487. }
  488. }
  489. }