using Aitex.Core.RT.Device; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.RecipeCenter; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.Routine; using CyberX8_Core; using CyberX8_RT.Devices.Resistivity; using CyberX8_RT.Devices.Rinse; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CyberX8_RT.Modules.Rinse { public class RinseFirstStepRoutine : RoutineBase, IRoutine { private enum RinseFirstStep { StartPrepare, FirstDrain, CheckDrain, WaitDrianEmpty, N2BubbleOn, N2BubbleOnDelay, Recipe_StartFirstRinseCycle, Recipe_PerformFirstRinseCycle, Recipe_FirstRinseCycleStartFilling, Recipe_FirstRinseCycleRecordStartWaterLevel, Recipe_FirstRinseCycleStartFillingWait, Recipe_FirstRinseCycleWaitFillingDetected, Recipe_FirstRinseCycleWaitFull, Recipe_FirstRinseCycleWaitEndFillTime, Recipe_FirstRinseCycleWaitDwell, Recipe_FirstRinseCycleWaitDrain, Recipe_FirstRinseCycleCheckDrain, Recipe_FirstRinseCycleWaitDrainExtraTime, Recipe_FirstRinseCycleEnd, Recipe_FirstRinseCycleComplete } #region 内部变量 /// /// 设备对象 /// private RinseDevice _device; /// /// Recipe /// private QdrRecipe _recipe; /// /// Fill打开注水记录Water Level /// private double _fillingDetectStartWaterLevel; /// /// 配置文件中注水整个过程的耗时 /// private int _concurrentFillTimeSeconds; /// /// 开始注水的偏差 /// private double _fillingStartedDelta; /// /// 注满数值 /// private int _sensorReadingFull; /// /// 液位为空数值 /// private int _sensorReadingEmpty; /// /// 开始流水时间 /// private DateTime _startFillTime; /// /// 从开始排水到检测是否排空的间隔时间 /// private int _normalDrainTimeSeconds; /// /// 开始注水后检测是否正常注水间隔 /// private int _checkIsFillingTimeSeconds; /// /// 开始注水后检测是否注满间隔 /// private int _checkIsFullTimeSeconds; /// /// 当前执行到哪一步的显示 /// private string _currentStateMachine; #endregion /// /// 构造函数 /// /// public RinseFirstStepRoutine(string module) : base(module) { } /// /// 启动 /// /// /// public RState Start(params object[] objects) { _device = DEVICE.GetDevice(Module); _recipe = objects[0] as QdrRecipe; _concurrentFillTimeSeconds = SC.GetValue("QDR.ConcurrentFillTimeSeconds"); _fillingStartedDelta = SC.GetValue("QDR.FillingStartedDelta"); _sensorReadingFull = SC.GetValue("QDR.SensorReadingFull"); _sensorReadingEmpty = SC.GetValue("QDR.SensorReadingEmpty"); _normalDrainTimeSeconds = SC.GetValue("QDR.NominalDrainTimeSeconds"); _checkIsFillingTimeSeconds = SC.GetValue("QDR.NominalCheckFillWaterTimeSeconds"); _checkIsFullTimeSeconds = SC.GetValue("QDR.NominalCheckFillFullTimeSeconds"); _fillingDetectStartWaterLevel = 0; //配置项规范性验证 if (_checkIsFillingTimeSeconds + _checkIsFullTimeSeconds > _concurrentFillTimeSeconds) { NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalCheckFillWaterTimeSeconds' plus 'QDR.NominalCheckFillFullTimeSeconds' is large than QDR.ConcurrentFillTimeSeconds",-1); return RState.Failed; } if (_normalDrainTimeSeconds > _recipe.DumpTimeSeconds) { NotifyError(eEvent.ERR_RINSE, $"configuration item 'QDR.NominalDrainTimeSeconds' is large than 'recipe.DumpTimeSeconds",-1); return RState.Failed; } return Runner.Start(Module, "Start Rinse First Step"); } /// /// Abort /// public void Abort() { Runner.Stop("Manual abort"); } /// /// 监控 /// /// public RState Monitor() { _currentStateMachine = Runner.CurrentStep.ToString(); _device.UpdateStateMachine(_currentStateMachine); //1.2-Start Runner.Run(RinseFirstStep.StartPrepare,StartPrepareAction, _delay_1ms) //1.3-WatiDrained .Run(RinseFirstStep.FirstDrain,OpenDrainValveandCheckMetalValve, _delay_1ms) .RunDelay(RinseFirstStep.CheckDrain, CheckWaterLevelEmpty, _normalDrainTimeSeconds*1000) //1.4-ExtraDrainDeylay .RunIf(RinseFirstStep.WaitDrianEmpty, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0, NullFun ,(_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000) //1.5-N2PreCharge .RunIf(RinseFirstStep.N2BubbleOn, _recipe.Step1N2BubbleOn, N2ValveOn, _delay_1ms) .RunIf(RinseFirstStep.N2BubbleOnDelay, _recipe.Step1N2BubbleOn, NullFun, _recipe.N2ChargeTimeSeconds*1000) //1.6-StartFirstRinseCylce .LoopStart(RinseFirstStep.Recipe_StartFirstRinseCycle, "Rinse first step", _recipe.Step1NumberOfRinse, PrepareStart, _delay_1ms) //1.7-PerformFirstRinseCycle .LoopRun(RinseFirstStep.Recipe_PerformFirstRinseCycle,OpenN2ValveAndCloseDumpValve,_delay_1ms) //1.8-FirstRinseCycleStartFilling .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleStartFilling, () => _device.FillValveOn(), _delay_1ms) .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleRecordStartWaterLevel, CheckFillValveOn, _delay_1ms) .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleStartFillingWait, CheckFillNormalStatus, _checkIsFillingTimeSeconds * 1000) //1.9-FirstRinseCycleWaitFillingDetected and 2.0-FirstRinseCycleWaitFull .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleWaitFillingDetected, CheckFillFullStatus, _checkIsFullTimeSeconds * 1000) //2.1-FirstRinseCycleWaitEndFillTime .LoopDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitEndFillTime, (_concurrentFillTimeSeconds - _checkIsFillingTimeSeconds- _checkIsFullTimeSeconds) * 1000) //2.2-FirstRinseCycleWaitDwell .LoopRunDelay(RinseFirstStep.Recipe_FirstRinseCycleWaitDwell, StartDwell, _recipe.Step1DwellTimeSeconds * 1000) //2.3-FirstRinseCycleWaitDrain .LoopRun(RinseFirstStep.Recipe_FirstRinseCycleWaitDrain, StartOpenDumpValve,_delay_1ms) .LoopRunOnlyTimeOutFault(RinseFirstStep.Recipe_FirstRinseCycleCheckDrain,CheckWaterLevelEmpty, _normalDrainTimeSeconds * 1000) //2.4-FirstRinseCycleWaitDrainExtraTime .LoopRunIf(RinseFirstStep.Recipe_FirstRinseCycleWaitDrainExtraTime, _recipe.DumpTimeSeconds - _normalDrainTimeSeconds > 0,NullFun, (_recipe.DumpTimeSeconds - _normalDrainTimeSeconds) * 1000 ) .LoopEnd(RinseFirstStep.Recipe_FirstRinseCycleEnd, NullFun, _delay_1ms) .End(RinseFirstStep.Recipe_FirstRinseCycleComplete, NullFun, _delay_1ms); return Runner.Status; } /// /// Close Fill valve 和 Clamp valve /// /// private bool StartPrepareAction() { bool result = _device.FillValveOff(); if (!result) { NotifyError(eEvent.ERR_RINSE, "Close Fill Valve error",0); return false; } result = _device.WaferHolderClampValveOn(); if (!result) { NotifyError(eEvent.ERR_RINSE, "Open Clamp Valve error", 0); return false; } return result; } /// /// 打开排水阀并且检查是否需要打开metal drain valve /// /// private bool OpenDrainValveandCheckMetalValve() { bool result = _device.DrainValveOn(); if (!result) { NotifyError(eEvent.ERR_RINSE, "Open Drain Valve error",0); return false; } if (_recipe.Step1NumberOfDumpToMetalDrain > 0) { result = _device.WasteValveOff(); if (!result) { NotifyError(eEvent.ERR_RINSE, "Open Metal Valve error", 0); return false; } } return result; } /// /// N2 Valve On /// /// private bool N2ValveOn() { return _device.N2ValveOn(); } /// /// 检验N2Valve on /// /// private bool CheckN2ValveOn() { return _device.RinseData.N2Valve; } /// /// 准备启动 /// /// private bool PrepareStart() { if (_recipe.Step1N2BubbleOn) { return _device.N2ValveOff(); } return true; } /// /// 启动N2和关闭Dump Valve /// /// private bool OpenN2ValveAndCloseDumpValve() { bool result = true; if(_recipe.Step1N2BubbleOn) { result = _device.N2ValveOn(); if(!result) { NotifyError(eEvent.ERR_RINSE, "Open N2 Valve error",0); return false; } } result = _device.DrainValveOff(); if(!result) { NotifyError(eEvent.ERR_RINSE, "Close Dump Valve error", 0); } return result; } /// /// 检验Fill Valve打开状态 /// /// private bool CheckFillValveOn() { _startFillTime = DateTime.Now; _fillingDetectStartWaterLevel = _device.RinseData.WaterLevel; return true; } /// /// 检验是否正常流水 /// /// private bool CheckFillNormalStatus() { double currentWaterLevel = _device.RinseData.WaterLevel; bool result =(currentWaterLevel-_fillingDetectStartWaterLevel)>_fillingStartedDelta; return result; } /// /// 检验是否注满 /// /// private bool CheckFillFullStatus() { double currentWaterLevel = _device.RinseData.WaterLevel; bool result= currentWaterLevel > _sensorReadingFull; return result; } /// /// 开始Dwell /// /// private bool StartDwell() { bool result = _device.FillValveOff(); if(!result) { NotifyError(eEvent.ERR_RINSE, "Fill Valve off error",0); return false; } if(_recipe.Step1N2BubbleOn) { result = _device.N2ValveOff(); if(!result) { NotifyError(eEvent.ERR_RINSE, "N2 Valve off error", 0); return false; } } return true; } /// /// 打开Dump Valve /// /// private bool StartOpenDumpValve() { CheckNeedCloseMetalDrain(); bool result = _device.DrainValveOn(); if(!result) { NotifyError(eEvent.ERR_RINSE, "Open Dump valve error",0); return false; } return result; } /// /// 检验快排是否排空 /// /// private bool CheckWaterLevelEmpty() { double currentWaterLevel = _device.RinseData.WaterLevel; bool reseult = currentWaterLevel < _sensorReadingEmpty; if (!reseult) { NotifyError(eEvent.ERR_RINSE, $"current water level: {currentWaterLevel} is large than sensorReadingEmpty: {_sensorReadingEmpty}", 0); } return reseult; } /// /// 检验是否需要关闭Metal Valve20 /// /// private void CheckNeedCloseMetalDrain() { if (Runner.LoopCounter + 1>_recipe.Step1NumberOfDumpToMetalDrain) { bool result = _device.WasteValveOn(); if (!result) { NotifyError(eEvent.ERR_RINSE, "Close Metal Drain Valve error", 0); } } } } }