Browse Source

add reservoir flow check;
update different recipe scheduler

chenkui 4 days ago
parent
commit
0a521ad09f

+ 1 - 1
CyberX8_RT/Config/System.sccfg

@@ -235,7 +235,7 @@
 		<config default="0.125" name="ShortTestThreshold" nameView="ShortTestThreshold" description="short test threshold" max="1" min="0" paramter="" tag="" unit="A" type="Double"/>		
 		<config default="100" name="WaferShuttleSoakMaxTime" nameView="WaferShuttleSoakMaxTime" description="Max Time Length of Wafer Shuttle Soak in metal" type="Integer" min="0" max="100000" paramter="" tag="" unit="minute"/>
 		<config default="10" name="CurrentCheckDelay" nameView="CurrentCheckDelay" description="After delay second to check current"  type="Integer" min="0" max="60" paramter="" tag="" unit="s" />
-
+		<config default="true" name="EnableFlowError" nameView="EnableFlowError" description="true-complete metal process then wafer status is changed to error,false-abort metal process then wafer status is changed to error" max="" min="" paramter="" tag="" unit="" type="Bool" />
 		<config default="5" name="CellFlowAlarmHoldoffTime" nameView="CellFlowAlarmHoldoffTime" description="CellFlow Alarm Holdoff Time" max="100" min="0" paramter="" tag="" unit="s" type="Double"/>
 		<config default="5" name="CurrentAlarmHoldoffTime" nameView="CurrentAlarmHoldoffTime" description="Current Alarm Holdoff Time" max="100" min="0" paramter="" tag="" unit="s" type="Double"/>
 		<config default="5" name="VoltageAlarmHoldoffTime" nameView="VoltageAlarmHoldoffTime" description="Voltage Alarm Holdoff Time" max="100" min="0" paramter="" tag="" unit="s" type="Double"/>

+ 118 - 58
CyberX8_RT/Devices/Reservoir/CompactMembranReservoirDevice.cs

@@ -89,6 +89,16 @@ namespace CyberX8_RT.Devices.Reservoir
         private const string COUNTER_STOP = "Stop";
         private const string COUNTER_RESET = "Reset";
         private const int ENABLE = 5;
+
+        private const string CA_FLOW_START_LOW_LIMIT_ERROR = "CaFlowStartLowLimitError";
+        private const string CA_FLOW_RECIPE_ERROR = "CaFlowRecipeError";
+        private const string CA_FLOW_RECIPE_WARN = "CaFlowRecipeWarn";
+        private const string AN_A_FLOW_ZERO_ERROR = "AnAFlowZeroError";
+        private const string AN_A_FLOW_RECIPE_ERROR = "AnAFlowRecipeError";
+        private const string AN_A_FLOW_RECIPE_WARN = "AnAFlowRecipeWarn";
+        private const string AN_B_FLOW_ZERO_ERROR = "AnBFlowZeroError";
+        private const string AN_B_FLOW_RECIPE_ERROR = "AnBFlowRecipeError";
+        private const string AN_B_FLOW_RECIPE_WARN = "AnBFlowRecipeWarn";
         #endregion
 
         #region 内部变量
@@ -121,6 +131,10 @@ namespace CyberX8_RT.Devices.Reservoir
         /// </summary>
         private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
         /// <summary>
+        /// 错误字典
+        /// </summary>
+        private Dictionary<string, bool> _errorDic = new Dictionary<string, bool>();
+        /// <summary>
         /// 数据
         /// </summary>
         private CompactMembranReservoirData _reservoirData = new CompactMembranReservoirData();
@@ -240,12 +254,6 @@ namespace CyberX8_RT.Devices.Reservoir
         /// CrossDose是否初始化
         /// </summary>
         private bool _isCrossDoseInitialized;
-        /// <summary>
-        /// WarningFlag
-        /// </summary>
-        private List<bool> _isCAFlowRateWARN;
-        private List<bool> _isANAFlowRateWARN;
-        private List<bool> _isANBFlowRateWARN;
         private bool _isTCControlWARN = false;
         /// <summary>
         /// flow fault hold off时长
@@ -445,6 +453,15 @@ namespace CyberX8_RT.Devices.Reservoir
                         if (metalDevice != null)
                         {
                             _metalDevices.Add(metalDevice);
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_A_FLOW_ZERO_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_A_FLOW_RECIPE_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_A_FLOW_RECIPE_WARN}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_B_FLOW_RECIPE_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_B_FLOW_RECIPE_WARN}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{AN_B_FLOW_ZERO_ERROR}"] = false;
                         }
                     }
                 }
