| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 | using Aitex.Core.Common.DeviceData;using Aitex.Core.RT.Device;using Aitex.Core.RT.Device.Unit;using Aitex.Core.RT.Event;using Aitex.Core.RT.Routine;using Aitex.Core.RT.SCCore;using MECF.Framework.Common.DBCore;using MECF.Framework.Common.Equipment;using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.TMs;using FurnaceRT.Equipments.PMs;using FurnaceRT.Equipments.PMs.Routines;using System;using System.Collections.Generic;using System.Diagnostics;namespace FurnaceRT.Modules.PMs{    public class PMLeakCheckRoutine : PMBaseRoutine    {        enum RoutineStep        {            CheckSlitValve,            SetValve,            SetTV,            SetGasLine1,            SetGasLine2,            SetGasLine3,            SetGasLine4,            SetTuning,            Pump,            ContinuePump,            ClosePumpValve,            DoLeakCheck,            CalcLeakCheck,            Vent,            UnsetTuning,            StopVent,        }        enum LeakCheckType        {            ChamberOnly,            ChamberAndGasline,            ChamberAndGaslineToFacility,        }        private int _paramContinuePumpTime;        private int _paramLeakCheckTime;        private string _leakCheckType;        private bool[] _isMfcChecked;        private string _gaslineSelection;        private double[] _mfcScale = new double[4];        private double _beginPressure;        private int _tvPostion;        private double _basePressure;        private int _timeoutPump;        private bool _enableTuning;        private float _tuningPercent;        private float _ventAtmPressure;        //private TM _tm;        private Stopwatch _swTimer = new Stopwatch();        private List<string> _mfc = new List<string>() { "Mfc1", "Mfc2", "Mfc3", "Mfc4" };        public int ElapsedTime        {            get { return _swTimer.IsRunning ? (int)(_swTimer.ElapsedMilliseconds / 1000) : 0; }        }        public PMLeakCheckRoutine(ModuleName module, PMModule pm) : base(module, pm)        {            Module = module.ToString();            Name = "Leak Check";        }        internal void Init(int pumpTime, int leakCheckTime, string leakCheckType, bool[] isMfcChecked)        {            _paramContinuePumpTime = pumpTime;            _paramLeakCheckTime = leakCheckTime;            _leakCheckType = leakCheckType;            _isMfcChecked = isMfcChecked;            if (_leakCheckType != LeakCheckType.ChamberOnly.ToString())            {                _gaslineSelection = string.Empty;                for (int i = 0; i < _isMfcChecked.Length; i++)                {                    if (_isMfcChecked[i])                    {                        _mfcScale[i] = DEVICE.GetDevice<IoMfc3>($"{Module}.{_mfc[i]}").Scale;                        _gaslineSelection += _mfc[i] + ",";                    }                }                _gaslineSelection = _gaslineSelection.Remove(_gaslineSelection.Length - 1);            }        }        public override Result Start(params object[] objs)        {            Reset();            _swTimer.Restart();            _tvPostion = SC.GetValue<int>($"PM.{Module}.LeakCheck.TVPosition");            _basePressure = SC.GetValue<double>($"PM.{Module}.LeakCheck.PumpBasePressure");            _timeoutPump = SC.GetValue<int>($"PM.{Module}.LeakCheck.PumpTimeout");            _enableTuning = SC.GetValue<bool>($"PM.{Module}.LeakCheck.EnableTuning");            _tuningPercent = (float) SC.GetValue<double>($"PM.{Module}.LeakCheck.TuningPercent");            _ventAtmPressure = (float)SC.GetValue<double>($"PM.{Module}.VentRoutine.VentBasePressure");            return Result.RUN;        }        public override Result Monitor()        {            try            {                CheckSlitValve((int)RoutineStep.CheckSlitValve, PMModule);                SetValve((int)RoutineStep.SetValve, PMModule);                SetTV((int)RoutineStep.SetTV, PMModule, _tvPostion);                if (_leakCheckType == LeakCheckType.ChamberAndGasline.ToString())                {                    for (int i = 0; i < _isMfcChecked.Length; i++)                    {                        if (_isMfcChecked[i])                        {                            SetGasLine((int)Enum.Parse(typeof(RoutineStep), $"SetGasLine{i + 1}"), PMModule, _mfc[i], 0);                        }                    }                }                else if (_leakCheckType == LeakCheckType.ChamberAndGaslineToFacility.ToString())                {                    for (int i = 0; i < _isMfcChecked.Length; i++)                    {                        if (_isMfcChecked[i])                        {                            SetGasLine((int)Enum.Parse(typeof(RoutineStep), $"SetGasLine{i + 1}"), PMModule, _mfc[i], _mfcScale[i]);                        }                    }                }                if (_enableTuning)                {                    SetTuning((int)RoutineStep.SetTuning, PMModule, _tuningPercent);                }                Pump((int)RoutineStep.Pump, PMModule, _timeoutPump, _basePressure);                ContinuePump((int)RoutineStep.ContinuePump, _paramContinuePumpTime);                ClosePumpValve((int)RoutineStep.ClosePumpValve, PMModule);                DoLeakCheck((int)RoutineStep.DoLeakCheck, _paramLeakCheckTime);                CalcLeakCheck((int)RoutineStep.CalcLeakCheck, _paramLeakCheckTime);                FastVent((int)RoutineStep.Vent, PMModule, _ventAtmPressure, _timeoutPump);                if (_enableTuning)                {                    UnsetTuning((int)RoutineStep.UnsetTuning, PMModule);                }                StopVent((int)RoutineStep.StopVent, PMModule, _timeoutPump);            }            catch (RoutineBreakException)            {                return Result.RUN;            }            catch (RoutineFaildException)            {                return Result.FAIL;            }            _swTimer.Stop();            return Result.DONE;        }        public override void Abort()        {            Stop($"{Module} leak check aborted");            _swTimer.Stop();            //LeakCheckDataRecorder.Add((int)_swTimer.ElapsedMilliseconds / 1000, _beginPressure, _tm.ChamberPressure, 0, Result.FAIL.ToString(), _leakCheckType, Module, _gaslineSelection);        }        private void SetTuning(int id, PMModule pm, float percent)        {            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Start leak check pumping");                //pm.ChamberProcessPressureGauge.SetTuning(_tuningPercent);                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        private void UnsetTuning(int id, PMModule pm )        {            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Stop leak check venting");                //pm.ChamberProcessPressureGauge.UnsetTuning();                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        private void StopVent(int id, PMModule pm, int timeout)        {            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Turn off {pm.Name} vent valve");                //if (!pm.Gas4Valve.TurnValve(false, out string reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        private void FastVent(int id, PMModule pm, float ventPressure, int timeout)        {            Tuple<bool, Result> ret = ExecuteAndWait(id, () =>            {                Notify($"Turn {pm.Name} vent valve on, vent to {ventPressure} Torr");                //if (!pm.Gas4Valve.TurnValve(true, out string reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            }, () =>            {                return pm.ChamberPressure >= ventPressure;            }, timeout * 1000);            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else if (ret.Item2 == Result.TIMEOUT) //timeout                {                    Stop($"{pm.Name} vent timeout, over {timeout} seconds");                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        public void CheckSlitValve(int id, PMModule pm)        {            Tuple<bool, Result> ret = Check(id, () =>            {                Notify($"Check {Module} slit valve is closed");                if (!pm.CheckSlitValveClose())                {                    Stop($"{Module} slit valve is not closed.");                    return false;                }                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }            }        }        public void SetValve(int id, PMModule pm)        {            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Run {pm.Name} close valve all");                string reason = "";                foreach (var stick in PMModule.GasSticks)                {                    if (!stick.SetFlow(out reason, 0, 0))                    {                        Stop(reason);                        return false;                    }                }                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        public void SetTV(int id, PMModule pm, float position)        {            Tuple<bool, Result> ret = Check(id, () =>            {                Notify($"Run {Module} set TV position");                //if (!pm.ThrottleValve.SetMode(PressureCtrlMode.TVPositionCtrl, out string reason))                //{                //    Stop(reason);                //    return false;                //}                //if (!pm.ThrottleValve.SetPosition(position, out reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }            }        }        private void SetGasLine(int id, PMModuleBase pm, string mfcId, double flow)        {            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Set gas {mfcId} flow to {flow} sccm");                //if (!pm.SetGasLine(mfcId, (float)flow, out string reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    Stop($"Set gas {mfcId} flow to {flow} sccm failed.");                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        public void Pump(int id, PMModule pm, int timeout, double pressure)        {            Tuple<bool, Result> ret = ExecuteAndWait(id, () =>            {                Notify($"{pm.Name} pump to {pressure} Torr");                //if (!pm.PumpValve.TurnValve(true, out string reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            }, () =>            {                return pm.ChamberPressure < pressure;            }, timeout * 1000);            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else if (ret.Item2 == Result.TIMEOUT) //timeout                {                    Stop($"{pm.Name} pump timeout, over {timeout} seconds");                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        public void ContinuePump(int id, int delayTime)        {            Tuple<bool, Result> ret = Delay(id, () =>            {                Notify($"continue pump {delayTime} seconds");                return true;            }, delayTime * 1000);            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                throw new RoutineBreakException();            }        }        public void ClosePumpValve(int id, PMModule pm)        {            string timeoutReason = string.Empty;            Tuple<bool, Result> ret = Execute(id, () =>            {                Notify($"Run {pm.Name} close valve all");                //if (!pm.PumpValve.TurnValve(false, out string reason))                //{                //    Stop(reason);                //    return false;                //}                return true;            });            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw (new RoutineFaildException());                }                else                    throw (new RoutineBreakException());            }        }        public void DoLeakCheck(int id, double time)        {            Tuple<bool, Result> ret = Delay(id, () =>            {                Notify($"Keep pressure for {time} seconds");                _beginPressure = PMModule.ChamberPressure * 1000; // 单位使用mTorr                return true;            }, time * 1000);            if (ret.Item1)            {                if (ret.Item2 == Result.RUN)                {                    throw (new RoutineBreakException());                }            }        }        public void CalcLeakCheck(int id, int time)        {            Tuple<bool, Result> ret = Execute(id, () =>            {                double endPressure = PMModule.ChamberPressure * 1000; // 单位使用mTorr                double leakRate = (endPressure - _beginPressure) / (time / 60.0);                LeakCheckDataRecorder.Add(time, _beginPressure, endPressure, leakRate, Result.Succeed.ToString(), _leakCheckType, Module, _gaslineSelection);                EV.PostInfoLog(Module,                    $"{Module} leak check result: end at {DateTime.Now.ToString("HH:mm:ss")}, start: {_beginPressure:F2} mTorr, end: {endPressure:F2} mTorr, using {time} seconds, leak rate: {leakRate:F2}");                return true;            });        }    }}
 |