PMMfcVerificationRoutine.cs 14 KB

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