using System; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using VirgoCommon; using VirgoRT.Devices; namespace VirgoRT.Modules.PMs { class LeakCheckRoutine : PMRoutineBase { private enum LeakCheckStep { PumpDown, CheckDoor, CheckDryPump, CloseAllValve, OpenPumpingValve, OpenGasFinalValve, CloseGasFinalValve, OpenMfc1Valve, OpenMfc2Valve, OpenMfc3Valve, OpenMfc4Valve, OpenMfc5Valve, CloseMfc1Valve, CloseMfc2Valve, CloseMfc3Valve, CloseMfc4Valve, CloseMfc5Valve, StartFlow, StopFlow, RecordStartPressure, RecordEndPressure, PumpDownDelay, StartPressureDelay, EndPressureDelay, ClosePumpValve, LeakCheckDelay, CalcLeakCheck, End, EndLeakCheck, AbortLeakCheck, CheckPressure }; // Fields private double _beginPressure = 0; private double _endPressure = 0; private double _leakRate; public double LeakRate { get; private set; } private int _leakCheckPumpDownTime; private int _leakCheckWaitTime; private LeakCheckMode _mode; private bool[] _enableGasLine = new bool[5]; private double[] _mfcFlow = new double[5]; private readonly PumpDownRoutine _pumpdownRoutine; // Properties // public int ElapseTime => (int)(delayTimer.GetElapseTime() / 1000.0); // Constructor // public LeakCheckRoutine(JetPM chamber, PumpDownRoutine _pdRoutine) : base(chamber) { Name = "leak check"; bUINotify = true; _pumpdownRoutine = _pdRoutine; } public void Terminate() { } public Result Start(params object[] objs) { // 预检查 if (CheckLid() == Result.RUN && CheckSlitDoor() == Result.RUN && CheckDryPump() == Result.RUN) { _enableGasLine = new bool[5] { false, false, false, false, false }; _mfcFlow = new double[5] { 0.0, 0.0, 0.0, 0.0, 0.0 }; Reset(); delayTimer.Start(0); try { if (objs.Length == 0) { _leakCheckPumpDownTime = SC.GetValue($"{Module}.Pump.LeakCheckPumpingTime"); _leakCheckWaitTime = SC.GetValue($"{Module}.Pump.LeakCheckWaitTime"); _leakRate = SC.GetValue($"{Module}.Pump.LeakRate"); _mode = LeakCheckMode.ChamberOnly; } else { _leakCheckPumpDownTime = Convert.ToInt32(objs[0].ToString()); _leakCheckWaitTime = Convert.ToInt32(objs[1].ToString()); _mode = (LeakCheckMode)Enum.Parse(typeof(LeakCheckMode), objs[2].ToString()); _leakRate = Convert.ToInt32(objs[3].ToString()); for (int i = 0; i < 5; i++) _enableGasLine[i] = Convert.ToBoolean(objs[4 + i].ToString()); } for (int i = 0; i < 5; i++) { if (_enableGasLine[i]) _mfcFlow[i] = SC.GetValue($"{Module}.MfcGas{i + 1}.MfcN2Scale"); } } catch (Exception ex) { LOG.Write(ex); return Result.FAIL; } return Result.RUN; } return Result.FAIL; } public Result Monitor() { try { ExecuteRoutine((int)LeakCheckStep.PumpDown, _pumpdownRoutine); if (_mode == LeakCheckMode.ChamberOnly) { ; } else if (_mode == LeakCheckMode.ChamberAndGasLine) { SetValve((int)LeakCheckStep.OpenGasFinalValve, ValveType.PROCESS, true); if (_enableGasLine[0]) SetValve((int)LeakCheckStep.OpenMfc1Valve, ValveType.Mfc1, true); if (_enableGasLine[1]) SetValve((int)LeakCheckStep.OpenMfc2Valve, ValveType.Mfc2, true); if (_enableGasLine[2]) SetValve((int)LeakCheckStep.OpenMfc3Valve, ValveType.Mfc3, true); if (_enableGasLine[3]) SetValve((int)LeakCheckStep.OpenMfc4Valve, ValveType.Mfc4, true); if (_enableGasLine[4]) SetValve((int)LeakCheckStep.OpenMfc5Valve, ValveType.Mfc5, true); } else if (_mode == LeakCheckMode.ChamberAndGasLineAndFAC) { SetValve((int)LeakCheckStep.OpenGasFinalValve, ValveType.PROCESS, true); if (_enableGasLine[0]) SetValve((int)LeakCheckStep.OpenMfc1Valve, ValveType.Mfc1, true); if (_enableGasLine[1]) SetValve((int)LeakCheckStep.OpenMfc2Valve, ValveType.Mfc2, true); if (_enableGasLine[2]) SetValve((int)LeakCheckStep.OpenMfc3Valve, ValveType.Mfc3, true); if (_enableGasLine[3]) SetValve((int)LeakCheckStep.OpenMfc4Valve, ValveType.Mfc4, true); if (_enableGasLine[4]) SetValve((int)LeakCheckStep.OpenMfc5Valve, ValveType.Mfc5, true); StartFlowMFC((int)LeakCheckStep.StartFlow, _mfcFlow); } TimeDelay((int)LeakCheckStep.PumpDownDelay, _leakCheckPumpDownTime); SetValve((int)LeakCheckStep.ClosePumpValve, ValveType.FAST_PUMP, false); //记录腔体Start pressure P1 RecordBeginPressure((int)LeakCheckStep.RecordStartPressure); //pump down delay TimeDelay((int)LeakCheckStep.EndPressureDelay, _leakCheckWaitTime); //记录腔体End pressure P2 RecordEndPressure((int)LeakCheckStep.RecordEndPressure); CalcLeakCheck((int)LeakCheckStep.CalcLeakCheck, _leakRate, _leakCheckWaitTime, 0); if (_mode == LeakCheckMode.ChamberOnly) { ; } else if (_mode == LeakCheckMode.ChamberAndGasLine) { SetValve((int)LeakCheckStep.CloseGasFinalValve, ValveType.PROCESS, false); if (_enableGasLine[0]) SetValve((int)LeakCheckStep.CloseMfc1Valve, ValveType.Mfc1, false); if (_enableGasLine[1]) SetValve((int)LeakCheckStep.CloseMfc2Valve, ValveType.Mfc2, false); if (_enableGasLine[2]) SetValve((int)LeakCheckStep.CloseMfc3Valve, ValveType.Mfc3, false); if (_enableGasLine[3]) SetValve((int)LeakCheckStep.CloseMfc4Valve, ValveType.Mfc4, false); if (_enableGasLine[4]) SetValve((int)LeakCheckStep.CloseMfc5Valve, ValveType.Mfc5, false); } else if (_mode == LeakCheckMode.ChamberAndGasLineAndFAC) { SetValve((int)LeakCheckStep.CloseGasFinalValve, ValveType.PROCESS, false); if (_enableGasLine[0]) SetValve((int)LeakCheckStep.CloseMfc1Valve, ValveType.Mfc1, false); if (_enableGasLine[1]) SetValve((int)LeakCheckStep.CloseMfc2Valve, ValveType.Mfc2, false); if (_enableGasLine[2]) SetValve((int)LeakCheckStep.CloseMfc3Valve, ValveType.Mfc3, false); if (_enableGasLine[3]) SetValve((int)LeakCheckStep.CloseMfc4Valve, ValveType.Mfc4, false); if (_enableGasLine[4]) SetValve((int)LeakCheckStep.CloseMfc5Valve, ValveType.Mfc5, false); StopFlowMFC((int)LeakCheckStep.StopFlow); } End((int)LeakCheckStep.End); //ExecuteRoutine((int)LeakCheckStep.EndLeakCheck, _pumpDownRoutine); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { return Result.FAIL; } return Result.DONE; } public void DelayLeakCheck(int id, string name, double time) { bool Func() { Notify(name); return true; } Tuple ret = Delay(id, Func, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.RUN) { throw new RoutineBreakException(); } } } public void CheckChamberPressure(int id, double target, out double pressure, int time) { bool Func() { return true; } bool? Check1() { if (_chamber.ChamberPressure < target) { Notify($"腔体压力 [{_chamber.ChamberPressure}] mt, 低于 [{target}] mt"); return true; } Stop($"腔体压力 [{_chamber.ChamberPressure}], 高于 [{target}]"); return false; } pressure = _chamber.ChamberPressure; Tuple ret = ExecuteAndWait(id, Func, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void RecordBeginPressure(int id) { bool Func() { _beginPressure = _chamber.ChamberPressure; Notify($"腔体压力初始值 {_beginPressure} mt"); return true; } bool? Check1() { return true; } Tuple ret = ExecuteAndWait(id, Func, Check1, 1 * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void RecordEndPressure(int id) { bool Func() { _endPressure = _chamber.ChamberPressure; Notify($"腔体压力结束值 {_endPressure} mt"); return true; } bool? Check1() { return true; } Tuple ret = ExecuteAndWait(id, Func, Check1, 1 * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void CalcLeakCheck(int id, double target, int timeRate, int time) { bool Func() { return true; } bool? Check1() { LeakRate = (_endPressure - _beginPressure) / (timeRate / 60.0); if (LeakRate < target) { Notify($"腔体漏率 [{LeakRate}] mt/min, 低于 [{target}] mt/min"); LeakCheckResultManager.Instance.AddLeakCheck(Module, DateTime.Now, ElapseTime, (double)_beginPressure, (double)_endPressure, LeakRate, LeakCheckStatus.Succeed.ToString(), _mode.ToString()); return true; } Stop($"腔体漏率 [{LeakRate}] mt/min, 高于 [{target}] mt/min"); LeakCheckResultManager.Instance.AddLeakCheck(Module, DateTime.Now, ElapseTime, (double)_beginPressure, (double)_endPressure, LeakRate, LeakCheckStatus.Failed.ToString(), _mode.ToString()); return false; } Tuple ret = ExecuteAndWait(id, Func, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void StopFlowMFC(int id) { bool Func() { _chamber.StopAllGases(); return true; } bool? Check1() { return true; } Tuple ret = ExecuteAndWait(id, Func, Check1, 1 * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void StartFlowMFC(int id, double[] mfcValues) { bool Func() { for (int index = 0; index < mfcValues.Length; index++) { _chamber.FlowGas(index, mfcValues[index]); } return true; } bool? Check1() { return true; } Tuple ret = ExecuteAndWait(id, Func, Check1, 1 * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void DeleteLeadCheck(object[] args) { LeakCheckResultManager.Instance.Delete(Module, args[0].ToString()); } public override void Abort() { try { _chamber.CloseValves(); LeakCheckResultManager.Instance.AddLeakCheck(Module, DateTime.Now, ElapseTime, (double)_beginPressure, (double)_chamber.ChamberPressure, 0, LeakCheckStatus.Aborted.ToString(), _mode.ToString()); } catch (Exception ex) { LOG.Write(ex); } } } }