PMMfcVerificationRoutine.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Event;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using MECF.Framework.Common.DBCore;
  7. using System;
  8. using System.Collections.Generic;
  9. using VirgoRT.Devices;
  10. using VirgoRT.Devices.IODevices;
  11. namespace VirgoRT.Modules.PMs
  12. {
  13. public enum VerifyMode
  14. {
  15. OnePoint,
  16. TenPoint,
  17. }
  18. class PMMfcVerificationRoutine : PMRoutineBase, IRoutine
  19. {
  20. enum RoutineStep
  21. {
  22. CheckNeedPumpDown1,
  23. CheckNeedPumpDown2,
  24. RunPumpRoutine1,
  25. RunPumpRoutine2,
  26. RunPumpRoutine3,
  27. CheckThrottleValveStatus,
  28. ClosePumpValve,
  29. GetBeginPressure,
  30. SetGasFlow,
  31. CalcMfcCalibration,
  32. Delay1,
  33. Delay2,
  34. StopGasFlow,
  35. CheckFinished,
  36. Loop,
  37. EndLoop,
  38. CheckFlowStable,
  39. }
  40. private readonly PumpDownRoutine _pumpdownRoutine;
  41. private int _paramContinuePumpTime;
  42. private double _beginPressure;
  43. private double _endPressure;
  44. private double _elapsedTime;
  45. private DeviceTimer _verificationDeviceTimer = new DeviceTimer();
  46. private int _mfcIndex;
  47. private float _mfcFlow;
  48. private double _flowTime;
  49. private double _mfcActualFlow;
  50. private double _getBeginPressureDelayTime;
  51. private double _maxPressure;
  52. private MfcBase1 _mfcDevice;
  53. private VerifyMode _paramMode;
  54. private Dictionary<int, float> _paramFlowSet = new Dictionary<int, float>();
  55. private Dictionary<float, Tuple<float, float>> _calibrationResult = new Dictionary<float, Tuple<float, float>>();
  56. private bool _isPumpDownNeed;
  57. private float _pressureStableTolerance = 2;//2mTorr
  58. private float _flowStableTolerance = 0.02f;//2%
  59. private int _stableTime = 1;//1s
  60. private double _chamberVolume;
  61. private double _gasTemperature;
  62. private double _leakRate;
  63. private double _maxDeviation;
  64. public PMMfcVerificationRoutine(JetPM chamber, PumpDownRoutine pumpDownRoutine) : base(chamber)
  65. {
  66. Name = "MFC Verification";
  67. bUINotify = true;
  68. _pumpdownRoutine = pumpDownRoutine;
  69. }
  70. internal void Init(string mfc, double flow, int flowCount)
  71. {
  72. int.TryParse(mfc.Replace("MFC", ""), out _mfcIndex);
  73. _mfcDevice = DEVICE.GetDevice<MfcBase1>($"{Module}.MfcGas{_mfcIndex}");
  74. _mfcIndex -= 1;//start from 0
  75. _mfcFlow = (float)flow;
  76. if (flowCount == 10)
  77. _paramMode = VerifyMode.TenPoint;
  78. else
  79. _paramMode = VerifyMode.OnePoint;
  80. }
  81. public Result Start(params object[] objs)
  82. {
  83. Reset();
  84. if (CheckLid() != Result.RUN)
  85. {
  86. return Result.FAIL;
  87. }
  88. if (CheckSlitDoor() != Result.RUN)
  89. {
  90. return Result.FAIL;
  91. }
  92. if (CheckDryPump() != Result.RUN)
  93. {
  94. return Result.FAIL;
  95. }
  96. _calibrationResult.Clear();
  97. _paramFlowSet.Clear();
  98. _chamberVolume = SC.GetValue<double>($"{Module}.MFCVerification.ChamberVolume");
  99. _gasTemperature = SC.GetValue<double>($"{Module}.MFCVerification.GasTemperature");
  100. _flowTime = SC.GetValue<double>($"{Module}.MFCVerification.GasFlowTime");
  101. _maxDeviation = SC.GetValue<double>($"{Module}.MFCVerification.MaxDeviation");
  102. _paramContinuePumpTime = 20;//20s
  103. _getBeginPressureDelayTime = 2;//2s
  104. _pressureStableTolerance = (float)SC.GetValue<double>($"{Module}.MFCVerification.PressureStableTolerance");
  105. _flowStableTolerance = (float) (SC.GetValue<double>($"{Module}.MFCVerification.FlowStableTolerance") / 100.0);
  106. _stableTime = 1;//1s
  107. _maxPressure = SC.GetValue<double>($"{Module}.MFCVerification.TargetPressure");
  108. if (_paramMode == VerifyMode.TenPoint)
  109. {
  110. for (int i = 0; i < 10; i++)
  111. {
  112. _paramFlowSet.Add(i, (float)_mfcDevice.Scale * (i + 1) / 10);
  113. }
  114. }
  115. else
  116. {
  117. if (_mfcFlow <= 0 || _mfcFlow > _mfcDevice.Scale)
  118. {
  119. EV.PostWarningLog(Module, $"MFC set value {_mfcFlow} not valid");
  120. return Result.FAIL;
  121. }
  122. _paramFlowSet.Add(0, _mfcFlow);
  123. }
  124. _mfcDevice.ResetVerificationData();
  125. _isPumpDownNeed = true;
  126. _leakRate = 0;
  127. var dbData = DataQuery.Query($"SELECT * FROM \"leak_check_data\" where \"module_name\" = '{Module}' order by \"operate_time\" DESC;");
  128. if (dbData != null && dbData.Rows.Count > 0 && !dbData.Rows[0]["leak_rate"].Equals(DBNull.Value))
  129. {
  130. _leakRate = Convert.ToDouble(dbData.Rows[0]["leak_rate"]);
  131. }
  132. return Result.RUN;
  133. }
  134. public Result Monitor()
  135. {
  136. try
  137. {
  138. if (_isPumpDownNeed)
  139. {
  140. ExecuteRoutine((int)RoutineStep.RunPumpRoutine1, _pumpdownRoutine);
  141. }
  142. CheckThrottleValveFullOpen((int)RoutineStep.CheckThrottleValveStatus);
  143. StartLoop((int)RoutineStep.Loop, "", _paramFlowSet.Count, Notify, Stop);
  144. //抽到底压
  145. CheckNeedPumpDown((int)RoutineStep.CheckNeedPumpDown1);
  146. if (_isPumpDownNeed)
  147. {
  148. ExecuteRoutine((int)RoutineStep.RunPumpRoutine2, _pumpdownRoutine);
  149. }
  150. //流气
  151. SetGasFlow((int)RoutineStep.SetGasFlow, _mfcIndex, _paramMode == VerifyMode.TenPoint ? _paramFlowSet[LoopCounter] : _mfcFlow);
  152. //等待,稳定一下
  153. Delay((int)RoutineStep.Delay1, _paramContinuePumpTime);
  154. //检查Stable
  155. CheckFlowStable((int)RoutineStep.CheckFlowStable, _mfcDevice, _flowStableTolerance, _pressureStableTolerance, _stableTime);
  156. //关闭抽气阀
  157. SetValve((int)RoutineStep.ClosePumpValve, ValveType.FAST_PUMP, false);
  158. //稳压
  159. Delay((int)RoutineStep.Delay2, _getBeginPressureDelayTime);
  160. //得到初始压力值
  161. GetBeginPressure((int)RoutineStep.GetBeginPressure);
  162. //等待,流气时间或者压力到设定值
  163. CheckFinished((int)RoutineStep.CheckFinished, _flowTime, _maxPressure);
  164. //计算Flow
  165. CalcMfcCalibration((int)RoutineStep.CalcMfcCalibration, _paramMode == VerifyMode.TenPoint ? _paramFlowSet[LoopCounter] : _mfcFlow);
  166. StopGasFlow((int)RoutineStep.StopGasFlow, _mfcIndex);
  167. EndLoop((int)RoutineStep.EndLoop, Notify, Stop);
  168. CheckNeedPumpDown((int)RoutineStep.CheckNeedPumpDown2);
  169. if (_isPumpDownNeed)
  170. {
  171. ExecuteRoutine((int)RoutineStep.RunPumpRoutine3, _pumpdownRoutine);
  172. }
  173. }
  174. catch (RoutineBreakException)
  175. {
  176. return Result.RUN;
  177. }
  178. catch (RoutineFaildException)
  179. {
  180. _verificationDeviceTimer.Stop();
  181. _chamber.StopAllGases();
  182. _chamber.SetValveOnOff(ValveType.PROCESS, false);
  183. _mfcDevice.ResetVerificationData();
  184. return Result.FAIL;
  185. }
  186. return Result.DONE;
  187. }
  188. public new void Abort()
  189. {
  190. _verificationDeviceTimer.Stop();
  191. _chamber.StopAllGases();
  192. _chamber.SetValveOnOff(ValveType.PROCESS, false);
  193. _mfcDevice.ResetVerificationData();
  194. }
  195. private void CheckNeedPumpDown(int id)
  196. {
  197. string reason = string.Empty;
  198. Tuple<bool, Result> ret = Execute(id, () =>
  199. {
  200. Notify($"Check {Module} need pump down");
  201. _isPumpDownNeed = _chamber.ChamberPressure > SC.GetValue<int>($"{Module}.Pump.PumpBasePressure");
  202. return true;
  203. });
  204. if (ret.Item1)
  205. {
  206. if (ret.Item2 == Result.FAIL)
  207. {
  208. throw (new RoutineFaildException());
  209. }
  210. else
  211. throw (new RoutineBreakException());
  212. }
  213. }
  214. private void SetGasFlow(int id, int mfcId, double flow)
  215. {
  216. string reason = string.Empty;
  217. Tuple<bool, Result> ret = Execute(id, () =>
  218. {
  219. Notify($"Set gas {mfcId} flow to {flow} sccm");
  220. _chamber.SetValveOnOff(ValveType.PROCESS, true);
  221. if (!_chamber.FlowGas(mfcId, flow))
  222. {
  223. return false;
  224. }
  225. return true;
  226. });
  227. if (ret.Item1)
  228. {
  229. if (ret.Item2 == Result.FAIL)
  230. {
  231. Stop($"Set gas {mfcId} flow to {flow} sccm failed, for {reason}");
  232. throw (new RoutineFaildException());
  233. }
  234. else
  235. throw (new RoutineBreakException());
  236. }
  237. }
  238. private void StopGasFlow(int id, int mfcId)
  239. {
  240. string reason = string.Empty;
  241. Tuple<bool, Result> ret = Execute(id, () =>
  242. {
  243. Notify($"Stop gas {mfcId} flow");
  244. _chamber.SetValveOnOff(ValveType.PROCESS, false);
  245. if (!_chamber.FlowGas(mfcId, 0))
  246. {
  247. return false;
  248. }
  249. return true;
  250. });
  251. if (ret.Item1)
  252. {
  253. if (ret.Item2 == Result.FAIL)
  254. {
  255. Stop($"Stop gas {mfcId} flow failed, for {reason}");
  256. throw (new RoutineFaildException());
  257. }
  258. else
  259. throw (new RoutineBreakException());
  260. }
  261. }
  262. private void CalcMfcCalibration(int id, float flow)
  263. {
  264. Tuple<bool, Result> ret = Execute(id, () =>
  265. {
  266. _mfcActualFlow = 273.15 * _chamberVolume / ((273.15 + _gasTemperature) * 760000) * ((_endPressure - _beginPressure) / _elapsedTime - _leakRate);
  267. EV.PostInfoLog(Module, $"Calculate flow: calculate flow={_mfcActualFlow}, setpoint={flow}, begin pressure(torr)={_beginPressure:f3}, end pressure(torr)={_endPressure:f3}," +
  268. $"elapsed time(minute)={_elapsedTime:f3}");
  269. double deviation = (Math.Abs(_mfcActualFlow) - Math.Abs(flow)) / Math.Abs(flow) * 100;
  270. bool isOk = Math.Abs(deviation) <= Math.Abs(_maxDeviation);
  271. if (!isOk)
  272. {
  273. EV.PostWarningLog(Module, $"MFC {_mfcDevice.DisplayName} verify failed, deviation is {deviation}%, exceed max tolerance {_maxDeviation}%");
  274. }
  275. if (_paramMode == VerifyMode.TenPoint)
  276. {
  277. _calibrationResult[flow] = Tuple.Create((float)_mfcActualFlow, (float)_elapsedTime);
  278. _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, _calibrationResult.Count == 10, _elapsedTime*60, deviation, isOk);
  279. }
  280. else
  281. {
  282. _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, true, _elapsedTime*60, deviation, isOk);
  283. }
  284. return true;
  285. });
  286. }
  287. private void GetBeginPressure(int id)
  288. {
  289. Tuple<bool, Result> ret = Execute(id, () =>
  290. {
  291. Notify($"Get begin pressure {_chamber.ChamberPressure.ToString("f1")}");
  292. _beginPressure = _chamber.ChamberPressure;
  293. _verificationDeviceTimer.Start(0);
  294. return true;
  295. });
  296. }
  297. private void CheckFlowStable(int id, MfcBase1 mfc, float flowStable, float pressureStable, int time)
  298. {
  299. Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
  300. {
  301. Notify($"Check {mfc.Name} flow stable");
  302. _verificationDeviceTimer.Start(0);
  303. _beginPressure = _chamber.ChamberPressure;
  304. return true;
  305. }, () =>
  306. {
  307. if (_verificationDeviceTimer.GetElapseTime() > time * 1000 && Math.Abs(_chamber.ChamberPressure - _beginPressure) <= pressureStable &&
  308. Math.Abs(mfc.SetPoint - mfc.FeedBack) / mfc.SetPoint < flowStable)
  309. {
  310. return true;
  311. }
  312. return false;
  313. }, time * 2 * 1000);
  314. if (ret.Item1)
  315. {
  316. if (ret.Item2 == Result.FAIL)
  317. {
  318. Stop($"Check {mfc.Name} flow {mfc.SetPoint} stable failed.");
  319. throw (new RoutineFaildException());
  320. }
  321. else if (ret.Item2 == Result.TIMEOUT) //timeout
  322. {
  323. Stop($"Check {mfc.Name} flow stable timeout in {time * 2} seconds");
  324. throw (new RoutineFaildException());
  325. }
  326. else
  327. throw (new RoutineBreakException());
  328. }
  329. }
  330. private void CheckFinished(int id, double flowTime, double maxPressure)
  331. {
  332. Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
  333. {
  334. Notify($"Check finished one point");
  335. return true;
  336. }, () =>
  337. {
  338. if (_verificationDeviceTimer.GetElapseTime() > flowTime * 1000 || _chamber.ChamberPressure / 1000 > maxPressure)
  339. {
  340. _endPressure = _chamber.ChamberPressure;//mTorr
  341. _elapsedTime = _verificationDeviceTimer.GetElapseTime() / (1000 * 60);//unit minutes
  342. return true;
  343. }
  344. return false;
  345. }, flowTime * 2 * 1000);
  346. if (ret.Item1)
  347. {
  348. if (ret.Item2 == Result.FAIL)
  349. {
  350. throw (new RoutineFaildException());
  351. }
  352. else if (ret.Item2 == Result.TIMEOUT) //timeout
  353. {
  354. Stop($"Check finished one point can not finished in {flowTime * 2} seconds");
  355. throw (new RoutineFaildException());
  356. }
  357. else
  358. throw (new RoutineBreakException());
  359. }
  360. }
  361. }
  362. }