@@ -454,9 +471,6 @@ namespace CyberX8_RT.Devices.Reservoir
                     _crossDoseHelper = new CrossDoseHelper(Module);
                     _isCrossDoseInitialized = false;
                 }
-                _isCAFlowRateWARN = new List<bool>(new bool[_metalDevices.Count]);
-                _isANAFlowRateWARN = new List<bool>(new bool[_metalDevices.Count]);
-                _isANBFlowRateWARN = new List<bool>(new bool[_metalDevices.Count]);
             }
         }
         /// <summary>
@@ -2024,25 +2038,50 @@ namespace CyberX8_RT.Devices.Reservoir
                     if (!hotMetalDevice.FlowValveStable) continue;
                     MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(hotMetalDevice.Name);
                     double cellFlow = hotMetalDevice.MetalDeviceData.CellFlow;
-                    if (cellFlow < _resRecipe.CAFlowRateErrorLow)
+                    //double cellFlowStartLowLimit = SC.GetValue<double>("Metal.CellFlowStartLowLimit");
+                    if (cellFlow <= 0)
                     {
-                        if (!metalEntity.IsError)
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"])
                         {
-                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = true;
+                            string reason = $"{hotMetalDevice.Name} cellflow:{cellFlow} is less or equal 0";
+                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
                             metalEntity.PostMsg(MetalMsg.Error);
+                            metalEntity.WriteErrorReason(reason);
                         }
+                        continue;
                     }
-                    else if (cellFlow < _resRecipe.CAFlowRateWarningLow)
+                    else
                     {
-                        if (!_isCAFlowRateWARN[i])
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = false;
+                    }
+                    if (cellFlow < _resRecipe.CAFlowRateErrorLow)
+                    {
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"])
                         {
-                            LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}");
-                            _isCAFlowRateWARN[i] = true;
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = true;
+                            string reason = $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}";
+                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
+                            metalEntity.SetFlowErrorFlag(reason);
                         }
+                        continue;
                     }
                     else
                     {
-                        _isCAFlowRateWARN[i] = false;
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = false;
+                    }
+
+                    if (cellFlow < _resRecipe.CAFlowRateWarningLow)
+                    {
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"])
+                        {
+                            LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}");
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = true;
+                        }
+                    }
+                    else
+                    {
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = false;
                     }
                 }
             }
@@ -2064,57 +2103,78 @@ namespace CyberX8_RT.Devices.Reservoir
                     if (hotMetalDevice.MetalDeviceData.ANAPinEnable && hotMetalDevice.ANAFlowValveStable)
                     {
                         double ANAcellFlow = hotMetalDevice.ANACellFlow.CounterValue;
-                        if (ANAcellFlow < _resRecipe.ANFlowRateErrorLow)
-                        {
-                            if (!metalEntity.IsError)
-                            {
-                                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} ANASideflow:{ANAcellFlow} is less than recipe's ANFlowRateErrorLow parameter:{_resRecipe.ANFlowRateErrorLow}");
-                                metalEntity.PostMsg(MetalMsg.Error);
-                            }
-                        }
-                        else if (ANAcellFlow < _resRecipe.ANFlowRateWarningLow)
-                        {
-                            if (!_isANAFlowRateWARN[i])
-                            {
-                                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} ANASideflow:{ANAcellFlow} is less than recipe's ANFlowRateWarningLow parameter:{_resRecipe.ANFlowRateWarningLow}");
-                                _isANAFlowRateWARN[i] = true;
-                            }
-                        }
-                        else
-                        {
-                            _isANAFlowRateWARN[i] = false;
-                        }
+                        AnSideFlowCheck(ANAcellFlow, metalEntity, "A", AN_A_FLOW_ZERO_ERROR, AN_A_FLOW_RECIPE_ERROR,
+                            AN_A_FLOW_RECIPE_WARN, _resRecipe.ANFlowRateErrorLow, _resRecipe.ANFlowRateWarningLow);
                     }
                     //ANBCellFlow
                     if (hotMetalDevice.MetalDeviceData.ANBPinEnable && hotMetalDevice.ANBFlowValveStable)
                     {
                         double ANBcellFlow = hotMetalDevice.ANBCellFlow.CounterValue;
-                        if (ANBcellFlow < _resRecipe.ANFlowRateErrorLow)
-                        {
-                            if (!metalEntity.IsError)
-                            {
-                                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} ANBSideflow:{ANBcellFlow} is less than recipe's ANFlowRateErrorLow parameter:{_resRecipe.ANFlowRateErrorLow}");
-                                metalEntity.PostMsg(MetalMsg.Error);
-                            }
-                        }
-                        else if (ANBcellFlow < _resRecipe.ANFlowRateWarningLow)
-                        {
-                            if (!_isANBFlowRateWARN[i])
-                            {
-                                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} ANBSideflow:{ANBcellFlow} is less than recipe's ANFlowRateWarningLow parameter:{_resRecipe.ANFlowRateWarningLow}");
-                                _isANBFlowRateWARN[i] = true;
-                            }
-
-                        }
-                        else
-                        {
-                            _isANBFlowRateWARN[i] = false;
-                        }
+                        AnSideFlowCheck(ANBcellFlow, metalEntity, "B", AN_B_FLOW_ZERO_ERROR, AN_B_FLOW_RECIPE_ERROR,
+                            AN_B_FLOW_RECIPE_WARN, _resRecipe.ANFlowRateErrorLow, _resRecipe.ANFlowRateWarningLow);
                     }
                 }
             }
         }
         /// <summary>
