PufSwapRoutine.cs 19 KB

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