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.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PunkHPX8_RT.Modules.VpwCell { public class VpwExtendCleanRoutine : RoutineBase, IRoutine { private enum PrepareStep { OpenDrainValve, OpenCellValve, LoopStart, LoopRun, LoopEnd, End } #region 内部变量 /// /// recipe /// private VpwRecipe _recipe; /// /// 设备 /// private VpwCellDevice _vpwCellDevice; /// /// Main设备 /// private VpwMainDevice _mainDevice; /// /// 总时长 /// private int _totalMicrosecond = 0; /// /// 步骤 /// private int _stepIndex = 0; /// /// 启动步骤时间 /// private DateTime _startStepTime = DateTime.Now; #endregion /// /// 构造函数 /// /// public VpwExtendCleanRoutine(string module) : base(module) { } /// /// 中止 /// public void Abort() { Runner.Stop("Manual abort"); } /// /// 监控 /// /// public RState Monitor() { Runner.Run(PrepareStep.OpenDrainValve, OpenDrainValve, _delay_1ms) .Run(PrepareStep.OpenCellValve,OpenCellValve,_delay_1ms) .LoopStart(PrepareStep.LoopStart,"Loop Step",_recipe.VentRinseStep.Count,NullFun,_delay_1ms) .LoopRunWithStopStatus(PrepareStep.LoopRun, CheckStepComplete, () => { return false; }, _totalMicrosecond + 60 * 1000)//总时长再延迟1分种 .LoopEnd(PrepareStep.LoopEnd,NullFun,_delay_1ms) .End(PrepareStep.End,NullFun,_delay_1ms); return Runner.Status; } /// /// open vent valve /// /// private bool OpenDrainValve() { bool result = _vpwCellDevice.DrainValveOn(); if (!result) { NotifyError(eEvent.ERR_VPW, "open drain valve failed", 0); } return result; } /// /// 打开相应的cell valve /// /// private bool OpenCellValve() { int count = 0; int enableCount = 0; if (_recipe.ExtendCleanDripEnable) { count += _vpwCellDevice.FlowDripOn()?1:0; enableCount++; } if (_recipe.ExtendCleanLargeEnable) { count += _vpwCellDevice.FlowLargeOn() ? 1 : 0; enableCount++; } if (_recipe.ExtendCleanSmallEnable) { count += _vpwCellDevice.FlowSmallOn() ? 1 : 0; enableCount++; } bool result= count == enableCount; if (!result) { NotifyError(eEvent.ERR_VPW, "open cell valve failed", 0); } foreach (var item in _recipe.ExtendCleanRinseStep) { _totalMicrosecond += item.DurationSeconds * 1000; } _startStepTime = DateTime.Now; _stepIndex = 0; return result; } /// /// 检验步骤是否完成 /// /// private bool CheckStepComplete() { _mainDevice.CellFlow = _vpwCellDevice.CommonData.DiwFlow; if (_stepIndex >= _recipe.ExtendCleanRinseStep.Count) { LOG.WriteLog(eEvent.INFO_VPW, Module, $"step {_stepIndex} is over step count {_recipe.ExtendCleanRinseStep.Count}"); return true; } int length = _recipe.ExtendCleanRinseStep[_stepIndex].DurationSeconds; if (DateTime.Now.Subtract(_startStepTime).TotalSeconds >= length) { _stepIndex++; _startStepTime = DateTime.Now; if (_stepIndex >= _recipe.ExtendCleanRinseStep.Count) { LOG.WriteLog(eEvent.INFO_VPW, Module, $"step {_stepIndex} is over step count {_recipe.ExtendCleanRinseStep.Count}"); return true; } bool result = _vpwCellDevice.ChangeRotationSpeed(_recipe.ExtendCleanRinseStep[_stepIndex].RotationSpeed*6); if (result) { LOG.WriteLog(eEvent.INFO_VPW, Module, $"step {_stepIndex} complete"); } return result; } int firstDelay = SC.GetValue($"{Module}.FlowCheckDelay") * 1000; if (DateTime.Now.Subtract(_startStepTime).TotalMilliseconds >= firstDelay) { bool abnormal = CheckDisable(); if (abnormal) { return false; } } return false; } /// /// 检验数据 /// /// private bool CheckDisable() { double flow = _vpwCellDevice.CommonData.DiwFlow; double lowError = _recipe.ExtendCleanFlowSetPoint * (1 - (double)_recipe.ExtendCleanFlowErrorPercent / 100); double upError = _recipe.ExtendCleanFlowSetPoint * (1 + (double)_recipe.ExtendCleanFlowErrorPercent / 100); double lowWarn = _recipe.ExtendCleanFlowSetPoint * (1 - (double)_recipe.ExtendCleanFlowWarningPercent / 100); double upWarn = _recipe.ExtendCleanFlowSetPoint * (1 + (double)_recipe.ExtendCleanFlowWarningPercent / 100); if (flow upError) { NotifyError(eEvent.ERR_VPW, $"{Module} cell flow {flow} is up than {upError} ", 0); Abort(); return true; } if ((flow <= upError && flow >= upWarn) || (flow >= lowError && flow <= lowWarn)) { string str = $"{Module} cell flow {flow} is in warning"; if (AlarmListManager.Instance.AddWarn(Module, $"{Module} cell flow", str)) { LOG.WriteLog(eEvent.WARN_VPW, Module, str); } } bool isSimulatorMode = SC.GetValue("System.IsSimulatorMode"); if (!isSimulatorMode) { if (!_vpwCellDevice.CheckRotationRunning()) { NotifyError(eEvent.ERR_VPW, $"{Module} rotation is stopped", 0); Abort(); return true; } } return false; } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _recipe=(VpwRecipe)objs[0]; _vpwCellDevice = DEVICE.GetDevice(Module); _mainDevice = DEVICE.GetDevice(ModuleName.VPWMain1.ToString()); _totalMicrosecond = 0; _stepIndex = 0; return Runner.Start(Module, $"{Module} extend clean"); } /// /// 重试 /// /// public RState Retry(int step) { if (_recipe == null) { NotifyError(eEvent.ERR_VPW, "recipe is null", -1); return RState.Failed; } List preStepIds = new List(); return Runner.Retry(PrepareStep.OpenDrainValve, preStepIds, Module, "Extend clean Retry"); } } }