PufSwapRoutine.cs 20 KB

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