Ver código fonte

add reservoir hold off time Monitor

chenzk 3 semanas atrás
pai
commit
411483be01

+ 5 - 0
CyberX8_RT/Config/System.sccfg

@@ -231,6 +231,11 @@
 		<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="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"/>
+		
 		<configs name="Metal1" nameView="Metal1">
 				<config default="50" name="MetalTotalAmpHoursWarningLimit" nameView="MetalTotalAmpHoursWarningLimit"  type="Double" value="0"  min="0" max="100000" paramter="" tag="" unit=""/>
 				<config default="100" name="MetalTotalAmpHoursFaultLimit" nameView="MetalTotalAmpHoursFaultLimit"  type="Double" value="0"  min="0" max="100000" paramter="" tag="" unit="" description="" />

+ 1 - 0
CyberX8_RT/CyberX8_RT.csproj

@@ -275,6 +275,7 @@
     <Compile Include="Modules\EFEM\RobotCycleMoveRoutine.cs" />
     <Compile Include="Modules\EFEM\RobotCycleRoutine.cs" />
     <Compile Include="Modules\FaModuleNotifier.cs" />
+    <Compile Include="Modules\HoldoffTimeSignalMonitor.cs" />
     <Compile Include="Modules\Loader\LoaderLotTrackUtil.cs" />
     <Compile Include="Modules\Loader\LoaderLoadSideRoutine.cs" />
     <Compile Include="Modules\Loader\LoaderUnloadSideRoutine.cs" />

+ 25 - 2
CyberX8_RT/Devices/Reservoir/StandardHotReservoirDevice.cs

@@ -222,6 +222,14 @@ namespace CyberX8_RT.Devices.Reservoir
         /// 是否配备CMM
         /// </summary>
         private bool _isCMMConfig = false;
+        /// <summary>
+        /// holdofftime 配置项
+        /// </summary>
+        private double _cellFlowHoldoffTime;
+        /// <summary>
+        /// holdoff监控
+        /// </summary>
+        private HoldoffTimeSignalMonitor _cellFlowHoldoffTimeSignalMonitor;
         #endregion
 
         #region 属性
@@ -304,9 +312,15 @@ namespace CyberX8_RT.Devices.Reservoir
             levelSampleCount = SC.GetValue<int>("Reservoir.LevelAvgSamples");
             levelSampleCount = levelSampleCount == 0 ? 20 : levelSampleCount;
             _LevelSamples = new Queue<double>(levelSampleCount);
+
+            _cellFlowHoldoffTime = SC.GetValue<double>($"Metal.CellFlowAlarmHoldoffTime");
+            _cellFlowHoldoffTimeSignalMonitor = new HoldoffTimeSignalMonitor(Module, "CellFLow");
+
             _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
             ResPowerOn();//保持继电器常开
             ClearErrorLogSet(Module.ToString());//软件启动的时候也清一下ErrorLogSet
+
+      
         }
         /// <summary>
         /// 定时器