+        /// 阳极单面Flow检验
+        /// </summary>
+        /// <param name="anCellFlow"></param>
+        /// <param name="metalEntity"></param>
+        /// <param name="side"></param>
+        /// <param name="flowZeroError"></param>
+        /// <param name="anFlowRecipeError"></param>
+        /// <param name="anFlowRecipeWarn"></param>
+        /// <param name="anFlowRecipeErrorLow"></param>
+        /// <param name="anFlowRecipeWarnLow"></param>
+        private void AnSideFlowCheck(double anCellFlow, MetalEntity metalEntity, string side, string flowZeroError,
+            string anFlowRecipeError, string anFlowRecipeWarn, double anFlowRecipeErrorLow, double anFlowRecipeWarnLow)
+        {
+            if (anCellFlow <= 0)
+            {
+                if (!_errorDic[$"{metalEntity.Module}_{flowZeroError}"])
+                {
+                    _errorDic[$"{metalEntity.Module}_{flowZeroError}"] = true;
+                    string reason = $"{metalEntity.Module} AN{side}Sideflow:{anCellFlow} is less or equal 0";
+                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
+                    metalEntity.PostMsg(MetalMsg.Error);
+                    metalEntity.WriteErrorReason(reason);
+                }
+                return;
+            }
+            else
+            {
+                _errorDic[$"{metalEntity.Module}_{flowZeroError}"] = false;
+            }
+            if (anCellFlow < anFlowRecipeErrorLow)
+            {
+                if (!_errorDic[$"{metalEntity.Module}_{anFlowRecipeError}"])
+                {
+                    _errorDic[$"{metalEntity.Module}_{anFlowRecipeError}"] = true;
+                    string reason = $"{metalEntity.Module} AN{side}Sideflow:{anCellFlow} is less than recipe ANFlowRateErrorLow parameter:{anFlowRecipeErrorLow}";
+                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
+                    metalEntity.SetFlowErrorFlag(reason);
+                }
+                return;
+            }
+            else
+            {
+                _errorDic[$"{metalEntity.Module}_{anFlowRecipeError}"] = false;
+            }
+            if (anCellFlow < anFlowRecipeWarnLow)
+            {
+                if (!_errorDic[$"{metalEntity.Module}_{anFlowRecipeWarn}"])
+                {
+                    LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{metalEntity.Module} AN{side}Sideflow:{anCellFlow} is less than recipe ANFlowRateWarningLow parameter:{anFlowRecipeWarnLow}");
+                    _errorDic[$"{metalEntity.Module}_{anFlowRecipeWarn}"] = true;
+                }
+            }
+            else
+            {
+                _errorDic[$"{metalEntity.Module}_{anFlowRecipeWarn}"] = false;
+            }
+        }
+        /// <summary>
         /// Temperature Check
         /// </summary>
         private void TemperatureCheck()

+ 44 - 22
CyberX8_RT/Devices/Reservoir/StandardHotReservoirDevice.cs

