|
@@ -9,6 +9,8 @@ using CyberX8_RT.Devices.Metal;
|
|
|
using CyberX8_RT.Devices.PowerSupplier;
|
|
|
using CyberX8_RT.Devices.Reservoir;
|
|
|
using CyberX8_RT.Devices.Temperature;
|
|
|
+using CyberX8_RT.Modules.Metal;
|
|
|
+using CyberX8_RT.Modules;
|
|
|
using MECF.Framework.Common.Alarm;
|
|
|
using MECF.Framework.Common.CommonData;
|
|
|
using MECF.Framework.Common.CommonData.Metal;
|
|
@@ -23,7 +25,7 @@ using System.Diagnostics;
|
|
|
|
|
|
namespace CyberX8_RT.Modules.Metal
|
|
|
{
|
|
|
- public class ReservoirRunRecipeRoutine : RoutineBase,IRoutine
|
|
|
+ public class ReservoirRunRecipeRoutine : RoutineBase, IRoutine
|
|
|
{
|
|
|
#region 常量
|
|
|
private const int LOTTRACK_TIME = 1000;
|
|
@@ -181,7 +183,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
/// <summary>
|
|
|
/// 构造函数
|
|
|
/// </summary>
|
|
|
- public ReservoirRunRecipeRoutine(string moduleName):base(moduleName)
|
|
|
+ public ReservoirRunRecipeRoutine(string moduleName) : base(moduleName)
|
|
|
{
|
|
|
|
|
|
}
|
|
@@ -191,7 +193,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
/// </summary>
|
|
|
public void Abort()
|
|
|
{
|
|
|
- if (_device != null)
|
|
|
+ if (_device != null)
|
|
|
{
|
|
|
_device.SideAPowerSupplier.DisableOperation("", null);
|
|
|
_device.SideBPowerSupplier.DisableOperation("", null);
|
|
@@ -202,7 +204,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
_device.StopLinmot();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
Runner.Stop("Manual Abort");
|
|
|
}
|
|
|
/// <summary>
|
|
@@ -213,13 +215,13 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
{
|
|
|
LottrackRecord();
|
|
|
Runner.Run(RecipeStep.PlatingDelay, PlatingDelay, _delay_1ms)
|
|
|
- .WaitWithStopCondition(RecipeStep.PlatingDelayCheck,()=>{ return _device.CheckLinmotRoutineEnd(); }, () => { return _device.CheckLinmotRoutineError(); } )
|
|
|
+ .WaitWithStopCondition(RecipeStep.PlatingDelayCheck, () => { return _device.CheckLinmotRoutineEnd(); }, () => { return _device.CheckLinmotRoutineError(); })
|
|
|
.RunIf(RecipeStep.HotPlating, _recipe.HotPlatingCurrentOn, HotPlating, _delay_1ms)
|
|
|
.RunIf(RecipeStep.WaitPlatingDelay, !_recipe.HotPlatingCurrentOn, NullFun, WaitPlatingDelay, _recipe.PlatingDelaySeconds * 1000 + 10000)
|
|
|
.RunIf(RecipeStep.RunPowerStep, !_recipe.HotPlatingCurrentOn, StartPowerStep, _delay_1ms)
|
|
|
- .WaitWithStopCondition(RecipeStep.RunPowerStepWait,CheckRecipeStepEndStatus,CheckRecipeStepStopStatus,_delay_5s)
|
|
|
+ .WaitWithStopCondition(RecipeStep.RunPowerStepWait, CheckRecipeStepEndStatus, CheckRecipeStepStopStatus, _delay_5s)
|
|
|
.LoopStart(RecipeStep.LoopStart, "Loop update linmot speed", _powerSupplierStepPeriodDatas.Count, NullFun, _delay_1ms)
|
|
|
- .LoopRunWithStopStatus(RecipeStep.LoopCheckRun, CheckStepComplete, () => { return false; })
|
|
|
+ .LoopRunWithStopStatus(RecipeStep.LoopCheckRun, CheckStepComplete, () => { return false; }, 24 * 60 * 60 * 1000)
|
|
|
.LoopEnd(RecipeStep.LoopEnd, NullFun, _delay_1ms)
|
|
|
.Run(RecipeStep.StopLinmot, StopLinmot, _delay_1ms)
|
|
|
.Run(RecipeStep.StopPowerSuppliers, StopPowerSupplier, _delay_1ms)
|
|
@@ -247,7 +249,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
public void AddLotTrackData()
|
|
|
{
|
|
|
MetalLotTrackData data = new MetalLotTrackData();
|
|
|
- if(_metalType == STRATUS)
|
|
|
+ if (_metalType == STRATUS)
|
|
|
{
|
|
|
data.Flow = _standardHotMetalDevice.MetalDeviceData.CellFlow;
|
|
|
data.ANLevel = 0;
|
|
@@ -314,7 +316,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
{
|
|
|
if (_recipe.HotPlatingCurrentOn)
|
|
|
{
|
|
|
- if(DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds <= _recipe.PlatingDelaySeconds)
|
|
|
+ if (DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds <= _recipe.PlatingDelaySeconds)
|
|
|
{
|
|
|
data.RunTime = DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds;
|
|
|
data.DurationRef = _recipe.PlatingDelaySeconds;
|
|
@@ -322,17 +324,18 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if(data.StepNum == 1) data.DurationRef -= _recipe.PlatingDelaySeconds;
|
|
|
- data.RunTime = (data.StepNum == 1)?(DateTime.Now.Subtract(_startStepTime).TotalSeconds - _recipe.PlatingDelaySeconds): DateTime.Now.Subtract(_startStepTime).TotalSeconds;
|
|
|
+ if (data.StepNum == 1) data.DurationRef -= _recipe.PlatingDelaySeconds;
|
|
|
+ data.RunTime = (data.StepNum == 1) ? (DateTime.Now.Subtract(_startStepTime).TotalSeconds - _recipe.PlatingDelaySeconds) : DateTime.Now.Subtract(_startStepTime).TotalSeconds;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
data.RunTime = DateTime.Now.Subtract(_startStepTime).TotalSeconds;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
_datas.Add(data);
|
|
|
}
|
|
|
/// <summary>
|
|
@@ -346,7 +349,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
if (result)
|
|
|
{
|
|
|
_platingDelayTime = DateTime.Now;
|
|
|
- if(!_recipe.HotPlatingCurrentOn) _hotPlatingRunTime = DateTime.Now;
|
|
|
+ if (!_recipe.HotPlatingCurrentOn) _hotPlatingRunTime = DateTime.Now;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
@@ -420,7 +423,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
if (string.IsNullOrEmpty(_side))
|
|
|
{
|
|
|
bool resultA = _device.SideAPowerSupplier.Status == RState.End;
|
|
|
- bool resultB=_device.SideBPowerSupplier.Status == RState.End;
|
|
|
+ bool resultB = _device.SideBPowerSupplier.Status == RState.End;
|
|
|
return resultA && resultB;
|
|
|
}
|
|
|
else
|
|
@@ -442,14 +445,14 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(_side))
|
|
|
{
|
|
|
- bool resultA = _device.SideAPowerSupplier.Status == RState.Failed||_device.SideAPowerSupplier.Status==RState.Timeout;
|
|
|
- bool resultB = _device.SideBPowerSupplier.Status == RState.Failed||_device.SideBPowerSupplier.Status==RState.Timeout;
|
|
|
+ bool resultA = _device.SideAPowerSupplier.Status == RState.Failed || _device.SideAPowerSupplier.Status == RState.Timeout;
|
|
|
+ bool resultB = _device.SideBPowerSupplier.Status == RState.Failed || _device.SideBPowerSupplier.Status == RState.Timeout;
|
|
|
return resultA && resultB;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
|
|
|
- return cellPowerSupplier.Status == RState.Failed||cellPowerSupplier.Status==RState.Timeout;
|
|
|
+ return cellPowerSupplier.Status == RState.Failed || cellPowerSupplier.Status == RState.Timeout;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
@@ -520,9 +523,10 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData();
|
|
|
step.Current = item.ForwardAmps;
|
|
|
step.Hour = (ushort)(item.CurrentRampDurartionSeconds / 3600);
|
|
|
- step.Minute = (ushort)(item.CurrentRampDurartionSeconds / 60);
|
|
|
+ step.Minute = (ushort)((item.CurrentRampDurartionSeconds - step.Hour * 3600) / 60);
|
|
|
step.Second = (ushort)(item.CurrentRampDurartionSeconds % 60);
|
|
|
step.Microsecond = 0;
|
|
|
+ step.Voltage = _recipe.VoltageWarningLevel;
|
|
|
_powerSupplierStepPeriodDatas.Add(step);
|
|
|
}
|
|
|
}
|
|
@@ -543,14 +547,19 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private bool CheckStepComplete()
|
|
|
- {
|
|
|
+ {
|
|
|
if (_stepIndex >= _powerSupplierStepPeriodDatas.Count)
|
|
|
{
|
|
|
_stepWatch.Stop();
|
|
|
LOG.WriteLog(eEvent.INFO_METAL, Module, $"step {_stepIndex} is over step count {_powerSupplierStepPeriodDatas.Count}");
|
|
|
return true;
|
|
|
}
|
|
|
- if (DateTime.Now.Subtract(_startStepTime).TotalMilliseconds >= 2000)
|
|
|
+ int firstDelay = 2000;
|
|
|
+ if (_stepIndex == 0)
|
|
|
+ {
|
|
|
+ firstDelay = SC.GetValue<int>("Metal.CurrentCheckDelay") * 1000;
|
|
|
+ }
|
|
|
+ if (DateTime.Now.Subtract(_startStepTime).TotalMilliseconds >= firstDelay)
|
|
|
{
|
|
|
bool abnormal = CheckMetalDisable();
|
|
|
if (abnormal)
|
|
@@ -558,11 +567,11 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
int length = _powerSupplierStepPeriodDatas[_stepIndex].Hour * 3600 + _powerSupplierStepPeriodDatas[_stepIndex].Minute * 60 +
|
|
|
_powerSupplierStepPeriodDatas[_stepIndex].Second;
|
|
|
if (DateTime.Now.Subtract(_startStepTime).TotalSeconds >= length)
|
|
|
- {
|
|
|
+ {
|
|
|
_stepIndex++;
|
|
|
if (_stepIndex >= _powerSupplierStepPeriodDatas.Count)
|
|
|
{
|
|
@@ -585,7 +594,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
_anodeAUsage += _device.SideAPowerSupplier.PowerSupplierData.Current * second / 3600;
|
|
|
_anodeBUsage += _device.SideBPowerSupplier.PowerSupplierData.Current * second / 3600;
|
|
|
}
|
|
|
- else if(_side==SIDE_A)
|
|
|
+ else if (_side == SIDE_A)
|
|
|
{
|
|
|
_anodeAUsage += _device.SideAPowerSupplier.PowerSupplierData.Current * second / 3600;
|
|
|
}
|
|
@@ -604,7 +613,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(_side))
|
|
|
- {
|
|
|
+ {
|
|
|
if (!_device.SideAPowerSupplier.PowerSupplierData.Enabled)
|
|
|
{
|
|
|
LOG.WriteLog(eEvent.ERR_METAL, Module, "PowerA disable");
|
|
@@ -740,7 +749,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
if (!_isCurrentWarningA && ((_device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault)
|
|
|
|| (_device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)))
|
|
|
{
|
|
|
- _isCurrentWarningA = true;
|
|
|
+ _isCurrentWarningA = true;
|
|
|
LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideA Current {_device.SideAPowerSupplier.PowerSupplierData.Current} is not in " +
|
|
|
$"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault}");
|
|
|
}
|
|
@@ -898,11 +907,11 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
/// <param name="voltage"></param>
|
|
|
/// <param name="side"></param>
|
|
|
/// <returns></returns>
|
|
|
- private bool CheckSidePowerInvalid(double current,double voltage,string side)
|
|
|
+ private bool CheckSidePowerInvalid(double current, double voltage, string side)
|
|
|
{
|
|
|
double maxVoltage = _recipe.VolatageLimitMax;
|
|
|
double warnVoltage = _recipe.VoltageWarningLevel;
|
|
|
- double minVoltage=_recipe.VolatageLimitMin;
|
|
|
+ double minVoltage = _recipe.VolatageLimitMin;
|
|
|
if (voltage > maxVoltage)
|
|
|
{
|
|
|
LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is large than recipe max voltage {maxVoltage}");
|
|
@@ -1015,6 +1024,8 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
_side = objs[1].ToString();
|
|
|
}
|
|
|
_startRecipeStep = false;
|
|
|
+ _anodeAUsage = 0;
|
|
|
+ _anodeBUsage = 0;
|
|
|
_device = DEVICE.GetDevice<MetalCellDevice>(Module);
|
|
|
_metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
|
|
|
UpdatePowerStepDatas();
|
|
@@ -1022,7 +1033,7 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
|
|
|
_header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
|
|
_header.Recipe = $"{_recipe.Ppid}.dep.rcp";
|
|
|
- if(SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID");
|
|
|
+ if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID");
|
|
|
|
|
|
//lotTract记录SequenceRecipe
|
|
|
MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
|
|
@@ -1045,30 +1056,51 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
_metalType = metalItem.SubType;
|
|
|
if (_metalType == STRATUS)
|
|
|
{
|
|
|
- _standardHotReservoirDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
|
|
|
+ _standardHotReservoirDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
|
|
|
_standardHotMetalDevice = DEVICE.GetDevice<StandardHotMetalDevice>(Module);
|
|
|
- if (_standardHotReservoirDevice == null || _standardHotMetalDevice == null)
|
|
|
+ if (_standardHotReservoirDevice == null || _standardHotMetalDevice == null)
|
|
|
{
|
|
|
LOG.WriteLog(eEvent.ERR_METAL, Module, $"metal or reservoir device is null");
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
+ if (_standardHotMetalDevice.MetalDeviceData.CellFlow <= 0) //检查cell flow
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal cell flow is 0");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_compactMembranReservoirDevice = DEVICE.GetDevice<CompactMembranReservoirDevice>(reservoirName);
|
|
|
_compactMembranMetalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(Module);
|
|
|
- if(_compactMembranMetalDevice == null || _compactMembranReservoirDevice == null)
|
|
|
+ if (_compactMembranMetalDevice == null || _compactMembranReservoirDevice == null)
|
|
|
{
|
|
|
LOG.WriteLog(eEvent.ERR_METAL, Module, $"metal or reservoir device is null");
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
+ if (_compactMembranMetalDevice.MetalDeviceData.CellFlow <= 0) //检查cell flow
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal cell flow is 0");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+ if (_compactMembranMetalDevice.ANACellFlow.CounterValue <= 0) //检查hold flow
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal AnodeA flow is 0");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+ if (_compactMembranMetalDevice.ANBCellFlow.CounterValue <= 0)
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal AnodeB flow is 0");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(reservoirName);
|
|
|
_temperatureController = DEVICE.GetDevice<TemperatureController>(reservoirItem.TCID);
|
|
|
if (_temperatureController == null)
|
|
|
- {
|
|
|
+ {
|
|
|
LOG.WriteLog(eEvent.ERR_METAL, Module, $"Temperature controller is null");
|
|
|
- return RState.Failed;
|
|
|
+ return RState.Failed;
|
|
|
}
|
|
|
_persistentValue = MetalPersistentManager.Instance.GetMetalPersistentValue(Module);
|
|
|
if (_persistentValue == null)
|
|
@@ -1079,16 +1111,9 @@ namespace CyberX8_RT.Modules.Metal
|
|
|
_lotTackTime = DateTime.Now;
|
|
|
return Runner.Start(Module, "Metal run recipe");
|
|
|
}
|
|
|
-
|
|
|
public void clearLotTrack()
|
|
|
{
|
|
|
_datas.Clear();
|
|
|
}
|
|
|
-
|
|
|
- public void resetMetalUsage()
|
|
|
- {
|
|
|
- _anodeAUsage = 0;
|
|
|
- _anodeBUsage = 0;
|
|
|
- }
|
|
|
}
|
|
|
}
|