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);
}
}
}
}
}