@@ -72,6 +72,10 @@ namespace CyberX8_RT.Devices.Reservoir
         private const string REGULATE_PUMP = "RegulatePumpOn";
         private const string REGULATE_PUMP_SIGNAL_IN = "RegulatePumpSignalIn";
         private const string REGULATE_PUMP_SPEED = "RegulatePumpSpeed";
+
+        private const string CA_FLOW_START_LOW_LIMIT_ERROR = "CaFlowStartLowLimitError";
+        private const string CA_FLOW_RECIPE_ERROR = "CaFlowRecipeError";
+        private const string CA_FLOW_RECIPE_WARN = "CaFlowRecipeWarn";
         #endregion
 
         #region 内部变量
@@ -108,6 +112,10 @@ namespace CyberX8_RT.Devices.Reservoir
         /// </summary>
         private ReservoirOperation _currentOperation = ReservoirOperation.None;
         /// <summary>
+        /// 错误字典
+        /// </summary>
+        private Dictionary<string, bool> _errorDic = new Dictionary<string, bool>();
+        /// <summary>
         /// 手动注水时间(秒)
         /// </summary>
         private int _manualReplenSecond = 0;
@@ -176,10 +184,6 @@ namespace CyberX8_RT.Devices.Reservoir
         /// </summary>
         private DosingCommonHelper _dosingCommonHelper;
         /// <summary>
-        /// WarningFlag
-        /// </summary>
-        private List<bool> _isCAFlowRateWARN;
-        /// <summary>
         /// CMM Flow High Error
         /// </summary>
         private double _reservoirCMMFlowHighError;
@@ -794,6 +798,10 @@ namespace CyberX8_RT.Devices.Reservoir
                         if (metalDevice != null)
                         {
                             _metalDevices.Add(metalDevice);
+
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = false;
+                            _errorDic[$"{metalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = false;
                             _holdoffTimeSignalDic.Add($"{item.ModuleName}_CellFlow", new HoldoffTimeSignalMonitor(item.ModuleName, "CellFlow"));
                         }
                     }
@@ -806,7 +814,6 @@ namespace CyberX8_RT.Devices.Reservoir
                 }
                 _isCMMConfig = !string.IsNullOrEmpty(reservoirItem.CMMType);
             }
-            _isCAFlowRateWARN = new List<bool>(new bool[_metalDevices.Count]);
             //DosingSystem数据初始化            
             _replenType = reservoirItem.ChemReplenType;
             _replenNum = reservoirItem.ChemReplenPumps;
@@ -1635,34 +1642,49 @@ namespace CyberX8_RT.Devices.Reservoir
                     if (!hotMetalDevice.FlowValveStable) continue;
                     MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(hotMetalDevice.Name);
                     double cellFlow = hotMetalDevice.MetalDeviceData.CellFlow;
-                    //if (cellFlow < _resRecipe.CAFlowRateErrorLow)
-                    //{
-                    //    if (!metalEntity.IsError)
-                    //    {
-                    //        LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"cell {hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
-                    //        metalEntity.PostMsg(MetalMsg.Error);
-                    //    }
-                    //}
-                    bool cellFlowSignalresulte = _holdoffTimeSignalDic[$"{hotMetalDevice.Name}_CellFlow"].IsSignalAbnormal(_cellFlowHoldoffTime, cellFlow, null, _resRecipe.CAFlowRateErrorLow);
-                    if (cellFlowSignalresulte)
+                    if (cellFlow <= 0)
                     {
-                        if (!metalEntity.IsError)
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"])
                         {
-                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = true;
+                            string reason = $"{hotMetalDevice.Name} cellflow:{cellFlow} is less or equal 0";
+                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
                             metalEntity.PostMsg(MetalMsg.Error);
+                            metalEntity.WriteErrorReason(reason);
                         }
+                        continue;
+                    }
+                    else
+                    {
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_START_LOW_LIMIT_ERROR}"] = false;
                     }
-                    else if (cellFlow < _resRecipe.CAFlowRateWarningLow)
+                    if (cellFlow < _resRecipe.CAFlowRateErrorLow)
+                    {
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"])
+                        {
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = true;
+                            string reason = $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}";
+                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, reason);
+                            metalEntity.SetFlowErrorFlag(reason);
+                        }
+                        continue;
+                    }
+                    else
+                    {
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_ERROR}"] = false;
+                    }
+
+                    if (cellFlow < _resRecipe.CAFlowRateWarningLow)
                     {
-                        if (!_isCAFlowRateWARN[i])
+                        if (!_errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"])
                         {
-                            LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"cell {hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}");
-                            _isCAFlowRateWARN[i] = true;
+                            LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe CAFlowRateWarningLow parameter:{_resRecipe.CAFlowRateWarningLow}");
+                            _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = true;
                         }
                     }
                     else
                     {
-                        _isCAFlowRateWARN[i] = false;
+                        _errorDic[$"{hotMetalDevice.Module}_{CA_FLOW_RECIPE_WARN}"] = false;
                     }
                 }
             }

