using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Venus_RT.Devices; using MECF.Framework.Common.Routine; using System.Diagnostics; using Venus_Core; using System; using Venus_Unity; using MECF.Framework.Common.DBCore; namespace Venus_RT.Modules.PMs { class PMLeakCheckRoutine : PMRoutineBase, IRoutine { private enum LeakCheckStep { kPumpToBasePressure, kPumpingDelay, kLeakCheckDelay, kEnd, } public double LeakRate { get; private set; } private int _basePressure = 100; private int _leakcheckPumpTime = 180; private int _leakcheckHoldTime = 300; private double _startPressure = 0; private double _endPressure = 0; private double _leakRate = 30.0; private double _leakCheckBasePressure = 1; public string CurrentStep; private JetChamber jetChamber = JetChamber.None; Stopwatch _leakCheckTimer = new Stopwatch(); PMLeakCheckResult pMLeakCheckResult; Stopwatch _routineTimer = new Stopwatch(); PressureType _pressureType = PressureType.mTorr; private bool _readPenningGuagePressureFlag; private double _penningGuagePressure; public PMLeakCheckRoutine(JetPMBase chamber) : base(chamber) { jetChamber = (JetChamber)SC.GetValue($"{chamber.Name}.ChamberType"); Name = "PM Leakcheck"; if (chamber.ChamberType == JetChamber.Kepler2200A || chamber.ChamberType == JetChamber.Kepler2200B) { _pressureType = PressureType.Pa; } } public RState Start(params object[] objs) { if (CheckLid() && CheckSlitDoor() && CheckTurboPump()) { CurrentStep = "Pump To BasePressure"; Reset(); _basePressure = SC.GetValue($"{Module}.Pump.PumpBasePressure"); //_leakcheckPumpTime = SC.GetValue($"{Module}.Pump.LeakCheckPumpingTime"); //_leakcheckHoldTime = SC.GetValue($"{Module}.Pump.LeakCheckHoldTime"); //_leakRate = SC.GetValue($"{Module}.Pump.LeakRate"); _leakcheckPumpTime = (int)(objs[0]); _leakcheckHoldTime = (int)(objs[1]); _leakRate = (double)(objs[2]); _leakCheckBasePressure = SC.GetValue($"{Module}.Pump.LeakCheckBasePressure"); PreSetValves(); pMLeakCheckResult = new PMLeakCheckResult(); pMLeakCheckResult.CheckDate = DateTime.Now.ToString("yyyyMMddHHmm"); pMLeakCheckResult.CheckMode = "ChamberOnly"; _routineTimer.Restart(); _readPenningGuagePressureFlag = false; return Runner.Start(Module, Name); } return RState.Failed; } public RState Monitor() { Runner.Wait(LeakCheckStep.kPumpToBasePressure, PumpingToBasePressure) .Run(LeakCheckStep.kPumpingDelay, StartPumpDelay, PumpingDelay , (_leakcheckPumpTime+10)*1000) .Run(LeakCheckStep.kLeakCheckDelay, StartLeakCheck, _leakcheckHoldTime * 1000) .End(LeakCheckStep.kEnd, CalcLeakCheckResult, _delay_50ms); return Runner.Status; } public void Abort() { CloseAllValves(); } private bool PumpingToBasePressure() { if (_chamber.ProcessPressure <= _basePressure) { _leakCheckTimer.Restart(); return true; } else return false; } private bool PumpingDelay() { if (_leakCheckTimer.ElapsedMilliseconds > (_leakcheckPumpTime - 5) * 1000 && _readPenningGuagePressureFlag==false) { _penningGuagePressure = _chamber.PenningGuagePressure; pMLeakCheckResult.BasePressure = _penningGuagePressure; _readPenningGuagePressureFlag = true; } if (_leakCheckTimer.ElapsedMilliseconds >= _leakcheckPumpTime * 1000) { if (_chamber.ProcessPressure <= _leakCheckBasePressure) return true; else { Runner.Stop($"PM Leakcheck失败, 工艺压力 [{_chamber.ProcessPressure}]{_pressureType}, 高于LeakCheck Base Pressure: [{_leakCheckBasePressure}] {_pressureType}"); } } return false; } private bool StartPumpDelay() { _chamber.OpenValve(ValveType.GasFinal, false); CurrentStep = "Check Pump"; return true; } private bool StartLeakCheck() { CurrentStep = "Leak Check"; _startPressure = _chamber.ProcessPressure; pMLeakCheckResult.StartPressure = _startPressure; Notify($"PM 压力开始值 {_startPressure} {_pressureType}"); _chamber.TurnPendulumValve(false); return true; } private bool CalcLeakCheckResult() { _endPressure = _chamber.ProcessPressure; pMLeakCheckResult.EndPressure = _endPressure; LeakRate = (_endPressure - _startPressure) * 60.0 / _leakcheckHoldTime; pMLeakCheckResult.LeakRate = LeakRate; if (LeakRate < _leakRate) { Notify($"PM Leakcheck完成, 压力结束值: {_startPressure} {_pressureType}, 漏率:{LeakRate} {_pressureType}/min"); pMLeakCheckResult.Result = "Success"; } else { Stop($"PM Leakcheck失败, 腔体漏率 [{LeakRate}] {_pressureType}/min, 高于 [{_leakRate}] {_pressureType}/min"); pMLeakCheckResult.Result = "Fail"; } if (RtInstance.ConfigType == ConfigType.Kepler2200) { LeakCheckDataRecorder.AddKepler2200(_leakcheckHoldTime, pMLeakCheckResult.BasePressure, Math.Round(_startPressure, 5), Math.Round(_endPressure, 5), LeakRate, pMLeakCheckResult.Result, "ChamberOnly", _chamber.Name); } else { LeakCheckDataRecorder.Add(_leakcheckHoldTime, Math.Round(_startPressure, 5), Math.Round(_endPressure, 5), LeakRate, pMLeakCheckResult.Result, "ChamberOnly", _chamber.Name); } _chamber.OpenValve(ValveType.GasFinal, true); _chamber.TurnPendulumValve(true); pMLeakCheckResult.LeakCheckTime = (int)_routineTimer.ElapsedMilliseconds / 1000; //SerializeHelper.Instance.WriteToJsonFile(pMLeakCheckResult, $"LeakCheck/PM/{DateTime.Now.ToString("yyyyMMddHHmm")}.json"); return true; } private void PreSetValves() { _chamber.OpenValve(ValveType.FastPump, false); if (jetChamber != JetChamber.VenusDE) { _chamber.OpenValve(ValveType.SoftPump, false); } _chamber.OpenValve(ValveType.TurboPumpPumping, true); _chamber.OpenValve(ValveType.Guage, true); _chamber.OpenValve(ValveType.GasFinal, true); _chamber.TurnPendulumValve(true); } } }