RinseFirstStepRoutine.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.IOCore;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.RecipeCenter;
  5. using Aitex.Core.RT.Routine;
  6. using Aitex.Core.RT.SCCore;
  7. using MECF.Framework.Common.RecipeCenter;
  8. using MECF.Framework.Common.Routine;
  9. using CyberX8_Core;
  10. using CyberX8_RT.Devices.Resistivity;
  11. using CyberX8_RT.Devices.Rinse;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. namespace CyberX8_RT.Modules.Rinse
  18. {
  19. public class RinseFirstStepRoutine : RoutineBase, IRoutine
  20. {
  21. private enum RinseFirstStep
  22. {
  23. StartPrepare,
  24. FirstDrain,
  25. CheckDrain,
  26. WaitDrianEmpty,
  27. N2BubbleOn,
  28. N2BubbleOnDelay,
  29. Recipe_StartFirstRinseCycle,
  30. Recipe_PerformFirstRinseCycle,
  31. Recipe_FirstRinseCycleStartFilling,
  32. Recipe_FirstRinseCycleRecordStartWaterLevel,
  33. Recipe_FirstRinseCycleStartFillingWait,
  34. Recipe_FirstRinseCycleWaitFillingDetected,
  35. Recipe_FirstRinseCycleWaitFull,
  36. Recipe_FirstRinseCycleWaitEndFillTime,
  37. Recipe_FirstRinseCycleWaitDwell,
  38. Recipe_FirstRinseCycleWaitDrain,
  39. Recipe_FirstRinseCycleCheckDrain,
  40. Recipe_FirstRinseCycleWaitDrainExtraTime,
  41. Recipe_FirstRinseCycleEnd,
  42. Recipe_FirstRinseCycleComplete
  43. }
  44. #region 内部变量
  45. /// <summary>
  46. /// 设备对象
  47. /// </summary>
  48. private RinseDevice _device;
  49. /// <summary>
  50. /// Recipe
  51. /// </summary>
  52. private QdrRecipe _recipe;
  53. /// <summary>
  54. /// Fill打开注水记录Water Level
  55. /// </summary>
  56. private double _fillingDetectStartWaterLevel;
  57. /// <summary>
  58. /// 配置文件中注水整个过程的耗时
  59. /// </summary>
  60. private int _concurrentFillTimeSeconds;
  61. /// <summary>
  62. /// 开始注水的偏差
  63. /// </summary>
  64. private double _fillingStartedDelta;
  65. /// <summary>
  66. /// 注满数值
  67. /// </summary>
  68. private int _sensorReadingFull;
  69. /// <summary>
  70. /// 液位为空数值
  71. /// </summary>
  72. private int _sensorReadingEmpty;
  73. /// <summary>
  74. /// 开始流水时间
  75. /// </summary>
  76. private DateTime _startFillTime;
  77. /// <summary>
  78. /// 从开始排水到检测是否排空的间隔时间
  79. /// </summary>
  80. private int _normalDrainTimeSeconds;
  81. /// <summary>
  82. /// 开始注水后检测是否正常注水间隔
  83. /// </summary>
  84. private int _checkIsFillingTimeSeconds;
  85. /// <summary>
  86. /// 开始注水后检测是否注满间隔
  87. /// </summary>
  88. private int _checkIsFullTimeSeconds;
  89. /// <summary>
  90. /// 当前执行到哪一步的显示
  91. /// </summary>
  92. private string _currentStateMachine;
  93. #endregion
  94. /// <summary>
  95. /// 构造函数
  96. /// </summary>
  97. /// <param name="module"></param>
  98. public RinseFirstStepRoutine(string module) : base(module)
  99. {
  100. }
  101. /// <summary>
  102. /// 启动
  103. /// </summary>
  104. /// <param name="objects"></param>
  105. /// <returns></returns>
  106. public RState Start(params object[] objects)
  107. {
  108. _device = DEVICE.GetDevice<RinseDevice>(Module);
  109. _recipe = objects[0] as QdrRecipe;
  110. _concurrentFillTimeSeconds = SC.GetValue<int>("QDR.ConcurrentFillTimeSeconds");
  111. _fillingStartedDelta = SC.GetValue<double>("QDR.FillingStartedDelta");
  112. _sensorReadingFull = SC.GetValue<int>("QDR.SensorReadingFull");
  113. _sensorReadingEmpty = SC.GetValue<int>("QDR.SensorReadingEmpty");
  114. _normalDrainTimeSeconds = SC.GetValue<int>("QDR.NominalDrainTimeSeconds");
  115. _checkIsFillingTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillWaterTimeSeconds");
  116. _checkIsFullTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillFullTimeSeconds");
  117. _fillingDetectStartWaterLevel = 0;
  118. //配置项规范性验证
  119. if (_checkIsFillingTimeSeconds + _checkIsFullTimeSeconds > _concurrentFillTimeSeconds)
  120. {
  121. NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalCheckFillWaterTimeSeconds' plus 'QDR.NominalCheckFillFullTimeSeconds' is large than QDR.ConcurrentFillTimeSeconds",-1);
  122. return RState.Failed;
  123. }
  124. if (_normalDrainTimeSeconds > _recipe.DumpTimeSeconds)
  125. {
  126. NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalDrainTimeSeconds' is large than 'recipe.DumpTimeSeconds",-1);
  127. return RState.Failed;
  128. }
  129. return Runner.Start(Module, "Start Rinse First Step");
  130. }
  131. /// <summary>
  132. /// Abort
  133. /// </summary>
  134. public void Abort()
  135. {
  136. Runner.Stop("Manual abort");
  137. }
  138. /// <summary>
  139. /// 监控
  140. /// </summary>
  141. /// <returns></returns>
  142. public RState Monitor()
  143. {
  144. _currentStateMachine = Runner.CurrentStep.ToString();
  145. _device.UpdateStateMachine(_currentStateMachine);
  146. //1.2-Start
  147. Runner.Run(RinseFirstStep.StartPrepare,StartPrepareAction, _delay_1ms)
  148. //1.3-WatiDrained
  149. .Run(RinseFirstStep.FirstDrain,OpenDrainValveandCheckMetalValve, _delay_1ms)
  150. .RunDelay(RinseFirstStep.CheckDrain, CheckWaterLevelEmpty, _normalDrainTimeSeconds*1000)
  151. //1.4-ExtraDrainDeylay
  152. .RunIf(RinseFirstStep.WaitDrianEmpty, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0, NullFun ,(_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000)
  153. //1.5-N2PreCharge
  154. .RunIf(RinseFirstStep.N2BubbleOn, _recipe.Step1N2BubbleOn, N2ValveOn, _delay_1ms)
  155. .RunIf(RinseFirstStep.N2BubbleOnDelay, _recipe.Step1N2BubbleOn, NullFun, _recipe.N2ChargeTimeSeconds*1000)
  156. //1.6-StartFirstRinseCylce
  157. .LoopStart(RinseFirstStep.Recipe_StartFirstRinseCycle, "Rinse first step", _recipe.Step1NumberOfRinse, PrepareStart, _delay_1ms)
  158. //1.7-PerformFirstRinseCycle
  159. .LoopRun(RinseFirstStep.Recipe_PerformFirstRinseCycle,OpenN2ValveAndCloseDumpValve,_delay_1ms)
  160. //1.8-FirstRinseCycleStartFilling
  161. .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleStartFilling, () => _device.FillValveOn(), _delay_1ms)
  162. .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleRecordStartWaterLevel, CheckFillValveOn, _delay_1ms)
  163. .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleStartFillingWait, CheckFillNormalStatus, _checkIsFillingTimeSeconds * 1000)
  164. //1.9-FirstRinseCycleWaitFillingDetected and 2.0-FirstRinseCycleWaitFull
  165. .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleWaitFillingDetected, CheckFillFullStatus, _checkIsFullTimeSeconds * 1000)
  166. //2.1-FirstRinseCycleWaitEndFillTime
  167. .LoopDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitEndFillTime, (_concurrentFillTimeSeconds - _checkIsFillingTimeSeconds- _checkIsFullTimeSeconds) * 1000)
  168. //2.2-FirstRinseCycleWaitDwell
  169. .LoopRunDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitDwell, StartDwell, _recipe.Step1DwellTimeSeconds * 1000)
  170. //2.3-FirstRinseCycleWaitDrain
  171. .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleWaitDrain, StartOpenDumpValve,_delay_1ms)
  172. .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleCheckDrain,CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000)
  173. //2.4-FirstRinseCycleWaitDrainExtraTime
  174. .LoopRunIf(RinseFirstStep.Recipe_FirstRinseCycleWaitDrainExtraTime, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0,NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000 )
  175. .LoopEnd(RinseFirstStep.Recipe_FirstRinseCycleEnd, NullFun, _delay_1ms)
  176. .End(RinseFirstStep.Recipe_FirstRinseCycleComplete, NullFun, _delay_1ms);
  177. return Runner.Status;
  178. }
  179. /// <summary>
  180. /// Close Fill valve 和 Clamp valve
  181. /// </summary>
  182. /// <returns></returns>
  183. private bool StartPrepareAction()
  184. {
  185. bool result = _device.FillValveOff();
  186. if (!result)
  187. {
  188. NotifyError(eEvent.ERR_RINSE, "Close Fill Valve error",0);
  189. return false;
  190. }
  191. result = _device.WaferHolderClampValveOn();
  192. if (!result)
  193. {
  194. NotifyError(eEvent.ERR_RINSE, "Open Clamp Valve error", 0);
  195. return false;
  196. }
  197. return result;
  198. }
  199. /// <summary>
  200. /// 打开排水阀并且检查是否需要打开metal drain valve
  201. /// </summary>
  202. /// <returns></returns>
  203. private bool OpenDrainValveandCheckMetalValve()
  204. {
  205. bool result = _device.DrainValveOn();
  206. if (!result)
  207. {
  208. NotifyError(eEvent.ERR_RINSE, "Open Drain Valve error",0);
  209. return false;
  210. }
  211. if (_recipe.Step1NumberOfDumpToMetalDrain > 0)
  212. {
  213. result = _device.WasteValveOff();
  214. if (!result)
  215. {
  216. NotifyError(eEvent.ERR_RINSE, "Open Metal Valve error", 0);
  217. return false;
  218. }
  219. }
  220. return result;
  221. }
  222. /// <summary>
  223. /// N2 Valve On
  224. /// </summary>
  225. /// <returns></returns>
  226. private bool N2ValveOn()
  227. {
  228. return _device.N2ValveOn();
  229. }
  230. /// <summary>
  231. /// 检验N2Valve on
  232. /// </summary>
  233. /// <returns></returns>
  234. private bool CheckN2ValveOn()
  235. {
  236. return _device.RinseData.N2Valve;
  237. }
  238. /// <summary>
  239. /// 准备启动
  240. /// </summary>
  241. /// <returns></returns>
  242. private bool PrepareStart()
  243. {
  244. if (_recipe.Step1N2BubbleOn)
  245. {
  246. return _device.N2ValveOff();
  247. }
  248. return true;
  249. }
  250. /// <summary>
  251. /// 启动N2和关闭Dump Valve
  252. /// </summary>
  253. /// <returns></returns>
  254. private bool OpenN2ValveAndCloseDumpValve()
  255. {
  256. bool result = true;
  257. if(_recipe.Step1N2BubbleOn)
  258. {
  259. result = _device.N2ValveOn();
  260. if(!result)
  261. {
  262. NotifyError(eEvent.ERR_RINSE, "Open N2 Valve error",0);
  263. return false;
  264. }
  265. }
  266. result = _device.DrainValveOff();
  267. if(!result)
  268. {
  269. NotifyError(eEvent.ERR_RINSE, "Close Dump Valve error", 0);
  270. }
  271. return result;
  272. }
  273. /// <summary>
  274. /// 检验Fill Valve打开状态
  275. /// </summary>
  276. /// <returns></returns>
  277. private bool CheckFillValveOn()
  278. {
  279. _startFillTime = DateTime.Now;
  280. _fillingDetectStartWaterLevel = _device.RinseData.WaterLevel;
  281. return true;
  282. }
  283. /// <summary>
  284. /// 检验是否正常流水
  285. /// </summary>
  286. /// <returns></returns>
  287. private bool CheckFillNormalStatus()
  288. {
  289. double currentWaterLevel = _device.RinseData.WaterLevel;
  290. bool result =(currentWaterLevel-_fillingDetectStartWaterLevel)>_fillingStartedDelta;
  291. return result;
  292. }
  293. /// <summary>
  294. /// 检验是否注满
  295. /// </summary>
  296. /// <returns></returns>
  297. private bool CheckFillFullStatus()
  298. {
  299. double currentWaterLevel = _device.RinseData.WaterLevel;
  300. bool result= currentWaterLevel > _sensorReadingFull;
  301. return result;
  302. }
  303. /// <summary>
  304. /// 开始Dwell
  305. /// </summary>
  306. /// <returns></returns>
  307. private bool StartDwell()
  308. {
  309. bool result = _device.FillValveOff();
  310. if(!result)
  311. {
  312. NotifyError(eEvent.ERR_RINSE, "Fill Valve off error",0);
  313. return false;
  314. }
  315. if(_recipe.Step1N2BubbleOn)
  316. {
  317. result = _device.N2ValveOff();
  318. if(!result)
  319. {
  320. NotifyError(eEvent.ERR_RINSE, "N2 Valve off error", 0);
  321. return false;
  322. }
  323. }
  324. return true;
  325. }
  326. /// <summary>
  327. /// 打开Dump Valve
  328. /// </summary>
  329. /// <returns></returns>
  330. private bool StartOpenDumpValve()
  331. {
  332. CheckNeedCloseMetalDrain();
  333. bool result = _device.DrainValveOn();
  334. if(!result)
  335. {
  336. NotifyError(eEvent.ERR_RINSE, "Open Dump valve error",0);
  337. return false;
  338. }
  339. return result;
  340. }
  341. /// <summary>
  342. /// 检验快排是否排空
  343. /// </summary>
  344. /// <returns></returns>
  345. private bool CheckWaterLevelEmpty()
  346. {
  347. double currentWaterLevel = _device.RinseData.WaterLevel;
  348. bool reseult = currentWaterLevel < _sensorReadingEmpty;
  349. if (!reseult)
  350. {
  351. NotifyError(eEvent.ERR_RINSE, $"current water level: {currentWaterLevel} is large than sensorReadingEmpty: {_sensorReadingEmpty}", 0);
  352. }
  353. return reseult;
  354. }
  355. /// <summary>
  356. /// 检验是否需要关闭Metal Valve20
  357. /// </summary>
  358. /// <returns></returns>
  359. private void CheckNeedCloseMetalDrain()
  360. {
  361. if (Runner.LoopCounter + 1>_recipe.Step1NumberOfDumpToMetalDrain)
  362. {
  363. bool result = _device.WasteValveOn();
  364. if (!result)
  365. {
  366. NotifyError(eEvent.ERR_RINSE, "Close Metal Drain Valve error", 0);
  367. }
  368. }
  369. }
  370. }
  371. }