+ 65 - 63
CyberX8_RT/Dispatch/WaferHolderTaskManager.cs

@@ -43,103 +43,105 @@ namespace CyberX8_RT.Dispatch
         /// </summary>
         public bool CreateWaferHolderTask(List<ProcessJobInfo> jobs)
         {
+            if (CheckEnableCreateWaferHolderTask())
+            {
+                return false;
+            }
             SequenceRecipe sequenceRecipe = jobs[0].SequenceRecipe;
             List<string> chemistries = SchedulerSequenceRecipeManager.Instance.GetSequenceChemistry(sequenceRecipe);
             WaferSize waferSize = (WaferSize)sequenceRecipe.SubstrateSize;
             WaferHolderInfo waferHolderInfo = SchedulerManager.Instance.GetAvaibleBufferToLoaderWaferHolder(waferSize,sequenceRecipe.CrsType,chemistries);
             if (waferHolderInfo != null && CheckWaferHolderNotExist(waferHolderInfo))
             {
-                if (CheckEnableCreateWaferHolderTask())
+                if(!Enum.TryParse(waferHolderInfo.CurrentLocation,out ModuleName locationModuleName))
+                {
+                    return false;
+                }
+                if (ModuleHelper.IsBuffer(locationModuleName)&&string.IsNullOrEmpty(waferHolderInfo.OriginalBuffer))
+                {
+                    waferHolderInfo.OriginalBuffer = waferHolderInfo.CurrentLocation;
+                }
+                WaferHolderTask waferHolderTask = new WaferHolderTask(waferHolderInfo, jobs[0]);
+                waferHolderTask.OnTaskComplete += WaferHolderTask_OnTaskComplete;                   
+                WaferInfo waferInfo = GetPreLoaderHasWafer();
+                int productWaferCount = 0;
+                int dummyWaferCount = 0;
+                if (waferInfo==null)
                 {
-                    if(!Enum.TryParse(waferHolderInfo.CurrentLocation,out ModuleName locationModuleName))
+                    var result= WaferTaskManager.Instance.CreateWaferTask(jobs, waferHolderInfo, waferHolderTask);
+                    productWaferCount = result.productWaferCount;
+                    dummyWaferCount= result.dummyWaferCount;
+                }
+                else
+                {
+                    if(!CheckWaferMatchedWaferHolderTaskNotCreated(waferInfo))
                     {
                         return false;
                     }
-                    if (ModuleHelper.IsBuffer(locationModuleName)&&string.IsNullOrEmpty(waferHolderInfo.OriginalBuffer))
-                    {
-                        waferHolderInfo.OriginalBuffer = waferHolderInfo.CurrentLocation;
-                    }
-                    WaferHolderTask waferHolderTask = new WaferHolderTask(waferHolderInfo, jobs[0]);
-                    waferHolderTask.OnTaskComplete += WaferHolderTask_OnTaskComplete;                   
-                    WaferInfo waferInfo = GetPreLoaderHasWafer();
-                    int productWaferCount = 0;
-                    int dummyWaferCount = 0;
-                    if (waferInfo==null)
+                    string waferHasMatch = WaferTaskManager.Instance.CheckWaferHasMatch(waferInfo.WaferID);
+                    if(string.IsNullOrEmpty(waferHasMatch))
                     {
-                        var result= WaferTaskManager.Instance.CreateWaferTask(jobs, waferHolderInfo, waferHolderTask);
-                        productWaferCount = result.productWaferCount;
-                        dummyWaferCount= result.dummyWaferCount;
+                        if (waferInfo.WaferType == WaferType.Production)
+                        {
+                            productWaferCount = 1;
+                            dummyWaferCount = 0;
+                        }
+                        else
+                        {
+                            productWaferCount = 0;
+                            dummyWaferCount = 1;
+                        }
                     }
                     else
                     {
-                        if(!CheckWaferMatchedWaferHolderTaskNotCreated(waferInfo))
-                        {
-                            return false;
-                        }
-                        string waferHasMatch = WaferTaskManager.Instance.CheckWaferHasMatch(waferInfo.WaferID);
-                        if(string.IsNullOrEmpty(waferHasMatch))
+                        WaferInfo matchWafer = WaferManager.Instance.GetWaferByWaferId(waferHasMatch);
+                        if (matchWafer == null || matchWafer.IsEmpty)
                         {
                             if (waferInfo.WaferType == WaferType.Production)
                             {
                                 productWaferCount = 1;
-                                dummyWaferCount = 0;
                             }
                             else
                             {
-                                productWaferCount = 0;
                                 dummyWaferCount = 1;
                             }
                         }
                         else
                         {
-                            WaferInfo matchWafer = WaferManager.Instance.GetWaferByWaferId(waferHasMatch);
-                            if (matchWafer == null || matchWafer.IsEmpty)
+                            if (waferInfo.WaferType == WaferType.Production)
                             {
-                                if (waferInfo.WaferType == WaferType.Production)
-                                {
-                                    productWaferCount = 1;
-                                }
-                                else
-                                {
-                                    dummyWaferCount = 1;
-                                }
+                                productWaferCount = 1;
                             }
                             else
                             {
-                                if (waferInfo.WaferType == WaferType.Production)
-                                {
-                                    productWaferCount = 1;
-                                }
-                                else
-                                {
-                                    dummyWaferCount = 1;
-                                }
-                                if (matchWafer.WaferType == WaferType.Production)
-                                {
-                                    productWaferCount += 1;
-                                }
-                                else
-                                {
-                                    dummyWaferCount += 1;
-                                }
+                                dummyWaferCount = 1;
+                            }
+                            if (matchWafer.WaferType == WaferType.Production)
+                            {
+                                productWaferCount += 1;
+                            }
+                            else
+                            {
+                                dummyWaferCount += 1;
                             }
                         }
                     }
-                    if(productWaferCount+dummyWaferCount == 0)
-                    {
-                        return false;
-                    }
-                    _waferHolderTaskDic.TryAdd(waferHolderTask.ID, waferHolderTask);
-                    lock (_waferHolderTaskObject)
-                    {
-                        _waferTaskList.Add(waferHolderTask);
-                    }
-                    LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create wafer Shuttle {waferHolderInfo.Id} task");
-                    List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyWaferHolderAllSchedulerSequence(waferHolderInfo, jobs[0].SequenceRecipe,productWaferCount,dummyWaferCount);
-                    waferHolderTask.InitialSchedulers(sequences);
-
-                    return true;
                 }
+                if(productWaferCount+dummyWaferCount == 0)
+                {
+                    return false;
+                }
+                _waferHolderTaskDic.TryAdd(waferHolderTask.ID, waferHolderTask);
+                lock (_waferHolderTaskObject)
+                {
+                    _waferTaskList.Add(waferHolderTask);
+                }
+                LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create wafer Shuttle {waferHolderInfo.Id} task");
+                List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyWaferHolderAllSchedulerSequence(waferHolderInfo, jobs[0].SequenceRecipe,productWaferCount,dummyWaferCount);
+                waferHolderTask.InitialSchedulers(sequences);
+
+                return true;
+                
             }
             return false;
         }

