using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Alarm; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.Routine; using MECF.Framework.Common.SubstrateTrackings; using PunkHPX8_Core; using PunkHPX8_RT.Devices.AXIS; using PunkHPX8_RT.Devices.VpwCell; using PunkHPX8_RT.Devices.VpwMain; using PunkHPX8_RT.Modules.VpwMain; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PunkHPX8_RT.Modules.VpwCell { public class VpwVacuumPrewetRoutine : RoutineBase, IRoutine { private enum PrepareStep { OpenVacuumValve, EnableVacuumPump, CheckVacuum, CloseVacuumValve, OpenVentValve, CheckLidReleaseVacuum, ChamberDown, CloseVentValve, ChamberUp, LastOpenVacuumValve, LastCheckVacuum, DryerHoldTime, OpenCellValve, End } #region 内部变量 /// /// recipe /// private VpwRecipe _recipe; /// /// 设备 /// private VpwCellDevice _vpwCellDevice; /// /// Main设备 /// private VpwMainDevice _mainDevice; /// /// Pump DownWarn时间 /// private int _pumpDownWarningTime = 60000; /// /// Pump Down超时 /// private int _pumpDownTimeOut = 80000; /// /// 开始Pump Down时间 /// private DateTime _pumpDownTime=DateTime.MinValue; /// /// 是否需要重试 /// private bool _isNeedRetry = false; /// /// Lid Release Pressure /// private int _lidReleasePressure = 730; /// /// Lid Release Pressure /// private int _lidReleasePressureTimeout = 10000; #endregion /// /// 构造函数 /// /// public VpwVacuumPrewetRoutine(string module) : base(module) { } /// /// 中止 /// public void Abort() { Runner.Stop("Manual abort"); } /// /// 监控 /// /// public RState Monitor() { Runner.Run(PrepareStep.OpenVacuumValve, PumpValveOn, _delay_1ms) .Run(PrepareStep.EnableVacuumPump, PumpEnable, _delay_1ms) .Wait(PrepareStep.CheckVacuum, CheckVacuumValue, _pumpDownTimeOut + 1000) .RunIf(PrepareStep.CloseVacuumValve, _isNeedRetry, PumpValveOff, _delay_1ms) .RunIf(PrepareStep.OpenVentValve, _isNeedRetry, OpenVentValve, _delay_1ms) .WaitIf(PrepareStep.CheckLidReleaseVacuum, _isNeedRetry, CheckLidReleaseVacuum, _lidReleasePressureTimeout) .RunIf(PrepareStep.ChamberDown, _isNeedRetry, ChamberDown, CheckChamberOpened, _delay_10s) .RunIf(PrepareStep.CloseVentValve, _isNeedRetry, CloseVentValve, _delay_1ms) .RunIf(PrepareStep.ChamberUp, _isNeedRetry, ChamberUp, CheckChamberClosed, _delay_10s) .RunIf(PrepareStep.LastOpenVacuumValve, _isNeedRetry, PumpValveOn, _delay_1ms) .WaitIf(PrepareStep.LastCheckVacuum, _isNeedRetry,LastCheckVacuumValue, _pumpDownTimeOut) .Delay(PrepareStep.DryerHoldTime,_recipe.DryHoldTime*1000) .Run(PrepareStep.OpenCellValve,OpenCellValve,_delay_1ms) .End(PrepareStep.End,NullFun,_delay_1ms); return Runner.Status; } /// /// pump valve on /// /// private bool PumpValveOn() { bool result = _vpwCellDevice.VacuumValveOn(); if (!result) { NotifyError(eEvent.ERR_VPW, "pump valve on failed", 0); } return result; } /// /// Pump valve off /// /// private bool PumpValveOff() { bool result = _vpwCellDevice.VacuumValveOff(); if (!result) { NotifyError(eEvent.ERR_VPW, "pump valve off failed", 0); } return result; } /// /// Pump Enable /// /// private bool PumpEnable() { bool result =_mainDevice.VacuumPumpEnable(); if (!result) { NotifyError(eEvent.ERR_VPW, "pump enable failed", 0); } else { _pumpDownTime = DateTime.Now; } return result; } /// /// 检验真空 /// /// private bool CheckVacuumValue() { double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure; if (vacuumValue >= _recipe.VacuumTarget) { return true; } if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownWarningTime) { AlarmListManager.Instance.AddWarn(Module, "vacuum value", $"vacuum value {vacuumValue} is less than {_recipe.VacuumTarget}"); } if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownTimeOut) { _isNeedRetry = true; } return false; } /// /// 检验Lid Release真空数值 /// /// private bool CheckLidReleaseVacuum() { double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure; return vacuumValue >= _lidReleasePressure; } /// /// open vent valve /// /// private bool OpenVentValve() { bool result = _vpwCellDevice.VentValveOn(); if (!result) { NotifyError(eEvent.ERR_VPW, "open vent valve failed", 0); } return result; } /// /// close vent valve /// /// private bool CloseVentValve() { bool result = _vpwCellDevice.VentValveOff(); if (!result) { NotifyError(eEvent.ERR_VPW, "close vent valve failed", 0); } return result; } /// /// Chamber down /// /// private bool ChamberDown() { bool result= _mainDevice.ChamberDown(); if (!result) { NotifyError(eEvent.ERR_VPW, "chamber down failed",0); } return result; } /// /// 检验Chamber是否打开 /// /// private bool CheckChamberOpened() { return _mainDevice.CommonData.ChamberOpened && !_mainDevice.CommonData.ChamberClosed; } /// /// Chamber up /// /// private bool ChamberUp() { bool result = _mainDevice.ChamberUp(); if (!result) { NotifyError(eEvent.ERR_VPW, "chamber up failed", 0); } return result; } /// /// 检验Chamber是否关闭 /// /// private bool CheckChamberClosed() { return !_mainDevice.CommonData.ChamberOpened && _mainDevice.CommonData.ChamberClosed; } /// /// 检验真空 /// /// private bool LastCheckVacuumValue() { double vacuumValue = _vpwCellDevice.CommonData.VacuumPressure; if (vacuumValue >= _recipe.VacuumTarget) { return true; } if (DateTime.Now.Subtract(_pumpDownTime).TotalMilliseconds >= _pumpDownWarningTime) { AlarmListManager.Instance.AddWarn(Module, "vacuum value", $"vacuum value {vacuumValue} is less than {_recipe.VacuumTarget}"); } return false; } /// /// 打开相应的cell valve /// /// private bool OpenCellValve() { int count = 0; int enableCount = 0; if (_recipe.VacuumPrewetDripEnable) { count += _vpwCellDevice.FlowDripOn()?1:0; enableCount++; } if (_recipe.VacuumPrewetLargeEnable) { count += _vpwCellDevice.FlowLargeOn() ? 1 : 0; enableCount++; } if (_recipe.VacuumPrewetSmallEnable) { count += _vpwCellDevice.FlowSmallOn() ? 1 : 0; enableCount++; } bool result = StartRotation(); if (!result) { NotifyError(eEvent.ERR_VPW, "start rotation failed", 0); return false; } result= count == enableCount; if (!result) { NotifyError(eEvent.ERR_VPW, "open cell valve failed", 0); } return result; } /// /// 同时旋转 /// /// private bool StartRotation() { int targetPosition = 0; int maxSpeed = 0; int second = 0; foreach(var item in _recipe.VacuumRinseStep) { second += item.DurationSeconds; int speed = item.RotationSpeed; if (maxSpeed < speed) { maxSpeed = speed; } } foreach(var item in _recipe.VentRinseStep) { second += item.DurationSeconds; int speed = item.RotationSpeed; if (maxSpeed < speed) { maxSpeed = speed; } } foreach(var item in _recipe.ExtendCleanRinseStep) { second += item.DurationSeconds; int speed = item.RotationSpeed; if (maxSpeed < speed) { maxSpeed = speed; } } targetPosition = maxSpeed * (second + 60 * 1000);//按最大速度*(时间+多出一分钟) _vpwCellDevice.SetRotationSpeed(_recipe.VacuumRinseStep[0].RotationSpeed / 6); return _vpwCellDevice.RotationProfilePosition(targetPosition); } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _recipe=(VpwRecipe)objs[0]; _vpwCellDevice = DEVICE.GetDevice(Module); _mainDevice = DEVICE.GetDevice(ModuleName.VPWMain1.ToString()); _pumpDownWarningTime = SC.GetValue($"{Module}.PumpDownWarningTime")*1000; _pumpDownTimeOut = SC.GetValue($"{Module}.PumpDownTimeout")*1000; _lidReleasePressure = SC.GetValue($"{Module}.LidReleasePressure"); _lidReleasePressureTimeout = SC.GetValue($"{Module}.LidReleasePressureTimeout"); _isNeedRetry = false; return Runner.Start(Module, $"{Module} prepare"); } /// /// 重试 /// /// public RState Retry(int step) { if (_recipe == null) { NotifyError(eEvent.ERR_RINSE, "recipe is null", -1); return RState.Failed; } List preStepIds = new List(); return Runner.Retry(PrepareStep.OpenVacuumValve, preStepIds, Module, "Vacuum Prewet Retry"); } } }