using System; using Aitex.Core.Equipment.SusceptorDefine; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.DBCore; using VirgoCommon; //using Virgo.Common; using VirgoRT.Devices; namespace VirgoRT.Modules.PMs { public enum MonitorStepState { Continue, Failed, Break, } class PMRoutineBase : ModuleRoutine { // ----------------------------Fields-------------------------- // //private SCConfigItem scOpenGasValveTimeout = null; private int dOpenGasValveTimeout = 1; //1S //private SCConfigItem scCloseGasValveTimeout = null; public int dCloseGasValveTimeout = 2; //2s //private SCConfigItem scOpenCloseSlitValveTimeout = null; protected int valveOpenCloseTimeout = 2; //2s protected int _PressureTrip1 = 80; protected bool bUINotify; protected readonly JetPM _chamber; // --------------------------Properties------------------------ // public string Display { get; set; } public string WaferID { get; set; } // Constructor protected PMRoutineBase(JetPM chamber) { this.Module = chamber.Module.ToString(); _chamber = chamber; bUINotify = true; dOpenGasValveTimeout = SC.GetValue($"{Module}.OpenGasValveTimeout"); dCloseGasValveTimeout = SC.GetValue($"{Module}.TimeLimitOfCloseGasValve"); valveOpenCloseTimeout = SC.GetValue($"{Module}.OpenCloseSlitValveTimeout"); } public Result CheckLid() { if (!_chamber.IsLidClosed) { this.Stop("The chamber lid must be closed"); return Result.FAIL; } return Result.RUN; } protected Result CheckSlitDoor() { if (!_chamber.IsSlitDoorClosed) { Stop("Slit door must be closed"); return Result.FAIL; } return Result.RUN; } protected Result CheckDryPump() { if (!_chamber.IsPumpRunning) { Stop("The pump has not started"); return Result.FAIL; } if (_chamber.HasPumpError) { Stop("The pump status error"); return Result.FAIL; } return Result.RUN; } public void CheckThrottleValveFullOpen(int id) { bool execute() { Notify("Open the throttle valve"); _chamber.FullOpenTV(); return true; } bool? Check1() { if (_chamber.TVPosition >= 98) { Notify("The throttle valve is opened"); return true; } return false; } Tuple ret = ExecuteAndWait(id, execute, Check1, 20 * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop("Not open the throttle valve"); throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { Stop("Start the throttle valve timeout"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected Result CheckCDA() { if (!_chamber.IsCDA_OK) { Stop("The CDA pressure signal is incorrect"); return Result.FAIL; } return Result.RUN; } protected void CloseAllValve(int id, int time) { bool execute() { Notify("Close all valve"); _chamber.CloseValves(); return true; } Tuple ret = ExecuteAndWait(id, execute, () => true, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void SetValve(int id, ValveType vlv, bool bOpen) { bool exec() { _chamber.SetValveOnOff(vlv, bOpen); Notify($"{(bOpen ? "open" : "close")} {vlv} valve"); return true; } bool? Check1() { if (vlv == ValveType.FAST_PUMP && bOpen) return _chamber.IsFastPumpOpened; else if (vlv == ValveType.FAST_PUMP && !bOpen) return !_chamber.IsFastPumpOpened; else if (vlv == ValveType.SOFT_PUMP && bOpen) return _chamber.IsSoftPumpOpened; else if (vlv == ValveType.SOFT_PUMP && !bOpen) return !_chamber.IsSoftPumpOpened; else return true; } var res = ExecuteAndWait(id, exec, Check1, 500); if (res.Item1) { throw new RoutineBreakException(); } } protected void CheckATM2(int id, bool on, int time) { bool? check() { //if (!_chamber.IsATM) //{ // Notify("ATM is OFF"); //} return on ? _chamber.IsATM : !_chamber.IsATM; } Tuple ret = ExecuteAndWait(id, () => { Notify($"Wait ATM sensor {(on ? "ON" : "OFF")}"); return true; }, check, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL || ret.Item2 == Result.TIMEOUT) { Stop($"ATM sensor {(_chamber.IsATM ? "ON" : "OFF")}"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckPressure(int id, int targetPressure, bool morethan, int time) { bool? Check1() { bool res = morethan ? _chamber.ChamberPressure > targetPressure : _chamber.ChamberPressure < targetPressure; if (res) { Notify($"The pressure has reached {targetPressure:N} mTorr"); } return res; } Tuple ret = ExecuteAndWait(id, () => { Notify($"Wait pressure {(morethan ? "rise" : "decline")} to {targetPressure:N} mTorr"); return true; }, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Current pressure [{_chamber.ChamberPressure}], not equal to [{targetPressure}]"); throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { Stop($"Check chamber pressuer timeout, current value [{_chamber.ChamberPressure*0.001:F2}] Torr"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckForeline(int id, uint target, int time) { bool Func() { Notify($"Check foreline pressure, target {target} mTorr"); return true; } bool? Check1() { return _chamber.ForelinePressure < target; } Tuple ret = ExecuteAndWait(id, Func, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { Stop($"Check foreline pressure timeout, current foreline pressure value {_chamber.ForelinePressure}"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckVAC(int id, double targetPressure, int time) { bool? Check1() { if (_chamber.ChamberPressure < targetPressure) { Notify($"Pump below [{targetPressure}]"); return true; } return false; } Tuple ret = ExecuteAndWait(id, () => true, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) //timeout { //Warning($"Can not pump to base pressure {target} in {time} seconds"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckVAC(int id, int time) { Tuple ret = ExecuteAndWait(id, () => true, () => _chamber.IsVAC, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop("VAC sensor NOT ON"); throw new RoutineFaildException(); } if (Result.TIMEOUT == ret.Item2) { Stop($"VAC sensor timeout, chamber pressure {_chamber.ChamberPressure}"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } public void SetLiftPinPos(int id, MovementPosition pos, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set lift pin {_chamber.Name} {pos}" ); if (!_chamber.SetLiftPin(pos, out string reason)) { Stop(reason); return false; } return true; }, () => _chamber.CheckLiftPinPos(pos), timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set lift pin {pos} in {timeout} seconds"); throw new RoutineFaildException(); } else throw new RoutineBreakException(); } } protected void End(int id) { bool Func() { double duration_min = counter.GetElapseTime(); TimeSpan ts = TimeSpan.FromMilliseconds(duration_min); string info = $"Finished in {ts.Minutes} minutes {ts.Seconds} seconds"; Notify(info); //if (bUINotify) // EV.PostPopDialogMessage(EventLevel.Information, Name, $"{Module} {info} Finished"); return true; } Tuple ret = Execute(id, Func); } public virtual void Abort() { _chamber.GeneratorPowerOn(false); _chamber.GeneratorBiasPowerOn(false); _chamber.StopAllGases(); } /// /// /// /// /// 单位:秒 public void CloseValve(int stepId, float delayTime) { bool Func() { Notify("Vent End Close Vent Valve"); _chamber.SetValveOnOff(ValveType.PURGE, false); _chamber.SetValveOnOff(ValveType.FAST_VENT, false); _chamber.SetValveOnOff(ValveType.PROCESS, false); //_chamber.OpenValve(ValveType.SOFT_PUMP, true); //_chamber.OpenValve(ValveType.FAST_PUMP, true); return true; } Tuple ret = Delay(stepId, Func, delayTime * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void StartLoop(int id, string name, int count, Action notify, Action error) { bool Func() { Notify($"{name} loop {LoopCounter + 1}"); return true; } Tuple ret = Loop(id, Func, count); if (ret.Item1) { if (ret.Item2 == Result.FAIL) throw new RoutineFaildException(); } } protected void EndLoop(int id, Action notify, Action error) { Tuple ret = EndLoop(id, () => true); if (ret.Item1) { if (ret.Item2 == Result.FAIL) throw new RoutineFaildException(); throw new RoutineBreakException(); } } protected void CyclePump(int id, int target, int timeLimit, bool isStopPumpOnceDone) { bool Func() { Notify($"Pumping to {target} mTorr"); _chamber.SetValveOnOff(ValveType.PROCESS, false); _chamber.SetValveOnOff(ValveType.PURGE, false); _chamber.SetValveOnOff(ValveType.FAST_VENT, false); _chamber.SetValveOnOff(ValveType.FAST_PUMP, true); return true; } bool? Check1() { if (_chamber.ChamberPressure < target) { if (isStopPumpOnceDone) { _chamber.SetValveOnOff(ValveType.FAST_PUMP, false); } return true; } return true; } Tuple ret = ExecuteAndWait(id, Func, Check1, timeLimit * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { Stop($"Set pump pressure {target} timeout in time {timeLimit}"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CycleVent(int id, int target, int timeLimit, bool isStopVentOnceDone) { bool Func() { Notify($"Venting to {target} mTorr"); _chamber.SetValveOnOff(ValveType.FAST_PUMP, false); _chamber.SetValveOnOff(ValveType.PROCESS, true); _chamber.SetValveOnOff(ValveType.PURGE, true); return true; } bool? Check1() { if (_chamber.ChamberPressurePressure > target) { if (isStopVentOnceDone) { _chamber.SetValveOnOff(ValveType.PROCESS, false); _chamber.SetValveOnOff(ValveType.PURGE, false); _chamber.SetValveOnOff(ValveType.FAST_VENT, false); } return true; } return false; } Tuple ret = ExecuteAndWait(id, Func, Check1, timeLimit * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set vent pressure {target} timeout in vent time {timeLimit}"); if (isStopVentOnceDone) { _chamber.SetValveOnOff(ValveType.PROCESS, false); _chamber.SetValveOnOff(ValveType.PURGE, false); _chamber.SetValveOnOff(ValveType.FAST_VENT, false); } throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckSubstrateTemp(int id, double target, int time, double tolerance) { bool Func() { if (_chamber.SubstrateTempFB > target) { Notify($"Substrate current temp {_chamber.SubstrateTempFB} ℃, greater than target {target.ToString()} ℃"); //return true; } _chamber.HeatSubstrate(target); Notify($"Check substrate temp,current temp{_chamber.SubstrateTempFB} ℃, target {target.ToString()} ℃"); return true; } bool? Check1() { if (Math.Abs( target) <= 0.1) return true; if (Math.Abs(_chamber.SubstrateTempFB - target) <= tolerance) return true; 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) { Stop($"Check substrate temp timeout, current Substrate temp value {_chamber.SubstrateTempFB}"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void CheckCoolantTemp(int id, double target, double offset, int time, double tolerance) { bool Func() { if (_chamber.CoolantOutletTempFB > target) { Notify($"Chiller current temp {_chamber.CoolantOutletTempFB} ℃, greater than target value {target.ToString()} ℃"); //return true; } _chamber.HeatChiller(target, offset); Notify($"Check chiller temp,current temp {_chamber.CoolantOutletTempFB} ℃, target {target.ToString()} ℃"); return true; } bool? Check1() { if (!_chamber.CheckChillerStatus()) return false; return Math.Abs(_chamber.CoolantOutletTempFB - target) <= tolerance; } Tuple ret = ExecuteAndWait(id, Func, Check1, time * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { if (!_chamber.CheckChillerStatus()) { Stop($"Chiller not connected or in error"); } else { Stop($"Check chiller temp timeout, current chiller temp value {_chamber.CoolantOutletTempFB}"); } throw new RoutineFaildException(); } throw new RoutineBreakException(); } } protected void SetSlitDoor(int id, bool isOpen, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Set slit door {_chamber.Name} " + (isOpen ? "open" : "close")); _chamber.SetSlitDoor(isOpen, out _); return true; }, () => isOpen ? _chamber.CheckSlitDoorOpen() : _chamber.CheckSlitDoorClose(), timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set slit door {(isOpen ? "open" : "close")} timeout in {timeout} seconds"); throw new RoutineFaildException(); } else throw new RoutineBreakException(); } } } }