+ 7 - 2
CyberX8_RT/Dispatch/WaferTaskManager.cs

@@ -132,10 +132,15 @@ namespace CyberX8_RT.Dispatch
             {
                 return (0,0);
             }
-            for(int i=0; i<processJobInfos.Count;i++)
+            string sequence = processJobInfos[0].SequenceRecipe.Ppid;
+            for (int i=0; i<processJobInfos.Count;i++)
             {
                 ProcessJobInfo processJobInfo = processJobInfos[i];
-                for(int j=0;j< processJobInfo.SlotWafers.Count; j++)
+                if (processJobInfo.SequenceRecipe.Ppid != sequence)
+                {
+                    continue;
+                }
+                for (int j=0;j< processJobInfo.SlotWafers.Count; j++)
                 {
                     var item = processJobInfo.SlotWafers[j];
                     if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2))

+ 1 - 1
CyberX8_RT/Modules/EFEM/EfemPlaceRoutine.cs

@@ -197,7 +197,7 @@ namespace CyberX8_RT.Modules.EFEM
                 Runner.WaitIf(PlaceStep.WaitIdle, _isAligner, WaitModuleReady)
                     .RunIf(PlaceStep.SetAlignWaferSize, _isAligner, SetAlignerWaferSize, _delay_1ms)
                      .Wait(PlaceStep.WaitWaferSizeIdle, WaitModuleReady)
