SRDProcessRecipeRoutine.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.RT.Routine;
  3. using MECF.Framework.Common.RecipeCenter;
  4. using MECF.Framework.Common.Routine;
  5. using CyberX8_Core;
  6. using CyberX8_RT.Devices.AXIS;
  7. using CyberX8_RT.Devices.SRD;
  8. using System;
  9. using System.Collections.Generic;
  10. using MECF.Framework.Common.Utilities;
  11. using MECF.Framework.Common.CommonData;
  12. using MECF.Framework.Common.CommonData.SRD;
  13. using Aitex.Core.RT.SCCore;
  14. using Aitex.Core.RT.Device;
  15. using CyberX8_RT.Devices.Facilities;
  16. using Aitex.Core.Util;
  17. using CyberX8_RT.Modules.Transporter;
  18. using MECF.Framework.Common.WaferHolder;
  19. using MECF.Framework.Common.Persistent.SRD;
  20. namespace CyberX8_RT.Modules.SRD
  21. {
  22. public class SRDProcessRecipeRoutine : RoutineBase, IRoutine
  23. {
  24. #region 常量
  25. private const int LOTTRACK_TIME = 1000;
  26. #endregion
  27. private enum SRDProcessState
  28. {
  29. Ready,
  30. StartLoader,
  31. Loading,
  32. StartRunRecipe,
  33. RunReciping,
  34. StartUnloader,
  35. Unloading,
  36. CycleEnd,
  37. End
  38. }
  39. #region 内部变量
  40. /// <summary>
  41. /// 次数
  42. /// </summary>
  43. private int _cycleCount = 0;
  44. /// <summary>
  45. /// Rotation Axis
  46. /// </summary>
  47. private JetAxisBase _rotationAxis;
  48. /// <summary>
  49. /// Arm Axis
  50. /// </summary>
  51. private JetAxisBase _armAxis;
  52. /// <summary>
  53. /// SRD Recipe
  54. /// </summary>
  55. private SrdRecipe _srdRecipe;
  56. /// <summary>
  57. /// 设备对象
  58. /// </summary>
  59. private SrdCommonDevice _srdCommonDevice;
  60. /// <summary>
  61. /// Run Recipe Routine
  62. /// </summary>
  63. private SRDRunRecipeRoutine _runRecipeRoutine;
  64. /// <summary>
  65. /// Unloader Routine
  66. /// </summary>
  67. private SRDUnloaderRoutine _unloaderRoutine;
  68. /// <summary>
  69. /// Loader Routine
  70. /// </summary>
  71. private SRDLoaderRoutine _loaderRoutine;
  72. /// <summary>
  73. /// lock track time
  74. /// </summary>
  75. private DateTime _lotTackTime = DateTime.Now;
  76. /// <summary>
  77. /// LotTrack数据
  78. /// </summary>
  79. private List<SRDLotTrackData> _datas = new List<SRDLotTrackData>();
  80. /// <summary>
  81. /// LotTrack文件头数据
  82. /// </summary>
  83. private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData();
  84. /// <summary>
  85. /// Facilities
  86. /// </summary>
  87. private SystemFacilities _facilities;
  88. /// <summary>
  89. /// Manual模式
  90. /// </summary>
  91. private bool _isManual = false;
  92. #endregion
  93. #region 属性
  94. /// <summary>
  95. /// 当前子状态机
  96. /// </summary>
  97. public string CurrentStateMachine
  98. {
  99. get { return GetCurrentStateMachine(); }
  100. }
  101. /// <summary>
  102. /// 当前cycle次数
  103. /// </summary>
  104. public int AchievedCycle { get { return Runner.LoopCounter; } }
  105. /// <summary>
  106. /// 是否正在用水
  107. /// </summary>
  108. public bool IsUsingWater { get { return _runRecipeRoutine.IsUsingWater; } }
  109. /// <summary>
  110. /// LotTrack数据
  111. /// </summary>
  112. public List<SRDLotTrackData> SRDLotTrackDatas { get { return _datas; } }
  113. /// <summary>
  114. /// LotTrack文件头数据
  115. /// </summary>
  116. public LotTrackFileHeaderCommonData SRDLotTrackHeaderDatas { get { return _header; } }
  117. #endregion
  118. /// <summary>
  119. /// 构造函数
  120. /// </summary>
  121. /// <param name="module"></param>
  122. public SRDProcessRecipeRoutine(string module, JetAxisBase rotationAxis, JetAxisBase armAxis, SrdCommonDevice srdCommon) : base(module)
  123. {
  124. _rotationAxis = rotationAxis;
  125. _armAxis = armAxis;
  126. _srdCommonDevice = srdCommon;
  127. _runRecipeRoutine = new SRDRunRecipeRoutine(module);
  128. _unloaderRoutine= new SRDUnloaderRoutine(module);
  129. _loaderRoutine = new SRDLoaderRoutine(module);
  130. }
  131. /// <summary>
  132. /// 取消
  133. /// </summary>
  134. public void Abort()
  135. {
  136. if(_unloaderRoutine.Monitor() == RState.Running)
  137. {
  138. _unloaderRoutine.Abort();
  139. }
  140. if (_runRecipeRoutine.Monitor() == RState.Running)
  141. {
  142. _runRecipeRoutine.Abort();
  143. }
  144. if (_loaderRoutine.Monitor() == RState.Running)
  145. {
  146. _loaderRoutine.Abort();
  147. }
  148. Runner.Stop("Manual Abort");
  149. if (_srdCommonDevice != null)
  150. {
  151. _srdCommonDevice.EnterErrorOperation();
  152. }
  153. }
  154. /// <summary>
  155. /// 监控
  156. /// </summary>
  157. /// <returns></returns>
  158. /// <exception cref="NotImplementedException"></exception>
  159. public RState Monitor()
  160. {
  161. LottrackRecord();
  162. Runner.LoopStart(SRDProcessState.Ready, "Process Recipe Start", _cycleCount, NullFun, _delay_1ms)
  163. .LoopRunIf(SRDProcessState.StartLoader, !_isManual,() => { return StartLoader(); }, _delay_1ms)
  164. .LoopRunIfWithStopStatus(SRDProcessState.Loading, !_isManual, CheckLoaderEndStatus, CheckLoaderErrorStatus)
  165. .LoopRun(SRDProcessState.StartRunRecipe, () => { return StartRunRecipe(); }, _delay_1ms)
  166. .LoopRunWithStopStatus(SRDProcessState.RunReciping, CheckRunRecipeEndStatus, CheckRunRecipeErrorStatus)
  167. .LoopRunIf(SRDProcessState.StartUnloader, !_isManual, () => { return StartUnloader(); }, _delay_1ms)
  168. .LoopRunIfWithStopStatus(SRDProcessState.Unloading, !_isManual, CheckUnloaderEndStatus, CheckUnloaderErrorStatus)
  169. .LoopEnd(SRDProcessState.CycleEnd, NullFun, _delay_1ms)
  170. .End(SRDProcessState.End, NullFun, _delay_1ms);
  171. return Runner.Status;
  172. }
  173. /// <summary>
  174. /// 启动
  175. /// </summary>
  176. /// <param name="objects"></param>
  177. /// <returns></returns>
  178. /// <exception cref="NotImplementedException"></exception>
  179. public RState Start(params object[] objects)
  180. {
  181. _srdRecipe = objects[0] as SrdRecipe;
  182. if (_srdRecipe == null)
  183. {
  184. LOG.WriteLog(eEvent.ERR_SRD, Module.ToString(), " recipe is null");
  185. return RState.Failed;
  186. }
  187. _cycleCount = (int)objects[1];
  188. if (_cycleCount == 0)
  189. {
  190. return RState.End;
  191. }
  192. _isManual = false;
  193. SRDPersistentValue srdPersistentValue = SRDPersistentManager.Instance.GetModulePersistentValue(Module);
  194. if(srdPersistentValue.OperatingMode.Equals("Manual")) _isManual = true;
  195. _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
  196. _header.Recipe = $"{_srdRecipe.Ppid}.srd.rcp";
  197. if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID");
  198. _facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  199. if (_facilities == null)
  200. {
  201. LOG.WriteLog(eEvent.ERR_SRD, Module, "Facility is null");
  202. return RState.Failed;
  203. }
  204. _datas.Clear();
  205. _lotTackTime = DateTime.Now;
  206. return Runner.Start(Module, "Process Recipe");
  207. }
  208. #region Loader
  209. /// <summary>
  210. /// 启动LoaderRoutine
  211. /// </summary>
  212. /// <param name="recipe"></param>
  213. /// <returns></returns>
  214. private bool StartLoader()
  215. {
  216. bool result = _loaderRoutine.Start() == RState.Running;
  217. if (!result)
  218. {
  219. NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0);
  220. }
  221. return result;
  222. }
  223. /// <summary>
  224. /// 检验LoaderRoutine完成情况
  225. /// </summary>
  226. /// <returns></returns>
  227. private bool CheckLoaderEndStatus()
  228. {
  229. return CommonFunction.CheckRoutineEndState(_loaderRoutine);
  230. }
  231. /// <summary>
  232. /// 检验LoaderRoutine错误情况
  233. /// </summary>
  234. /// <returns></returns>
  235. private bool CheckLoaderErrorStatus()
  236. {
  237. bool result = CommonFunction.CheckRoutineStopState(_loaderRoutine);
  238. if (result)
  239. {
  240. AddLotTrackData();
  241. NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0);
  242. }
  243. return result;
  244. }
  245. #endregion
  246. #region RunRecipe
  247. /// <summary>
  248. /// 启动状态机
  249. /// </summary>
  250. /// <param name="recipe"></param>
  251. /// <returns></returns>
  252. private bool StartRunRecipe()
  253. {
  254. bool result = _runRecipeRoutine.Start(_srdRecipe)==RState.Running;
  255. if (result)
  256. {
  257. LOG.WriteLog(eEvent.INFO_SRD, Module.ToString(), $"Start Run Recipe, recipe[{_srdRecipe.Ppid}] times[{_cycleCount + 1}]");
  258. }
  259. else
  260. {
  261. NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0);
  262. }
  263. return result;
  264. }
  265. /// <summary>
  266. /// 检验RunRecipeRoutine完成情况
  267. /// </summary>
  268. /// <returns></returns>
  269. private bool CheckRunRecipeEndStatus()
  270. {
  271. return CommonFunction.CheckRoutineEndState(_runRecipeRoutine);
  272. }
  273. /// <summary>
  274. /// 检验RunRecipeRoutine错误情况
  275. /// </summary>
  276. /// <returns></returns>
  277. private bool CheckRunRecipeErrorStatus()
  278. {
  279. bool result = CommonFunction.CheckRoutineStopState(_runRecipeRoutine);
  280. if (result)
  281. {
  282. AddLotTrackData();
  283. if (_srdCommonDevice != null)
  284. {
  285. _srdCommonDevice.EnterErrorOperation();
  286. }
  287. NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0);
  288. }
  289. return result;
  290. }
  291. #endregion
  292. #region Unloader
  293. /// <summary>
  294. /// 启动UnloaderRoutine
  295. /// </summary>
  296. /// <param name="recipe"></param>
  297. /// <returns></returns>
  298. private bool StartUnloader()
  299. {
  300. bool result= _unloaderRoutine.Start() == RState.Running;
  301. if (!result)
  302. {
  303. NotifyError(eEvent.ERR_SRD,_unloaderRoutine.ErrorMsg, 0);
  304. }
  305. return result;
  306. }
  307. /// <summary>
  308. /// 检验UnloaderRoutine完成情况
  309. /// </summary>
  310. /// <returns></returns>
  311. private bool CheckUnloaderEndStatus()
  312. {
  313. return CommonFunction.CheckRoutineEndState(_unloaderRoutine);
  314. }
  315. /// <summary>
  316. /// 检验UnloaderRoutine错误情况
  317. /// </summary>
  318. /// <returns></returns>
  319. private bool CheckUnloaderErrorStatus()
  320. {
  321. bool result= CommonFunction.CheckRoutineStopState(_unloaderRoutine);
  322. if (result)
  323. {
  324. AddLotTrackData();
  325. NotifyError(eEvent.ERR_SRD, _unloaderRoutine.ErrorMsg, 0);
  326. }
  327. return result;
  328. }
  329. #endregion
  330. /// <summary>
  331. /// 获取当前子状态机
  332. /// </summary>
  333. private string GetCurrentStateMachine()
  334. {
  335. string result;
  336. if(Runner.CurrentStep.ToString() == "Ready")
  337. {
  338. result = "Ready";
  339. }
  340. else if(Runner.CurrentStep.ToString().Contains("RunReciping"))
  341. {
  342. result = _runRecipeRoutine.CurrentStep;
  343. }
  344. else if(Runner.CurrentStep.ToString().Contains("Unloading"))
  345. {
  346. result = _unloaderRoutine.CurrentStep;
  347. }
  348. else
  349. {
  350. result = "End";
  351. }
  352. return result;
  353. }
  354. /// <summary>
  355. /// 记录Lottrack
  356. /// </summary>
  357. private void LottrackRecord()
  358. {
  359. //记录Lottrack
  360. if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME)
  361. {
  362. AddLotTrackData();
  363. _lotTackTime = DateTime.Now;
  364. }
  365. }
  366. /// <summary>
  367. /// 获取Lot Track数据
  368. /// </summary>
  369. /// <returns></returns>
  370. private void AddLotTrackData()
  371. {
  372. SRDLotTrackData data = new SRDLotTrackData();
  373. data.TimeStamp = DateTime.Now;
  374. data.StateMachine = GetCurrentStateMachine();
  375. data.ArmPosition = _armAxis.MotionData.MotorPosition;
  376. data.WaterPressure = _srdCommonDevice.CommonData.WaterPressure;
  377. data.WaferPresence = $"{_srdCommonDevice.WaferPresence}:{_srdCommonDevice.CommonData.WaferPresence}";
  378. data.ChuckVacuumOn = _srdCommonDevice.CommonData.ChuckVacuum;
  379. data.ChuckVacuumPressure = _srdCommonDevice.CommonData.VacuumValue;
  380. data.ArmTorque = _armAxis.MotionData.ActualTorque;
  381. data.SpinTorque = _rotationAxis.MotionData.ActualTorque;
  382. data.RotationSpeed = _rotationAxis.MotionData.ActualVelocity;
  383. data.N2BelowOn = false;
  384. data.WaterAbove = _srdCommonDevice.CommonData.WaterAbove;
  385. data.WaterBelow = _srdCommonDevice.CommonData.WaterBelow;
  386. data.ExhaustOn = _srdCommonDevice.CommonData.ExhaustOn;
  387. data.LoaderDIEnable = _facilities.LoaderDiEnable;
  388. data.WaterFlow = 0;
  389. _datas.Add(data);
  390. }
  391. /// <summary>
  392. /// 重试
  393. /// </summary>
  394. /// <param name="step"></param>
  395. public RState Retry(int step)
  396. {
  397. List<Enum> preStepIds = new List<Enum>();
  398. return Runner.Retry(SRDProcessState.Ready, preStepIds, Module, "RunRecipe Retry");
  399. }
  400. /// <summary>
  401. /// 检验前面完成状态
  402. /// </summary>
  403. /// <returns></returns>
  404. public bool CheckCompleteCondition(int index)
  405. {
  406. if (_armAxis.IsRun)
  407. {
  408. NotifyError(eEvent.ERR_SRD, "Arm axis is run", 0);
  409. return false;
  410. }
  411. if (!_armAxis.IsHomed)
  412. {
  413. NotifyError(eEvent.ERR_SRD, "Arm axis is not homed", 0);
  414. return false;
  415. }
  416. if (_rotationAxis.IsRun)
  417. {
  418. NotifyError(eEvent.ERR_SRD, "Rotation axis is run", 0);
  419. return false;
  420. }
  421. if (!_rotationAxis.IsHomed)
  422. {
  423. NotifyError(eEvent.ERR_SRD, "Rotation axis is not homed", 0);
  424. return false;
  425. }
  426. if (!_srdCommonDevice.CommonData.ChuckVacuum)
  427. {
  428. NotifyError(eEvent.ERR_SRD, "Vacuum is not released", 0);
  429. return false;
  430. }
  431. if (!_srdCommonDevice.CommonData.DoorOpened)
  432. {
  433. NotifyError(eEvent.ERR_SRD, "Door is not opened", 0);
  434. return false;
  435. }
  436. return true;
  437. }
  438. }
  439. }