@@ -1486,11 +1500,20 @@ 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 (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 = _cellFlowHoldoffTimeSignalMonitor.IsSignalAbnormal(_cellFlowHoldoffTime, cellFlow, null, _resRecipe.CAFlowRateErrorLow);
+                    if (cellFlowSignalresulte)
                     {
                         if (!metalEntity.IsError)
                         {
-                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"cell {hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
+                            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{hotMetalDevice.Name} cellflow:{cellFlow} is less than recipe's CAFlowRateErrorLow parameter:{_resRecipe.CAFlowRateErrorLow}");
                             metalEntity.PostMsg(MetalMsg.Error);
                         }
                     }

+ 96 - 0
CyberX8_RT/Modules/HoldoffTimeSignalMonitor.cs

@@ -0,0 +1,96 @@
+using Aitex.Core.RT.Log;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CyberX8_RT.Modules
+{
+    public class HoldoffTimeSignalMonitor
+    {
+        #region 内部变量
+        /// <summary>
+        /// 初次检测到变量异常的时间
+        /// </summary>
+        private DateTime _abnormalStartTime;
+        /// <summary>
+        /// 变量信号是否异常
+        /// </summary>
+        private bool _isInAbnormalState = false;
+        /// <summary>
+        /// 模块名
+        /// </summary>
+        private string _module;
+        /// <summary>
+        /// 异常项名
+        /// </summary>
+        private string _itemName;
+        #endregion
+
+        public HoldoffTimeSignalMonitor(string Muodule,string ItemName)
+        {
+            _module = Muodule;
+            _itemName = ItemName;
+        }
+        /// <summary>
+        /// 判断信号是否超出holdofftime时间的异常
+        /// </summary>
+        /// <param name="holdoffTime"></param>
+        /// <param name="currentValue"></param>
+        /// <param name="maxLimit"></param>
+        /// <param name="minLimit"></param>
+        /// <returns></returns>
+        public bool IsSignalAbnormal(double holdoffTime,double currentValue,double? maxLimit,double? minLimit)
+        { 
+            bool isAbnormal = false;
+            if(CheckValueAbnormal(currentValue,maxLimit,minLimit)) //检测当前值是否异常
+            {
+                isAbnormal = true;
+            }
+            if(isAbnormal && !_isInAbnormalState)//首次检测到异常
+            {
+                LOG.WriteLog(eEvent.WARN_METAL, _module, $"{_module} {_itemName} is Abnormal,CurrentValue is :{currentValue}");
+                _isInAbnormalState = true;
+                _abnormalStartTime = DateTime.Now; 
+            }
+            if(!isAbnormal && _isInAbnormalState) // holdofftime时间内恢复
+            {
+                LOG.WriteLog(eEvent.INFO_METAL, _module, $"{_module} {_itemName} is restore");
+                _isInAbnormalState = false;
+            }
+            if((DateTime.Now - _abnormalStartTime).TotalSeconds > holdoffTime && _isInAbnormalState)//异常时间超过holdofftime
+            {
+                _isInAbnormalState = false;//报错前把状态清掉,防止人工处理正常后该值一直为true
+                return true;
+            }
+            return false;
+        }
+        private bool CheckValueAbnormal(double currentValue, double? maxLimit, double? minLimit)
+        {
+            if(maxLimit!=null && minLimit != null)
+            {
+                if(currentValue >= maxLimit || currentValue <= minLimit)
+                {
+                    return true ;
+                } 
+            }
+            else if(maxLimit!=null && minLimit == null)
+            {
+                if (currentValue >= maxLimit)
+                {
+                    return true;
+                }
+            }
+            else if(maxLimit == null && minLimit != null)
+            {
+                if (currentValue <= minLimit)
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}

+ 88 - 16
CyberX8_RT/Modules/Metal/ReservoirRunRecipeRoutine.cs

@@ -163,6 +163,14 @@ namespace CyberX8_RT.Modules.Metal
         private bool _isCurrentWarningB = false;
         private bool _isZeroCurrent = false;
         private int _totalMicrosecond = 0;
+
+        private double _currentHoldoffTime;
+        private double _voltageHoldoffTime;
+        private double _cellFlowHoldoffTime;
+
+        private HoldoffTimeSignalMonitor _currentHoldoffTimeSignalMonitor;
+        private HoldoffTimeSignalMonitor _voltageHoldoffTimeSignalMonitor;
+        private HoldoffTimeSignalMonitor _cellFlowHoldoffTimeSignalMonitor;
         #endregion
         #region 属性
         /// <summary>
@@ -187,7 +195,13 @@ namespace CyberX8_RT.Modules.Metal
         /// </summary>
         public ReservoirRunRecipeRoutine(string moduleName) : base(moduleName)
         {
+            _currentHoldoffTime = SC.GetValue<double>($"Metal.CurrentAlarmHoldoffTime");
+            _voltageHoldoffTime = SC.GetValue<double>($"Metal.VoltageAlarmHoldoffTime");
+            _cellFlowHoldoffTime = SC.GetValue<double>($"Metal.CellFlowAlarmHoldoffTime");
 
+            _currentHoldoffTimeSignalMonitor = new HoldoffTimeSignalMonitor(Module, "Current");
+            _voltageHoldoffTimeSignalMonitor = new HoldoffTimeSignalMonitor(Module, "Voltage");
+            _cellFlowHoldoffTimeSignalMonitor = new HoldoffTimeSignalMonitor(Module, "CellFlow");
         }
 
         /// <summary>
@@ -647,9 +661,43 @@ namespace CyberX8_RT.Modules.Metal
                 Abort();
                 return true;
             }
+            if (!CheckMetalCellFlow()) //校验Manual 状态下run recipe的 cell flow和hold flow
+            {
+                Abort();
+                return true;
+            }
             return false;
         }
         /// <summary>
+        /// 监控流量
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckMetalCellFlow()
+        {
+            MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
+            if (metalEntity != null && metalEntity.IsManual)
+            {
+                MetalItem metalItem = MetalItemManager.Instance.GetMetalItem(Module);
+                _metalType = metalItem.SubType;
+                if (_metalType == STRATUS)
+                {
+                    StandardHotMetalDevice _standardHotMetalDevice = DEVICE.GetDevice<StandardHotMetalDevice>(Module.ToString());
+                    //if (_standardHotMetalDevice.MetalDeviceData.CellFlow <= 0)
+                    //{
+                    //    LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{Module} metal cell flow is 0");
+                    //    return false;
+                    //}
+                    bool cellFlowSignalresulte = _cellFlowHoldoffTimeSignalMonitor.IsSignalAbnormal(_cellFlowHoldoffTime, _standardHotMetalDevice.MetalDeviceData.CellFlow, null, 0);
+                    if (cellFlowSignalresulte)
+                    {
+                        LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{Module} metal cell flow is 0");
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        /// <summary>
         /// 检验电压电流的合理性
         /// </summary>
         /// <returns></returns>
@@ -736,17 +784,29 @@ namespace CyberX8_RT.Modules.Metal
             double maxVoltage = _recipe.VolatageLimitMax;
             double warnVoltage = _recipe.VoltageWarningLevel;
             double minVoltage = _recipe.VolatageLimitMin;
-            if (voltage > maxVoltage)
+            //if (voltage > maxVoltage)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is large than recipe max voltage {maxVoltage}");
+            //    return true;
+            //}
+            //if (voltage < minVoltage)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is less than recipe min voltage {minVoltage}");
+            //    return true;
+            //}
+            bool voltageSignalresulte = _voltageHoldoffTimeSignalMonitor.IsSignalAbnormal(_voltageHoldoffTime, voltage, maxVoltage, minVoltage);
+            if (voltageSignalresulte)
             {
-                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is large than recipe max voltage {maxVoltage}");
-                return true;
-            }
-            if (voltage < minVoltage)
-            {
-                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is less than recipe min voltage {minVoltage}");
+                if (voltage > maxVoltage)
+                {
+                    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is large than recipe max voltage {maxVoltage}");
+                }
+                if (voltage < minVoltage)
+                {
+                    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is less than recipe min voltage {minVoltage}");
+                }
                 return true;
             }
-
             if (voltage > warnVoltage)
             {
                 string str = $"{side} voltage is {voltage} in warning";
@@ -760,17 +820,29 @@ namespace CyberX8_RT.Modules.Metal
             double minErrorCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 - _recipe.FaultPercent * 0.01);
             double maxWarnCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 + _recipe.CurrentWarningLevel * 0.01);
             double minWarnCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 - _recipe.CurrentWarningLevel * 0.01);
-            if (current > maxErrorCurrent)
+            //if (current > maxErrorCurrent)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is large than recipe max current {maxErrorCurrent}");
+            //    return true;
+            //}
+            //if (current < minErrorCurrent)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is less than recipe min current {minErrorCurrent}");
+            //    return true;
+            //}
+            bool currentSignalresulte = _currentHoldoffTimeSignalMonitor.IsSignalAbnormal(_currentHoldoffTime, current, maxErrorCurrent, minErrorCurrent);
+            if (currentSignalresulte)
             {
-                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is large than recipe max current {maxErrorCurrent}");
-                return true;
-            }
-            if (current < minErrorCurrent)
-            {
-                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is less than recipe min current {minErrorCurrent}");
+                if (current > maxErrorCurrent)
+                {
+                    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is large than recipe max current {maxErrorCurrent}");
+                }
+                if (current < minErrorCurrent)
+                {
+                    LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is less than recipe min current {minErrorCurrent}");
+                }
                 return true;
             }
-
             if ((current <= maxErrorCurrent && current >= maxWarnCurrent) || (current >= minErrorCurrent && current <= minWarnCurrent))
             {
                 string str = $"{side} current {current} is in warning";