-                    .RunIf(PlaceStep.SetAlignWaferSize, _isAligner, SetAlignerDistance, _delay_1ms)
+                    .RunIf(PlaceStep.SetAlignDistance, _isAligner, SetAlignerDistance, _delay_1ms)
                      .Wait(PlaceStep.WaitAlignDistanceIdle, WaitModuleReady)
                     .Wait(PlaceStep.WaitModuleReady, WaitModuleReady)
                         .Run(PlaceStep.Placing1,           Place1,         Place1Done,     _moveTimeout)

+ 97 - 76
CyberX8_RT/Modules/Metal/MetalEntity.cs

@@ -31,6 +31,7 @@ using CyberX8_RT.Modules.EFEM;
 using static Mono.Security.X509.X520;
 using MECF.Framework.Common.DBCore;
 using Aitex.Core.Common;
+using Aitex.Core.RT.Routine;
 
 namespace CyberX8_RT.Modules.Metal
 {
@@ -134,6 +135,11 @@ namespace CyberX8_RT.Modules.Metal
         /// Wafershuttle最大浸泡时间
         /// </summary>
         private int _waferShuttleSoakMaxTime;
+
+        /// <summary>
+        /// Flow错误标识
+        /// </summary>
+        private bool _flowErrorFlag = false;
         #endregion
 
         #region 属性
@@ -457,6 +463,7 @@ namespace CyberX8_RT.Modules.Metal
                     _compactEmbranceRunRecipeRoutine.Abort();
                 }
             }
+            _flowErrorFlag = false;
             return true;
         }
         /// <summary>
@@ -505,14 +512,20 @@ namespace CyberX8_RT.Modules.Metal
                     return false;
                 }
             }
+            bool result = false;
             if (_metalItem.SubType == STRATUS)
             {
-                return _standardHotInitializeRoutine.Start(_persistentValue) == RState.Running;
+                result= _standardHotInitializeRoutine.Start(_persistentValue) == RState.Running;
             }
             else
             {
-                return _compactEmbranceInitializeRoutine.Start(_persistentValue) == RState.Running;
+                result= _compactEmbranceInitializeRoutine.Start(_persistentValue) == RState.Running;
             }
+            if (result)
+            {
+                _flowErrorFlag = false;
+            }
+            return result;
         }
         /// <summary>
         /// 检验Reservoir是否Initialized
@@ -648,91 +661,26 @@ namespace CyberX8_RT.Modules.Metal
             }
             if (rsstate == RState.End)
             {
-                _recipeTime = 0;
-                if (WaferHolderInfo != null)
-                {
-                    double anodeAUsage = GetAnodeAUsage();
-                    double anodeBUsage = GetAnodeBUsage();
-                    MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage);
-                    MetalUsageMointor(); //检查PMCounter消耗
-                    //CMM Usage
-                    string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
-                    if (_metalItem.SubType == STRATUS)
-                    {
-                        StandardHotReservoirDevice resDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
-                        resDevice.ReservoirUsageMonitor();
-                        resDevice.SetExportCMMUsage();
-                    }
-                    WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
-                    _isCurrentReceipeComplete = true;
-                    _currentWaferShuttleStartSoakTime = DateTime.Now;
-                }
-                _runrecipeElapsedTime = 0;
-
-                //记录LotTrack
-                _runRecipeCompleteTime = DateTime.Now;
-                int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds;
-                if (_metalItem.SubType == STRATUS)
-                {
-                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
-                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
-                        _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
-                }
-                else
-                {
-                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
-                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
-                        _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
-                }
+                RecipeCompleteRecord();
                 if (WaferHolderInfo != null && _currentRecipe != null)
                 {
+                    int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds;
                     FaModuleNotifier.Instance.NotifyWaferShuttleRecipeEnd(WaferHolderInfo, _currentRecipe.Ppid, timeLength);
                 }
