PMMfcVerificationRoutine.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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 Aitex.Core.RT.Device.Unit;
  14. using JetVirgoPM.Devices;
  15. using MECF.Framework.Common.Routine;
  16. namespace JetVirgoPM.PMs.Routines
  17. {
  18. public enum VerifyMode
  19. {
  20. OnePoint,
  21. TenPoint,
  22. }
  23. class PMMfcVerificationRoutine : PMRoutineBase, IStepRoutine
  24. {
  25. enum RoutineStep
  26. {
  27. CheckNeedPumpDown1,
  28. CheckNeedPumpDown2,
  29. RunPumpRoutine1,
  30. RunPumpRoutine2,
  31. RunPumpRoutine3,
  32. CheckThrottleValveStatus,
  33. ClosePumpValve,
  34. GetBeginPressure,
  35. SetGasFlow,
  36. CalcMfcCalibration,
  37. Delay1,
  38. Delay2,
  39. StopGasFlow,
  40. CheckFinished,
  41. Loop,
  42. EndLoop,
  43. CheckFlowStable,
  44. End,
  45. }
  46. private readonly PumpDownRoutine _pumpdownRoutine;
  47. private int _paramContinuePumpTime;
  48. private double _beginPressure;
  49. private double _endPressure;
  50. private double _elapsedTime;
  51. private DeviceTimer _verificationDeviceTimer = new DeviceTimer();
  52. private int _mfcIndex;
  53. private float _mfcFlow;
  54. private double _flowTime;
  55. private double _mfcActualFlow;
  56. private double _getBeginPressureDelayTime;
  57. private double _maxPressure;
  58. private MfcBase1 _mfcDevice;
  59. private VerifyMode _paramMode;
  60. private Dictionary<int, float> _paramFlowSet = new Dictionary<int, float>();
  61. private Dictionary<float, Tuple<float, float>> _calibrationResult = new Dictionary<float, Tuple<float, float>>();
  62. private bool _isPumpDownNeed;
  63. private float _pressureStableTolerance = 2;//2mTorr
  64. private float _flowStableTolerance = 0.02f;//2%
  65. private int _stableTime = 1;//1s
  66. private double _chamberVolume;
  67. private double _gasTemperature;
  68. private double _leakRate;
  69. private double _maxDeviation;
  70. private int _pumpBasePressure;
  71. public PMMfcVerificationRoutine(JetDualPM chamber, PumpDownRoutine pumpDownRoutine) : base(chamber)
  72. {
  73. Name = "MFC Verification";
  74. bUINotify = true;
  75. _pumpdownRoutine = pumpDownRoutine;
  76. }
  77. internal void Init(string mfc, double flow, int flowCount)
  78. {
  79. int.TryParse(mfc.Replace("MFC",""), out _mfcIndex);
  80. _mfcDevice = DEVICE.GetDevice<MfcBase1>($"{Module}.MfcGas{_mfcIndex}");
  81. _mfcIndex -= 1;//start from 0
  82. _mfcFlow = (float)flow;
  83. if (flowCount == 10)
  84. _paramMode = VerifyMode.TenPoint;
  85. else
  86. _paramMode = VerifyMode.OnePoint;
  87. }
  88. public RState Start(params object[] objs)
  89. {
  90. Reset();
  91. if(CheckLid() != RState.Running)
  92. {
  93. return RState.Failed;
  94. }
  95. if (CheckSlitDoor1() != RState.Running)
  96. {
  97. return RState.Failed;
  98. }
  99. if (CheckSlitDoor2() != RState.Running)
  100. {
  101. return RState.Failed;
  102. }
  103. if (CheckDryPump() != RState.Running)
  104. {
  105. return RState.Failed;
  106. }
  107. _calibrationResult.Clear();
  108. _paramFlowSet.Clear();
  109. _chamberVolume = SC.GetValue<double>($"{Module}.MFCVerification.ChamberVolume");
  110. _gasTemperature = SC.GetValue<double>($"{Module}.MFCVerification.GasTemperature");
  111. _flowTime = SC.GetValue<double>($"{Module}.MFCVerification.GasFlowTime");
  112. _maxDeviation = SC.GetValue<double>($"{Module}.MFCVerification.MaxDeviation");
  113. _paramContinuePumpTime = 20;//20s
  114. _getBeginPressureDelayTime = 2;//2s
  115. _pressureStableTolerance = (float)SC.GetValue<double>($"{Module}.MFCVerification.PressureStableTolerance");
  116. _flowStableTolerance = (float)(SC.GetValue<double>($"{Module}.MFCVerification.FlowStableTolerance") / 100.0);
  117. _stableTime = 1;//1s
  118. _maxPressure = SC.GetValue<double>($"{Module}.MFCVerification.TargetPressure");
  119. _pumpBasePressure = SC.GetValue<int>($"{Module}.Pump.PumpBasePressure");
  120. if (_paramMode == VerifyMode.TenPoint)
  121. {
  122. for (int i = 0; i < 10; i++)
  123. {
  124. _paramFlowSet.Add(i, (float)_mfcDevice.Scale * (i + 1) / 10);
  125. }
  126. }
  127. else
  128. {
  129. if (_mfcFlow <= 0 || _mfcFlow > _mfcDevice.Scale)
  130. {
  131. EV.PostWarningLog(Module, $"MFC set value {_mfcFlow} not valid");
  132. return RState.Failed;
  133. }
  134. _paramFlowSet.Add(0, _mfcFlow);
  135. }
  136. _mfcDevice.ResetVerificationData();
  137. _isPumpDownNeed = true;
  138. _leakRate = 0;
  139. var dbData = DataQuery.Query($"SELECT * FROM \"leak_check_data\" where \"module_name\" = '{Module}' order by \"operate_time\" DESC;");
  140. if (dbData != null && dbData.Rows.Count > 0 && !dbData.Rows[0]["leak_rate"].Equals(DBNull.Value))
  141. {
  142. _leakRate = Convert.ToDouble(dbData.Rows[0]["leak_rate"]);
  143. }
  144. return Runner.Start(_chamber.Module.ToString(), Name);
  145. }
  146. public RState Monitor()
  147. {
  148. Runner.Run(RoutineStep.RunPumpRoutine1, StartPump, CheckPump)
  149. .Run(RoutineStep.CheckThrottleValveStatus, FullOpenTV, CheckFullOpenTV, _delay_20s)
  150. .LoopStart(RoutineStep.CheckNeedPumpDown1, "", _paramFlowSet.Count, CheckNeedPumpDown, _delay_50ms) //抽到底压
  151. .LoopRun(RoutineStep.RunPumpRoutine2, StartPump, CheckPump)
  152. .LoopRun(RoutineStep.SetGasFlow, SetGasFlow, _delay_50ms) //流气
  153. .LoopDelay(RoutineStep.Delay1, _paramContinuePumpTime * 1000) //等待,稳定一下
  154. .LoopRun(RoutineStep.CheckFlowStable, FlowStable, CheckFlowStable, _stableTime * 2 * 1000) //检查Stable
  155. .LoopRun(RoutineStep.ClosePumpValve, ClosePumpValve, CheckClosePumpValve, 500) //关闭抽气阀
  156. .LoopDelay(RoutineStep.Delay2, (int)_getBeginPressureDelayTime * 1000) //稳压
  157. .LoopRun(RoutineStep.GetBeginPressure, GetBeginPressure, _delay_50ms)
  158. .LoopRun(RoutineStep.CheckFinished, ChamberPressure, CheckChamberPressure, (int)_flowTime * 2 * 1000) //等待,流气时间或者压力到设定值
  159. .LoopRun(RoutineStep.CalcMfcCalibration, CalcMfcCalibration, _delay_50ms) //计算Flow
  160. .LoopRun(RoutineStep.StopGasFlow, StopGasFlow, _delay_1s)
  161. .LoopEnd(RoutineStep.EndLoop, NullFun, _delay_1s)
  162. .Run(RoutineStep.CheckNeedPumpDown2, CheckNeedPumpDown, _delay_50ms)
  163. .Run(RoutineStep.RunPumpRoutine3, StartPump, CheckPump)
  164. .End(RoutineStep.End, NullFun, _delay_50ms);
  165. if (Runner.Status == RState.Failed)
  166. {
  167. _verificationDeviceTimer.Stop();
  168. _chamber.StopAllGases();
  169. _chamber.OpenValve(ValveType.PROCESS, false);
  170. _chamber.OpenValve(ValveType.PURGE, false);
  171. _mfcDevice.ResetVerificationData();
  172. }
  173. return Runner.Status;
  174. }
  175. public bool StartPump()
  176. {
  177. if(!_isPumpDownNeed)
  178. {
  179. return true;
  180. }
  181. return _pumpdownRoutine.Start() == RState.Running;
  182. }
  183. bool CheckPump()
  184. {
  185. if (!_isPumpDownNeed)
  186. {
  187. Notify($"{_chamber.Name} 无需设置 Pump ");
  188. return true;
  189. }
  190. var result = _pumpdownRoutine.Monitor();
  191. if (result == RState.Failed || result == RState.Timeout)
  192. {
  193. Runner.Stop($"设置 Pump {_chamber.Name} failed ");
  194. return true;
  195. }
  196. return result == RState.End;
  197. }
  198. private bool ClosePumpValve()
  199. {
  200. _chamber.OpenValve(ValveType.FAST_PUMP, false);
  201. Notify($"关闭 {ValveType.FAST_PUMP} 阀");
  202. return true;
  203. }
  204. private bool CheckClosePumpValve()
  205. {
  206. return !_chamber.IsFastPumpOpened;
  207. }
  208. public new void Abort()
  209. {
  210. _verificationDeviceTimer.Stop();
  211. _chamber.StopAllGases();
  212. _chamber.OpenValve(ValveType.PROCESS, false);
  213. _chamber.OpenValve(ValveType.PURGE, false);
  214. _mfcDevice.ResetVerificationData();
  215. }
  216. private bool CheckNeedPumpDown()
  217. {
  218. Notify($"Check {Module} need pump down");
  219. _isPumpDownNeed = _chamber.ChamberPressure > _pumpBasePressure;
  220. return true;
  221. }
  222. private bool SetGasFlow()
  223. {
  224. var flow = _paramMode == VerifyMode.TenPoint ? _paramFlowSet[Runner.LoopCounter] : _mfcFlow;
  225. Notify($"Set gas {_mfcIndex} flow to {flow} sccm");
  226. _chamber.OpenValve(ValveType.PROCESS, true);
  227. _chamber.OpenValve(ValveType.PURGE, true);
  228. if (!_chamber.FlowGas(_mfcIndex, flow))
  229. {
  230. return false;
  231. }
  232. return true;
  233. }
  234. private bool StopGasFlow()
  235. {
  236. Notify($"Stop gas {_mfcIndex} flow");
  237. _chamber.OpenValve(ValveType.PROCESS, false);
  238. _chamber.OpenValve(ValveType.PURGE, false);
  239. if (!_chamber.FlowGas(_mfcIndex, 0))
  240. {
  241. return false;
  242. }
  243. return true;
  244. }
  245. private bool CalcMfcCalibration()
  246. {
  247. var flow = _paramMode == VerifyMode.TenPoint ? _paramFlowSet[Runner.LoopCounter] : _mfcFlow;
  248. _mfcActualFlow = 273.15 * _chamberVolume / ((273.15 + _gasTemperature) * 760000) * ((_endPressure - _beginPressure) / _elapsedTime - _leakRate);
  249. EV.PostInfoLog(Module, $"Calculate flow: calculate flow={_mfcActualFlow}, setpoint={flow}, begin pressure(torr)={_beginPressure:f3}, end pressure(torr)={_endPressure:f3}," +
  250. $"elapsed time(minute)={_elapsedTime:f3}");
  251. double deviation = (Math.Abs(_mfcActualFlow) - Math.Abs(flow)) / Math.Abs(flow) * 100;
  252. bool isOk = Math.Abs(deviation) <= Math.Abs(_maxDeviation);
  253. if (!isOk)
  254. {
  255. EV.PostWarningLog(Module, $"MFC {_mfcDevice.DisplayName} verify failed, deviation is {deviation}%, exceed max tolerance {_maxDeviation}%");
  256. }
  257. if (_paramMode == VerifyMode.TenPoint)
  258. {
  259. _calibrationResult[flow] = Tuple.Create((float)_mfcActualFlow, (float)_elapsedTime);
  260. _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, _calibrationResult.Count == 10, _elapsedTime * 60, deviation, isOk);
  261. }
  262. else
  263. {
  264. _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, true, _elapsedTime * 60, deviation, isOk);
  265. }
  266. return true;
  267. }
  268. private bool GetBeginPressure()
  269. {
  270. Notify($"Get begin pressure {_chamber.ChamberPressure.ToString("f1")}");
  271. _beginPressure = _chamber.ChamberPressure;
  272. _verificationDeviceTimer.Start(0);
  273. return true;
  274. }
  275. private bool FlowStable()
  276. {
  277. Notify($"Check {_mfcDevice.Name} flow stable");
  278. _verificationDeviceTimer.Start(0);
  279. _beginPressure = _chamber.ChamberPressure;
  280. return true;
  281. }
  282. bool CheckFlowStable()
  283. {
  284. if (_verificationDeviceTimer.GetElapseTime() > _stableTime * 1000 && Math.Abs(_chamber.ChamberPressure - _beginPressure) <= _pressureStableTolerance &&
  285. Math.Abs(_mfcDevice.SetPoint - _mfcDevice.FeedBack) / _mfcDevice.SetPoint < _flowStableTolerance)
  286. {
  287. return true;
  288. }
  289. return false;
  290. }
  291. private bool ChamberPressure()
  292. {
  293. Notify($"Check finished one point");
  294. return true;
  295. }
  296. bool CheckChamberPressure()
  297. {
  298. if (_verificationDeviceTimer.GetElapseTime() > _flowTime * 1000 || _chamber.ChamberPressure / 1000 > _maxPressure)
  299. {
  300. _endPressure = _chamber.ChamberPressure;//mTorr
  301. _elapsedTime = _verificationDeviceTimer.GetElapseTime() / (1000 * 60);//unit minutes
  302. return true;
  303. }
  304. return false;
  305. }
  306. }
  307. }