using System.Collections.Generic; using Aitex.Core.RT.Routine; using Aitex.Core.RT.Device; using Aitex.Core.RT.SCCore; using Venus_RT.Devices; using Venus_RT.Devices.IODevices; using Aitex.Core.RT.Log; using Venus_Core; using Aitex.Core.Util; using System; using MECF.Framework.Common.DBCore; using MECF.Framework.Common.Routine; using System.Collections.ObjectModel; namespace Venus_RT.Modules.PMs { class PMGasVerificationRoutine : PMRoutineBase, IRoutine { private enum GasStep { kPrepareValves, kPumpDown_1, kGasFlow, kWaitPendulumFullClose, KDelay_2S, KGetBeginPressure, kDelay_1, kGasVerification, kStopGasFlow, kPumpDown_2, kEnd, } public enum VerifyMode { OnePoint, TenPoint, } private double _basePressure; private double _beginPressure; private double _endPressure; private double _elapsedTime; private DeviceTimer _verificationDeviceTimer = new DeviceTimer(); private int _mfcIndex; private float _mfcFlow; private int _flowTime; private int _pumpingTime; private int _holdTime; private double _mfcActualFlow; private double _maxPressure; private MfcBase1 _mfcDevice; private VerifyMode _paramMode; private Dictionary _paramFlowSet = new Dictionary(); private Dictionary> _calibrationResult = new Dictionary>(); private float _pressureStableTolerance = 2;//2mTorr private float _flowStableTolerance = 0.02f;//2% private double _chamberVolume; private double _gasTemperature; private double _leakRate; private double _maxDeviation; private readonly PumpDownRoutine _pumpDownRoutine; public ObservableCollection _MFCCalibrationDatas = new ObservableCollection(); //private bool _flag;//判断3分钟是否大于9torr private JetChamber jetChamber = JetChamber.None; public PMGasVerificationRoutine(JetPMBase chamber, PumpDownRoutine pdRoutine) : base(chamber) { Name = "Gas Verification"; _pumpDownRoutine = pdRoutine; jetChamber = chamber.ChamberType; } internal void Init(string mfc, double flow, int flowCount) { int.TryParse(mfc.Replace("MFC", ""), out _mfcIndex); _mfcDevice = DEVICE.GetDevice($"{Module}.MfcGas{_mfcIndex}"); _mfcIndex -= 1;//start from 0 _mfcFlow = (float)flow; if (flowCount == 10) _paramMode = VerifyMode.TenPoint; else _paramMode = VerifyMode.OnePoint; } public RState Start(params object[] objs) { if (!CheckLid()) { return RState.Failed; } if (!CheckSlitDoor()) { return RState.Failed; } if (!CheckDryPump()) { return RState.Failed; } if (!CheckTurboPump()) { return RState.Failed; } _calibrationResult.Clear(); _paramFlowSet.Clear(); _MFCCalibrationDatas.Clear(); _basePressure = SC.GetValue($"{Module}.MFCVerification.BasePressure"); _chamberVolume = SC.GetValue($"{Module}.MFCVerification.ChamberVolume"); _gasTemperature = SC.GetValue($"{Module}.MFCVerification.GasTemperature"); _pumpingTime = SC.GetValue($"{Module}.MFCVerification.PumpingTime"); _flowTime = SC.GetValue($"{Module}.MFCVerification.GasFlowTime"); _holdTime = SC.GetValue($"{Module}.MFCVerification.HoldTime"); _maxDeviation = SC.GetValue($"{Module}.MFCVerification.MaxDeviation"); _pressureStableTolerance = (float)SC.GetValue($"{Module}.MFCVerification.PressureStableTolerance"); _flowStableTolerance = (float)(SC.GetValue($"{Module}.MFCVerification.FlowStableTolerance") / 100.0); _maxPressure = SC.GetValue($"{Module}.MFCVerification.TargetPressure"); if (_paramMode == VerifyMode.TenPoint) { for (int i = 0; i < 10; i++) { _paramFlowSet.Add(i, (float)_mfcDevice.Scale * (i + 1) / 10); } } else { if (_mfcFlow <= 0 || _mfcFlow > _mfcDevice.Scale) { LOG.Write(eEvent.ERR_ROUTINE_FAILED, Module, Name, $"MFC set value {_mfcFlow} not valid"); return RState.Failed; } _paramFlowSet.Add(0, _mfcFlow); } _mfcDevice.ResetVerificationData(); _leakRate = 0; var dbData = DataQuery.Query($"SELECT * FROM \"leak_check_data\" where \"module_name\" = '{Module}' order by \"operate_time\" DESC;"); if (dbData != null && dbData.Rows.Count > 0 && !dbData.Rows[0]["leak_rate"].Equals(DBNull.Value)) { _leakRate = Convert.ToDouble(dbData.Rows[0]["leak_rate"]); } Reset(); return Runner.Start(Module, Name); } public RState Monitor() { Runner.Run(GasStep.kPrepareValves, PrepareValve, _delay_50ms) .LoopStart(GasStep.kPumpDown_1, $"{_mfcDevice.Name} Gas Verification", _paramFlowSet.Count, PumpingDown, WaitPumpDone) .LoopRun(GasStep.kGasFlow, FlowGas, CheckGasStable) .Wait(GasStep.kWaitPendulumFullClose, WaitPendulumFullClose) .LoopDelay(GasStep.KDelay_2S, 2 * 1000) .LoopRun(GasStep.KGetBeginPressure, GetBeginPressure, JudgePressure, (_holdTime + 10) * 1000) //.LoopDelay(GasStep.kDelay_1, _holdTime * 1000) .LoopRun(GasStep.kGasVerification, CalcMfcCalibration, _delay_2s) .LoopEnd(GasStep.kStopGasFlow, StopGasFlow, IsPumpDownOK) .End(GasStep.kEnd, NullFun, _delay_2s); return Runner.Status; } private bool JudgePressure() { if (_verificationDeviceTimer.GetElapseTime() < 3 * 60 * 1000 && _chamber.ChamberPressure > 9000) { return true; } if (_verificationDeviceTimer.GetElapseTime() > _holdTime * 1000) { return true; } return false; } public void Abort() { _verificationDeviceTimer.Stop(); _chamber.StopAllGases(); _chamber.CloseValves(); _mfcDevice.ResetVerificationData(); } private bool PrepareValve() { _chamber.CloseValves(); _chamber.OpenValve(ValveType.TurboPumpPumping, true); _chamber.OpenValve(ValveType.Guage, true); _chamber.OpenValve(ValveType.GasFinal, true); return true; } private bool PumpingDown() { _chamber.SetPVPostion(1000); return true; } private bool WaitPumpDone() { if (Runner.StepElapsedMS >= _pumpingTime * 1000) { if (_chamber.ProcessPressure <= _basePressure) { return true; } else { Runner.Stop($"MFC Gas Verification fail, Cannot pumping down to {_basePressure} mTorr in {_pumpingTime} seconds"); return true; } } return false; } private void OpenPVNVlv(int mfcIndex, bool on) { ValveType[] vlvs = new ValveType[] { ValveType.PV11, ValveType.PV21, ValveType.PV31, ValveType.PV41 }; if (_chamber.ChamberType == JetChamber.VenusSE || _chamber.ChamberType == JetChamber.VenusDE) { vlvs = new ValveType[] { ValveType.PV11, ValveType.PV21, ValveType.PV31, ValveType.PV41, ValveType.PV51, ValveType.PV61, ValveType.PV71, ValveType.PV81, ValveType.PV91, ValveType.PVA1, ValveType.PVB1, ValveType.PVC1, }; } // if (mfcIndex < 4) //{ _chamber.OpenValve(vlvs[mfcIndex], on); //} } private bool FlowGas() { Notify($"Start {_mfcDevice.Name} gas flow"); _verificationDeviceTimer.Start(0); //if (jetChamber == JetChamber.Kepler2200A || jetChamber == JetChamber.Kepler2200B) //{ // _beginPressure = ConvertPressureUnit.ConvertPaTomtorr(_chamber.ChamberPressure); //} //else //{ // _beginPressure = _chamber.ChamberPressure; //} _chamber.OpenValve(ValveType.GasFinal, true); OpenPVNVlv(_mfcIndex, true); if (!_chamber.FlowGas(_mfcIndex, _paramMode == VerifyMode.TenPoint ? _paramFlowSet[Runner.LoopCounter] : _mfcFlow)) { return false; } return true; } private bool WaitPendulumFullClose() { return _chamber.PendulumPosition <= 0; } private bool CheckGasStable() { if (_verificationDeviceTimer.GetElapseTime() > _flowTime * 1000) { if (!_chamber.TurnPendulumValve(false)) { Runner.Stop("Stop Pendulum Valve failed."); } return true; } //if (Math.Abs(_chamber.ChamberPressure - _beginPressure) > _pressureStableTolerance) //{ // Runner.Stop($""); // return true; //} if (_verificationDeviceTimer.GetElapseTime() > 3000) { if (Math.Abs(_mfcDevice.SetPoint - _mfcDevice.FeedBack) / _mfcDevice.SetPoint > _flowStableTolerance) { Runner.Stop($"Gas is not Stable"); return true; } } return false; } private bool GetBeginPressure() { if (jetChamber == JetChamber.Kepler2200A || jetChamber == JetChamber.Kepler2200B) { _beginPressure = ConvertPressureUnit.ConvertPaTomtorr((float)_chamber.ChamberPressure); } else { _beginPressure = _chamber.ChamberPressure; } Notify($"Get begin pressure {_beginPressure.ToString("f1")}"); _verificationDeviceTimer.Start(0); //Notify($"Check finished one point"); return true; } private bool CalcMfcCalibration() { //_mfcIndex += 1; // full open Pendulum valve //.SetPVPostion(1000); if (jetChamber == JetChamber.Kepler2200A || jetChamber == JetChamber.Kepler2200B) { _endPressure = ConvertPressureUnit.ConvertPaTomtorr((float)_chamber.ChamberPressure); } else { _endPressure = _chamber.ChamberPressure; } _elapsedTime = _verificationDeviceTimer.GetElapseTime() / (1000 * 60); //unit minute float flow = _paramMode == VerifyMode.TenPoint ? _paramFlowSet[Runner.LoopCounter] : _mfcFlow; _mfcActualFlow = 273.15 * _chamberVolume / ((273.15 + _gasTemperature) * 760000) * ((_endPressure - _beginPressure) / _elapsedTime - _leakRate); Notify($"Calculate flow: calculate flow={_mfcActualFlow}, setpoint={flow}, begin pressure(mtorr)={_beginPressure:f3}, end pressure(mtorr)={_endPressure:f3}," + $"elapsed time(minute)={_elapsedTime:f3}"); _MFCCalibrationDatas.Add(new MFCCalibrationData(flow, _mfcActualFlow)); double deviation = (Math.Abs(_mfcActualFlow) - Math.Abs(flow)) / Math.Abs(flow) * 100; bool isOk = Math.Abs(deviation) <= Math.Abs(_maxDeviation); if (!isOk) { LOG.Write(eEvent.ERR_ROUTINE_FAILED, Module, Name, $"MFC{(_mfcIndex + 1).ToString()} verify failed, deviation{deviation} exceed max tolerance{_maxDeviation}"); } if (_paramMode == VerifyMode.TenPoint) { _calibrationResult[flow] = Tuple.Create((float)_mfcActualFlow, (float)_elapsedTime); _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, _calibrationResult.Count == 10, _elapsedTime * 60, deviation, isOk, (int)VerifyMode.TenPoint); } else if (_paramMode == VerifyMode.OnePoint) { _mfcDevice.SetVerificationResult((float)flow, (float)_mfcActualFlow, true, _elapsedTime * 60, deviation, isOk, (int)VerifyMode.OnePoint); } return true; } private bool StopGasFlow() { Notify($"Stop gas {_mfcIndex} flow"); if (!_chamber.FlowGas(_mfcIndex, 0)) { return false; } OpenPVNVlv(_mfcIndex, false); _chamber.OpenValve(ValveType.TurboPumpPumping, false); _chamber.OpenValve(ValveType.FastPump, true); return _pumpDownRoutine.Start(_basePressure) == RState.Running; } private bool IsPumpDownOK() { var status = _pumpDownRoutine.Monitor(); if (status == RState.End) { return true; } else if (status == RState.Failed || status == RState.Timeout) { Runner.Stop($"Pump down to {_basePressure} failed."); return true; } return false; } } }