-
+                //流量错误标记后Metal变成Error
+                if (_flowErrorFlag)
+                {
+                    PostMsg(MetalMsg.Error);
+                    return false;
+                }
                 return true;
             }
             else if (rsstate == RState.Failed || rsstate == RState.Timeout)
             {
-                _recipeTime = 0;
-                if (WaferHolderInfo != null)
-                {
-                    double anodeAUsage = GetAnodeAUsage();
-                    double anodeBUsage = GetAnodeBUsage();
-                    MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage);
-                    MetalUsageMointor(); //失败了也要检查PMCounter消耗
-                    //CMMUsage
-                    string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
-                    if (_metalItem.SubType == STRATUS)
-                    {
-                        StandardHotReservoirDevice resDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
-                        resDevice.ReservoirUsageMonitor();
-                        resDevice.SetExportCMMUsage();
-                    }
-                }
-                _runrecipeElapsedTime = 0;
-                if (WaferHolderInfo != null && _currentRecipe != null)
-                {
-                    WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
-                }
+                RecipeCompleteRecord();
                 PostMsg(MetalMsg.Error);
-
-                //记录LotTrack
-                _runRecipeCompleteTime = DateTime.Now;
-                if (_metalItem.SubType == STRATUS)
-                {
-                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
-                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
-                        _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
-                }
-                else
-                {
-                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
-                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
-                        _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
-                }
                 if (WaferHolderInfo != null)
                 {
-                    WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
                     if (_currentRecipe != null)
                     {
                         FaModuleNotifier.Instance.NotifyWaferShuttleRecipeFailed(WaferHolderInfo, _currentRecipe.Ppid);
@@ -747,6 +695,52 @@ namespace CyberX8_RT.Modules.Metal
             return false;
         }
         /// <summary>
+        /// Recipe完成后纪录数据
+        /// </summary>
+        private void RecipeCompleteRecord()
+        {
+            _recipeTime = 0;
+            if (WaferHolderInfo != null)
+            {
+                double anodeAUsage = GetAnodeAUsage();
+                double anodeBUsage = GetAnodeBUsage();
+                MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage);
+                MetalUsageMointor(); //失败了也要检查PMCounter消耗
+                                     //CMMUsage
+                string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
+                if (_metalItem.SubType == STRATUS)
+                {
+                    StandardHotReservoirDevice resDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
+                    resDevice.ReservoirUsageMonitor();
+                    resDevice.SetExportCMMUsage();
+                }
+                else
+                {
+                    CompactMembranReservoirDevice resDevice = DEVICE.GetDevice<CompactMembranReservoirDevice>(reservoirName);
+                    resDevice.ReservoirUsageMonitor();
+                }
+                WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
+            }
+            _runrecipeElapsedTime = 0;
+
+            _isCurrentReceipeComplete = true;
+            _currentWaferShuttleStartSoakTime = DateTime.Now;
+            //记录LotTrack
+            _runRecipeCompleteTime = DateTime.Now;
+            if (_metalItem.SubType == STRATUS)
+            {
+                _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
+                MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
+                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
+            }
+            else
+            {
+                _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
+                MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
+                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
+            }
+        }
+        /// <summary>
         /// 写入错误原因
         /// </summary>
         /// <param name="reason"></param>
@@ -1145,6 +1139,33 @@ namespace CyberX8_RT.Modules.Metal
         }
         #endregion
 
+        #region Enter Flow Error
+        /// <summary>
+        /// 标记
+        /// </summary>
+        /// <returns></returns>
+        public bool SetFlowErrorFlag(string reason)
+        {
+            bool flowError = SC.GetValue<bool>("Metal.EnableFlowError");
+            if (!flowError)
+            {
+                PostMsg(MetalMsg.Error);
+            }
+            else
+            {
+                if (State == (int)MetalState.RunReciping)
+                {
+                    _flowErrorFlag = true;
+                }
+                else
+                {
+                    PostMsg(MetalMsg.Error);
+                }
+            }
+            WriteErrorReason(reason);
+            return true;
+        }
+        #endregion
         public bool Check(int msg, out string reason, params object[] args)
         {
             reason = "";

+ 8 - 0
Framework/Common/SubstrateTrackings/WaferManager.cs

@@ -275,6 +275,14 @@ namespace MECF.Framework.Common.SubstrateTrackings
 
         public WaferInfo  GetWafer(ModuleName module, int slot)
         {
+            if (!_locationWafers.ContainsKey(module))
+            {
+                return null;
+            }
+            if (!_locationWafers[module].ContainsKey(slot))
+            {
+                return null;
+            }
             return _locationWafers[module][slot];
         }