Merge branch 'feature/optimize-autotransfer' into develop

This commit is contained in:
DESKTOP-GPE37UV\THINKAPD 2022-11-23 09:24:49 +08:00
commit f468afd9a6
15 changed files with 702 additions and 375 deletions

View File

@ -11,6 +11,8 @@ namespace MECF.Framework.Simulator.Core.IoProviders
{
private Random _rd = new Random();
private readonly object _syncRoot = new object();
public ObservableCollection<NotifiableIoItem> DiItemList { get; set; }
public ObservableCollection<NotifiableIoItem> DoItemList { get; set; }
public ObservableCollection<NotifiableIoItem> AiItemList { get; set; }
@ -63,94 +65,97 @@ namespace MECF.Framework.Simulator.Core.IoProviders
void Init()
{
if (DiItemList == null)
lock (_syncRoot)
{
List<DIAccessor> diItems = IO.GetDiList(_source);
if (diItems != null)
if (DiItemList == null)
{
DiItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var diItem in diItems)
List<DIAccessor> diItems = IO.GetDiList(_source);
if (diItems != null)
{
NotifiableIoItem item = new NotifiableIoItem()
DiItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var diItem in diItems)
{
Name = diItem.Name,
Index = diItem.Index,
Description = diItem.Description,
BoolValue = diItem.Value,
Address = diItem.Addr,
BlockOffset = diItem.BlockOffset,
BlockIndex = diItem.Index,
};
DiItemList.Add(item);
NotifiableIoItem item = new NotifiableIoItem()
{
Name = diItem.Name,
Index = diItem.Index,
Description = diItem.Description,
BoolValue = diItem.Value,
Address = diItem.Addr,
BlockOffset = diItem.BlockOffset,
BlockIndex = diItem.Index,
};
DiItemList.Add(item);
}
}
}
}
if (DoItemList == null)
{
List<DOAccessor> doItems = IO.GetDoList(_source);
if (doItems != null)
if (DoItemList == null)
{
DoItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in doItems)
List<DOAccessor> doItems = IO.GetDoList(_source);
if (doItems != null)
{
NotifiableIoItem item = new NotifiableIoItem()
DoItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in doItems)
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
BoolValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
DoItemList.Add(item);
NotifiableIoItem item = new NotifiableIoItem()
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
BoolValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
DoItemList.Add(item);
}
}
}
}
if (AiItemList == null)
{
List<AIAccessor> aiItems = IO.GetAiList(_source);
if (aiItems != null)
if (AiItemList == null)
{
AiItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in aiItems)
List<AIAccessor> aiItems = IO.GetAiList(_source);
if (aiItems != null)
{
NotifiableIoItem item = new NotifiableIoItem()
AiItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in aiItems)
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
ShortValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
AiItemList.Add(item);
NotifiableIoItem item = new NotifiableIoItem()
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
ShortValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
AiItemList.Add(item);
}
}
}
}
if (AoItemList == null)
{
List<AOAccessor> aoItems = IO.GetAoList(_source);
if (aoItems != null)
if (AoItemList == null)
{
AoItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in aoItems)
List<AOAccessor> aoItems = IO.GetAoList(_source);
if (aoItems != null)
{
NotifiableIoItem item = new NotifiableIoItem()
AoItemList = new ObservableCollection<NotifiableIoItem>();
foreach (var ioItem in aoItems)
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
ShortValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
AoItemList.Add(item);
NotifiableIoItem item = new NotifiableIoItem()
{
Name = ioItem.Name,
Index = ioItem.Index,
Description = ioItem.Description,
ShortValue = ioItem.Value,
Address = ioItem.Addr,
BlockOffset = ioItem.BlockOffset,
BlockIndex = ioItem.Index,
};
AoItemList.Add(item);
}
}
}
}
@ -163,116 +168,125 @@ namespace MECF.Framework.Simulator.Core.IoProviders
protected override bool OnTimer()
{
if (DiItemList != null)
lock (_syncRoot)
{
foreach (var notifiableIoItem in DiItemList)
if (DiItemList != null)
{
if (notifiableIoItem.HoldValue)
foreach (var notifiableIoItem in DiItemList)
{
IO.DI[notifiableIoItem.Name].Value = notifiableIoItem.BoolValue;
if (notifiableIoItem.HoldValue)
{
IO.DI[notifiableIoItem.Name].Value = notifiableIoItem.BoolValue;
}
notifiableIoItem.BoolValue = IO.DI[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("BoolValue");
}
notifiableIoItem.BoolValue = IO.DI[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("BoolValue");
}
}
if (DoItemList != null)
{
foreach (var notifiableIoItem in DoItemList)
if (DoItemList != null)
{
notifiableIoItem.BoolValue = IO.DO[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("BoolValue");
}
}
if (AiItemList != null)
{
foreach (var notifiableIoItem in AiItemList)
{
if (notifiableIoItem.HoldValue)
foreach (var notifiableIoItem in DoItemList)
{
IO.AI[notifiableIoItem.Name].Value = notifiableIoItem.ShortValue;
notifiableIoItem.BoolValue = IO.DO[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("BoolValue");
}
}
if (AiItemList != null)
{
foreach (var notifiableIoItem in AiItemList)
{
if (notifiableIoItem.HoldValue)
{
IO.AI[notifiableIoItem.Name].Value = notifiableIoItem.ShortValue;
}
notifiableIoItem.ShortValue = IO.AI[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("ShortValue");
}
}
if (AoItemList != null)
{
foreach (var notifiableIoItem in AoItemList)
{
notifiableIoItem.ShortValue = IO.AO[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("ShortValue");
}
}
foreach (var plcBuffer in _buffers)
{
//IO修改 ---> PLC
if (plcBuffer.Type == IoType.DI)
{
var ioBuffers = IoManager.Instance.GetDiBuffer(_source);
if (ioBuffers != null)
{
foreach (var ioBuffer in ioBuffers)
{
if (plcBuffer.Offset == ioBuffer.Key)
{
plcBuffer.BoolValue = ioBuffer.Value;
}
}
}
}
notifiableIoItem.ShortValue = IO.AI[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("ShortValue");
// PLC --> IO
if (plcBuffer.Type == IoType.DO)
{
var ioBuffers = IoManager.Instance.GetDoBuffer(_source);
if (ioBuffers != null)
{
foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
IoManager.Instance.SetDoBuffer(_source, plcBuffer.Offset, plcBuffer.BoolValue);
}
}
}
}
//IO修改 ---> PLC
if (plcBuffer.Type == IoType.AI)
{
var ioBuffers = IoManager.Instance.GetAiBuffer(_source);
if (ioBuffers != null)
{
foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
plcBuffer.ShortValue =
Array.ConvertAll<short, ushort>(buffer.Value, x => (ushort)x);
}
}
}
}
// PLC --> IO
if (plcBuffer.Type == IoType.AO)
{
var ioBuffers = IoManager.Instance.GetAoBuffer(_source);
if (ioBuffers != null)
{
foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
IoManager.Instance.SetAoBuffer(_source, plcBuffer.Offset,
Array.ConvertAll<ushort, short>(plcBuffer.ShortValue, x => (short)x));
}
}
}
}
}
return true;
}
if (AoItemList != null)
{
foreach (var notifiableIoItem in AoItemList)
{
notifiableIoItem.ShortValue = IO.AO[notifiableIoItem.Name].Value;
notifiableIoItem.InvokePropertyChanged("ShortValue");
}
}
foreach (var plcBuffer in _buffers)
{
//IO修改 ---> PLC
if (plcBuffer.Type == IoType.DI)
{
var ioBuffers = IoManager.Instance.GetDiBuffer(_source);
if (ioBuffers != null)
{ foreach (var ioBuffer in ioBuffers)
{
if (plcBuffer.Offset == ioBuffer.Key)
{
plcBuffer.BoolValue = ioBuffer.Value;
}
}}
}
// PLC --> IO
if (plcBuffer.Type == IoType.DO)
{
var ioBuffers = IoManager.Instance.GetDoBuffer(_source);
if (ioBuffers!=null)
{ foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
IoManager.Instance.SetDoBuffer(_source, plcBuffer.Offset, plcBuffer.BoolValue);
}
}}
}
//IO修改 ---> PLC
if (plcBuffer.Type == IoType.AI)
{
var ioBuffers = IoManager.Instance.GetAiBuffer(_source);
if (ioBuffers != null)
{
foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
plcBuffer.ShortValue = Array.ConvertAll<short, ushort>(buffer.Value,x=>(ushort)x);
}
}}
}
// PLC --> IO
if (plcBuffer.Type == IoType.AO)
{
var ioBuffers = IoManager.Instance.GetAoBuffer(_source);
if (ioBuffers != null)
{ foreach (var buffer in ioBuffers)
{
if (plcBuffer.Offset == buffer.Key)
{
IoManager.Instance.SetAoBuffer(_source, plcBuffer.Offset, Array.ConvertAll<ushort, short>(plcBuffer.ShortValue, x => (short)x));
}
}}
}
}
return true;
}

View File

@ -482,7 +482,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
}
/// <summary>
/// 根据左侧选项查询数据
/// 根据DataLog界面左侧项目树中择的查询数据
/// </summary>
/// <returns></returns>
private static DataSet SearchDataBaseAsync(
@ -498,78 +498,109 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
// 遍历模组
foreach (var module in modules)
{
var sql = new StringBuilder();
//! 因为数据库中按天拆表无法一次性查询数据需使用UNION合并多表查询因此此处按天拼接SQL表达式
// 最终SQL表达式结构为
// (select xx from date1.xx) union (select xx from date2.xx) union (select xx from date3.xx)
// where time between xxx and xxx
// order by time asc
var ts = dateRange.Diff;
for (var day = 0; day <= ts.Days; day++)
// 如果当前根节点下没有被选中的终端节点,则忽略
if (module.ChildNodes.FirstOrDefault(x => (bool)x.HasTerminalSelected) == null)
continue;
if (module.ToString() != "IO")
{
// 检查表名是否存在否则SQL执行出错。
var tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.{module}";
if (module.ToString() == "IO")
{
var node = module.ChildNodes.FirstOrDefault(x => (bool)x.HasTerminalSelected);
tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.{node}";
}else if (module.ToString() != "PM1")
{
tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.System";
}
if (CheckTableExists(tblName))
// 如果不是IO节点则根节点名即为数据库名=
var dt = SearchSingleDbTable(module, dateRange, cancellation, progressReporter);
if (dt != null)
ds.Tables.Add(dt);
}
else
{
// 如果节点名是IO则数据库使用IO.[二级节点名]作为表名例如IO.PM1\IO.PM2\IO.TM\IO.System
var subNodes = module.ChildNodes;
foreach (var subNode in subNodes)
{
if (subNode.ChildNodes.FirstOrDefault(x => (bool)x.HasTerminalSelected) == null)
continue;
sql.Append("select \"time\" AS InternalTimeStamp");
var selectedParams = module.Flatten(true)
.Where(x => x.IsSelected == true);
// 添加待查询的列
foreach (var item in selectedParams)
{
sql.Append("," + $"\"{item}\"");
}
sql.Append($" from \"{tblName}\" ");
if (day < ts.Days)
sql.Append(" UNION ");
var dt = SearchSingleDbTable(subNode, dateRange, cancellation, progressReporter);
if (dt != null)
ds.Tables.Add(dt);
}
}
// 所有表名不可用,可能是日期范围错误
if (sql.Length <= 0)
{
continue;
}
sql.Append(
$" where \"time\" between {dateRange.Start.Ticks} and {dateRange.End.Ticks} order by InternalTimeStamp asc");
progressReporter?.Report(new ProgressUpdatingEventArgs(20, 100,
$"Querying {dateRange}..."));
if (cancellation?.Token.IsCancellationRequested == true)
return null;
// 查询数据并将返回的结果存储在DataSet中
var dataTable = QueryDataClient.Instance.Service.QueryData(sql.ToString());
if (cancellation?.Token.IsCancellationRequested == true)
return null;
//! 返回的 DataTable 可能不存在,原因是上述代码自动生成的表明可能不存在。
if (dataTable == null)
continue;
dataTable.TableName = module.Name;
ds.Tables.Add(dataTable);
}
}
return ds;
}
/// <summary>
/// IO节点在数据库中的表名比较特殊需要特殊处理。
/// </summary>
/// <param name="module"></param>
/// <param name="dateRange"></param>
/// <param name="cancellation"></param>
/// <param name="progressReporter"></param>
/// <returns></returns>
private static DataTable SearchSingleDbTable(TreeNode module, DateRangeHelper dateRange,
CancellationTokenSource cancellation = null,
IProgress<ProgressUpdatingEventArgs> progressReporter = null)
{
var sql = new StringBuilder();
//! 因为数据库中按天拆表无法一次性查询数据需使用UNION合并多表查询因此此处按天拼接SQL表达式
// 最终SQL表达式结构为
// (select xx from date1.xx) union (select xx from date2.xx) union (select xx from date3.xx)
// where time between xxx and xxx
// order by time asc
var ts = dateRange.Diff;
for (var day = 0; day <= ts.Days; day++)
{
var tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.{module}";
// 检查表名是否存在否则SQL执行出错。
if (CheckTableExists(tblName))
{
sql.Append("select \"time\" AS InternalTimeStamp");
var selectedParams = module.Flatten(true)
.Where(x => x.IsSelected == true);
// 添加待查询的列
foreach (var item in selectedParams)
{
sql.Append("," + $"\"{item}\"");
}
sql.Append($" from \"{tblName}\" ");
if (day < ts.Days)
sql.Append(" UNION ");
}
}
// 所有表名不可用,可能是日期范围错误
if (sql.Length <= 0)
{
return null;
}
sql.Append(
$" where \"time\" between {dateRange.Start.Ticks} and {dateRange.End.Ticks} order by InternalTimeStamp asc");
progressReporter?.Report(new ProgressUpdatingEventArgs(20, 100,
$"Querying {dateRange}..."));
if (cancellation?.Token.IsCancellationRequested == true)
return null;
// 查询数据并将返回的结果存储在DataSet中
var dataTable = QueryDataClient.Instance.Service.QueryData(sql.ToString());
if (cancellation?.Token.IsCancellationRequested == true)
return null;
//! 返回的 DataTable 可能不存在,原因是上述代码自动生成的表明可能不存在。
if (dataTable == null)
return null;
dataTable.TableName = module.Name;
return dataTable;
}
/// <summary>
/// 渲染图表。
/// </summary>

View File

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
@ -142,6 +143,8 @@ namespace Mainframe.LLs.Routines
EndLoop((int)RoutineStep.StopLoop);
}
TimeDelay((int)RoutineStep.TimeDelay2, 3);
}
catch (RoutineBreakException)
{
@ -149,15 +152,23 @@ namespace Mainframe.LLs.Routines
}
catch (RoutineFaildException)
{
UnlockPump2();
return Result.FAIL;
}
var result = Result.DONE;
if (_tmIoInterLock.SetLLPurgeRoutineRunning(false, out var reason) == false)
{
EV.PostWarningLog(Module,
$"Unable to perform {nameof(_tmIoInterLock.SetLLPurgeRoutineRunning)}, {reason}");
result = Result.FAIL;
}
UnlockPump2();
Notify($"Finished ! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
_tmIoInterLock.DoLLCyclePurgeRoutineRunning = false;
return Result.DONE;
return result;
}
public override void Abort()

View File

@ -149,6 +149,7 @@
<Compile Include="UnLoads\Routines\UnLoadLiftRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadPrepareTransferRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadPumpRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadCoolingAndPurgeRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadPurgeRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadSeparateRoutine.cs" />
<Compile Include="UnLoads\Routines\UnLoadServoToRoutine.cs" />

View File

@ -0,0 +1,215 @@
using System;
using System.Diagnostics;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Equipment;
namespace Mainframe.UnLoads.Routines
{
public class UnLoadCoolingAndPurgeRoutine : UnLoadBaseRoutine
{
enum RoutineStep
{
SlowPump,
FastPump,
PumpDelay,
CloseFastValve,
CloseSlowValve,
SlowVent,
FastVent,
VentDelay,
CloseFastVentValve,
CloseSlowVentValve,
StartLoop,
LoopPump,
LoopVent,
StopLoop,
TimeDelay1,
TimeDelay2
}
private int _purgeCount;
private int _routineTimeOut;
private double _pumpSwitchPressure;
private double _pumpBasePressure;
private int _pumpDelayTime;
private int _pumpTimeOut;
private double _ventBasePressure;
private int _ventDelayTime;
private int _ventTimeOut;
private int _coolingTimeInSec;
private readonly Stopwatch _swTimer = new Stopwatch();
private readonly Stopwatch _swCooling = new Stopwatch();
public UnLoadCoolingAndPurgeRoutine()
{
Module = ModuleName.UnLoad.ToString();
Name = "CoolingAndPurge";
}
public void Init()
{
}
public override Result Start(params object[] objs)
{
Reset();
if (objs.Length == 3
&& int.TryParse(objs[0].ToString(), out int coolingTime)
&& int.TryParse(objs[1].ToString(), out int purgeCount)
&& int.TryParse(objs[2].ToString(), out int pumpDelayTime))
{
_coolingTimeInSec = coolingTime;
_purgeCount = purgeCount;
_pumpDelayTime = pumpDelayTime;
}
else
{
_coolingTimeInSec = SC.GetValue<int>("UnLoad.CoolingTimeFallback");
_purgeCount = SC.GetValue<int>("UnLoad.Purge.CyclePurgeCount");
_pumpDelayTime = SC.GetValue<int>("UnLoad.Purge.PumpDelayTime");
}
_routineTimeOut = SC.GetValue<int>("UnLoad.Purge.RoutineTimeOut");
_pumpSwitchPressure = SC.GetValue<double>("UnLoad.Pump.SlowFastPumpSwitchPressure");
_pumpBasePressure = SC.GetValue<double>("UnLoad.Purge.PumpBasePressure");
_pumpTimeOut = SC.GetValue<int>("UnLoad.Purge.PumpTimeOut");
_ventBasePressure = SC.GetValue<double>("UnLoad.Purge.VentBasePressure");
_ventDelayTime = SC.GetValue<int>("UnLoad.Purge.VentDelayTime");
_ventTimeOut = _pumpTimeOut;
LockPump2(out var reason);
if (!UnLoadDevice.CheckLidClose())
{
EV.PostAlarmLog(Module, $"can not purge, lid is open");
return Result.FAIL;
}
if (!TMDevice.SetFastPumpValve(false, out reason))
{
EV.PostAlarmLog(Module, $"can not purge, TM fast pump value can not close");
return Result.FAIL;
}
if (!TMDevice.CheckSlitValveClose(ModuleHelper.Converter(UnLoadDevice.Module)))
{
EV.PostAlarmLog(Module, $"Can not purge, slit valve is open");
return Result.FAIL;
}
if (!TMDevice.SetTmToLLVent(false, out _))
{
EV.PostAlarmLog(Module, $"can not vent,can not close v85!");
}
if (!TmIoInterLock.SetUnloadPurgeRoutineRunning(true, out reason))
{
EV.PostAlarmLog(Module, $"can not purge,{reason}");
return Result.FAIL;
}
if (SC.GetValue<bool>("System.IsATMMode"))
{
return Result.DONE;
}
_swTimer.Restart();
_swCooling.Restart();
Notify("CoolingAnd Purge Start");
return Result.RUN;
}
public override Result Monitor()
{
try
{
CheckRoutineTimeOut();
if (_purgeCount > 0)
{
Loop((int)RoutineStep.StartLoop, _purgeCount);
SlowPump((int)RoutineStep.SlowPump, _pumpSwitchPressure, _pumpTimeOut);
FastPump((int)RoutineStep.FastPump, _pumpBasePressure, _pumpTimeOut);
TimeDelay((int)RoutineStep.PumpDelay, _pumpDelayTime);
CloseFastPumpValve((int)RoutineStep.CloseFastValve);
CloseSlowPumpValve((int)RoutineStep.CloseSlowValve);
TimeDelay((int)RoutineStep.TimeDelay1, 1);
SlowVent((int)RoutineStep.SlowVent, _ventBasePressure, _ventTimeOut);
CloseVentValve((int)RoutineStep.CloseSlowVentValve);
TimeDelay((int)RoutineStep.VentDelay, _ventDelayTime);
EndLoop((int)RoutineStep.StopLoop);
}
TimeDelay((int)RoutineStep.TimeDelay2, 3);
CheckCoolingDone();
}
catch (RoutineBreakException)
{
return Result.RUN;
}
catch (RoutineFaildException)
{
return Result.FAIL;
}
var result = Result.DONE;
if (TmIoInterLock.SetUnloadPurgeRoutineRunning(false, out var reason) == false)
{
EV.PostWarningLog(Module, $"Unable to perform {nameof(TmIoInterLock.SetUnloadPurgeRoutineRunning)}, {reason}");
result = Result.FAIL;
}
UnlockPump2();
Notify($"Finished ! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
return result;
}
public override void Abort()
{
TmIoInterLock.SetUnloadPurgeRoutineRunning(false, out _);
base.Abort();
}
private void CheckRoutineTimeOut()
{
if (_routineTimeOut > 10)
{
if ((int)(_swTimer.ElapsedMilliseconds / 1000) > _routineTimeOut)
{
EV.PostAlarmLog(Module, $"Routine TimeOut! over {_routineTimeOut} s");
throw (new RoutineFaildException());
}
}
}
private void CheckCoolingDone()
{
if (_swCooling.Elapsed.TotalSeconds > _coolingTimeInSec)
{
_swCooling.Stop();
return;
}
throw new RoutineBreakException();
}
public int GetRemainedTime()
{
if (_swCooling.IsRunning)
return _coolingTimeInSec - (int)(_swCooling.Elapsed.TotalSeconds);
return 0;
}
}
}

View File

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
@ -136,6 +137,8 @@ namespace Mainframe.UnLoads.Routines
TimeDelay((int)RoutineStep.VentDelay, _ventDelayTime);
EndLoop((int)RoutineStep.StopLoop);
}
TimeDelay((int)RoutineStep.TimeDelay2, 3);
}
catch (RoutineBreakException)
{
@ -143,14 +146,20 @@ namespace Mainframe.UnLoads.Routines
}
catch (RoutineFaildException)
{
UnlockPump2();
return Result.FAIL;
}
TmIoInterLock.SetUnloadPurgeRoutineRunning(false, out _);
var result = Result.DONE;
if (TmIoInterLock.SetUnloadPurgeRoutineRunning(false, out var reason) == false)
{
EV.PostWarningLog(Module, $"Unable to perform {nameof(TmIoInterLock.SetUnloadPurgeRoutineRunning)}, {reason}");
result = Result.FAIL;
}
UnlockPump2();
Notify($"Finished ! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
return Result.DONE;
return result;
}
public override void Abort()

View File

@ -35,6 +35,7 @@ namespace Mainframe.UnLoads
OpenDoor,
CloseDoor,
Cooling,
CoolingAndPurge,
Separating,
Grouping,
}
@ -55,6 +56,7 @@ namespace Mainframe.UnLoads
OpenDoor,
CloseDoor,
Cooling,
CoolingAndPurge,
SetOnline,
SetOffline,
ToInit,
@ -144,6 +146,7 @@ namespace Mainframe.UnLoads
private UnLoadPrepareTransferRoutine _prepareTransferRoutine;
//private UnLoadLiftRoutine _liftRoutine;
private UnLoadCoolingRoutine _unloadCoolingRoutine;
private UnLoadCoolingAndPurgeRoutine _unloadCoolingAndPurgeRoutine;
private UnLoadSeparateRoutine _unloadSeparateRoutine;
private UnLoadLeakCheckRoutine _unloadLeakCheckRoutine;
@ -192,6 +195,7 @@ namespace Mainframe.UnLoads
_prepareTransferRoutine = new UnLoadPrepareTransferRoutine();
_unloadSeparateRoutine = new UnLoadSeparateRoutine();
_unloadCoolingRoutine = new UnLoadCoolingRoutine();
_unloadCoolingAndPurgeRoutine = new UnLoadCoolingAndPurgeRoutine();
_unloadLeakCheckRoutine = new UnLoadLeakCheckRoutine();
}
@ -244,6 +248,11 @@ namespace Mainframe.UnLoads
Transition(STATE.Purge, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle);
Transition(STATE.Purge, MSG.Abort, FsmAbortTask, STATE.Idle);
//CoolingAndPurge
Transition(STATE.Idle, MSG.CoolingAndPurge, FsmStartCoolingAndPurge, STATE.CoolingAndPurge);
Transition(STATE.CoolingAndPurge, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle);
Transition(STATE.CoolingAndPurge, MSG.Abort, FsmAbortTask, STATE.Idle);
//Leak Check
Transition(STATE.Idle, MSG.LeakCheck, FsmStartLeakCheck, STATE.LeakCheck);
Transition(STATE.LeakCheck, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle);
@ -332,7 +341,7 @@ namespace Mainframe.UnLoads
DATA.Subscribe($"{Name}.CurrentRoutineLoop", () => CurrentRoutineLoop, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Name}.CurrentRoutineLoopTotal", () => CurrentRoutineLoopTotal, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Name}.RemainedCoolingTime", () => _unloadCoolingRoutine.GetRemainedTime());
DATA.Subscribe($"{Name}.RemainedCoolingTime", () => _unloadCoolingAndPurgeRoutine.GetRemainedTime());
/*
@ -543,6 +552,14 @@ namespace Mainframe.UnLoads
return ret == Result.RUN;
}
private bool FsmStartCoolingAndPurge(object[] param)
{
Result ret = StartRoutine(_unloadCoolingAndPurgeRoutine, param);
if (ret == Result.FAIL || ret == Result.DONE)
return false;
return ret == Result.RUN;
}
private bool FsmStartCooling(object[] param)
{
_unloadCoolingRoutine.Init((int)param[0]);
@ -590,6 +607,14 @@ namespace Mainframe.UnLoads
return (int)FSM_MSG.NONE;
}
public override int InvokeCoolingAndPurge(int timeInSec, int purgeLoopCount, int purgePumpDelay)
{
if (CheckToPostMessage((int)MSG.CoolingAndPurge, timeInSec, purgeLoopCount, purgePumpDelay))
return (int)MSG.CoolingAndPurge;
return (int)FSM_MSG.NONE;
}
public override int InvokeVent()
{
if (CheckToPostMessage((int)MSG.Vent))

View File

@ -42,6 +42,9 @@ namespace Mainframe.UnLoads
public abstract bool CheckReadyForMap(ModuleName robot, Hand blade, out string reason);
public abstract int InvokeCooling(int time);
public abstract int InvokeCoolingAndPurge(int time, int purgeLoopCount, int purgePumpDelay);
public abstract int InvokeVent();
public abstract int InvokePump();
public abstract int InvokePurge(params object[] objs);

View File

@ -1459,8 +1459,6 @@
<configs name="Purge">
<config default="3" name="CyclePurgeCount" description="吹扫的循环次数" max="1000" min="0" paramter="" tag="" unit="次" type="Integer" />
<config default="1" name="CyclePurgeCountAfterWaferPlaced" description="当Tray来自TMRobot时Wafer放好后的吹扫的循环次数" max="1000" min="0" paramter="" tag="" unit="次" type="Integer" />
<config default="10" name="PurgeDelayTimeAfterWaferPlaced" description="当Tray来自TMRobot时Wafer放好后的吹扫抽气延时" max="1000" min="0" paramter="" tag="" unit="s" type="Integer" />
<config default="0" name="PumpBasePressure" description="抽气的底压" max="1000" min="0" paramter="" tag="" unit="mbar" type="Double" />
<config default="10" name="PumpDelayTime" description="抽气到底压后,继续抽气多长时间" max="1000" min="0" paramter="" tag="" unit="s" type="Integer" />
<config default="100" name="PumpTimeOut" description="抽气超时时间" max="1000" min="0" paramter="" tag="" unit="s" type="Integer" />
@ -1506,7 +1504,8 @@
<config default="100" name="WarnTemprature" description="高于此温度需要报Warnning" max="900" min="0" paramter="" tag="" unit="s" type="Double" />
<config default="10" name="HomeTimeout" description="home time out" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
<config default="10" name="LiftMoveTimeOut" description="LiftMoveTimeOut" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
<config default="10" name="ClawMoveTimeOut" description="ClawMoveTimeOut" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
<config default="10" name="ClawMoveTimeOut" description="ClawMoveTimeOut" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
<config default="200" name="CoolingTimeFallback" description="当Sequence设定的Cooling时间无效时回落到此时间" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
<configs name="Home">
<config default="250" name="RoutineTimeOut" description="Routine超时时间" max="3000" min="0" paramter="" tag="" unit="s" type="Integer" />

View File

@ -1632,18 +1632,19 @@ namespace SicRT.Modules
private void MonitorLoadTask()
{
// 如果是第一次喂Wafer进来或第一次检测到Wafer被取走则重置Load腔状态。
if (_load.FirstDetectWaferArrive(0) || _load.FirstDetectWaferLeave(0))
{
Debug.WriteLine("Reset Purge Status!");
_load.ResetPurgedAndGroupedStatus();
}
if (!_load.IsAvailable)
{
return;
}
// 如果Load腔有Wafer和Tray并且Tray的工艺次数没有超过限制
if (_load.HasWafer(0) && _load.HasTrayAndNotExceedProcessCount(0))
{
@ -1653,24 +1654,9 @@ namespace SicRT.Modules
_load.GroupWaferTray();
return;
}
// 如果Group后还未Purge先执行Purge
if (!_load.HasPurgedAfterGrouped && _load.CheckWaferTrayGrouped())
{
if (_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0)
&& !_unload.IsInPumping)
{
// Group以后执行吹扫动作
_load.PurgeAfterGrouped(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
_load.GetWaferInfo(0).NextSequenceStep++;
return;
}
return;
}
// 如果没Purge过啥也不干
if (_load.HasPurgedAfterGrouped == false)
if (_load.HasPurged == false)
return;
// 有Wafer和石墨盘等待TM来取
@ -1722,16 +1708,8 @@ namespace SicRT.Modules
|| (_buffer.HasTray(1) && _buffer.NoWafer(1))
|| (_buffer.HasTray(2) && _buffer.NoWafer(2)))
{
// TMRobot放Tray前先Purge
if (!_load.HasPurgedAfterWaferPlaced && !_unload.IsInPumping)
{
var cycle = SC.GetValue<int>($"{ModuleName.LoadLock}.Purge.CyclePurgeCountAfterWaferPlaced");
var delay = SC.GetValue<int>($"{ModuleName.LoadLock}.Purge.PurgeDelayTimeAfterWaferPlaced");
_load.PurgeAfterWaferPlaced(cycle, delay);
}
// 如果还没Purge阻止TMRobot放Tray
if (!_load.HasPurgedAfterWaferPlaced)
if (!_load.HasPurged)
return;
if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0)
@ -1765,15 +1743,22 @@ namespace SicRT.Modules
{
_unload.ResetPurgedAndSeparatedStatus();
}
// 如果Load等着TMRobot来拿盘先保障Load
if (_load.HasWafer(0) && _load.HasTray(0) && !_tmRobot.HasTray(0) && !_tmRobot.HasWafer(0))
return;
// TM把Wafer和Tray放如UnLoad后先冷却再分离然后取Tray前Purge
if (_unload.HasWafer(0) && _unload.HasTray(0))
{
// 如果没冷却,先冷却
if (!_unload.CheckCoolingCompleted())
{
GetWaferSequenceCoolingTime(_unload.Module, 0, out int coolingTime);
_unload.Cooling(true, coolingTime);
GetWaferSequenceCoolingTime(_unload.Module, 0, out var coolingTime);
_unload.CoolingAndPurge(
true,
coolingTime, _unload.GetWaferPurgeCount(0),
_unload.GetWaferPumpDelayTime(0));
return;
}
@ -1790,7 +1775,7 @@ namespace SicRT.Modules
if (_unload.CheckWaferTraySeparated())
{
// 如果Sequence下一步是UnLoad,并且W&T已冷却和分离
if (!_unload.CheckPurgedBeforeTrayPicking()
if (!_unload.CheckPurgedBeforeTrayPicking()
&& !_load.IsInPumping)
{
_unload.PurgeBeforeTrayPicking(_unload.GetWaferPurgeCount(0),
@ -1840,6 +1825,14 @@ namespace SicRT.Modules
}
else // 如果UnLoad里啥也没有则准备好下次TMRobot喂 W&T
{
// 优先保证Load腔Purge和PrepareTransfer
if ((!_tmRobot.IsReadyForPlace(ModuleName.UnLoad, 0) && _load.CheckWaferNeedProcess(0))
|| _aligner.CheckWaferNeedProcess(0)
|| _waferRobot.CheckWaferNeedProcess(0)
|| GetCurrentTrayCount() <= 1)
return;
// 如果Wafer取完后还没有Purge先Purge
if (!_unload.CheckPurgedAfterWaferPicked() && !_load.IsInPumping)
{
@ -2021,10 +2014,27 @@ namespace SicRT.Modules
if (!_tmRobot.IsAvailable)
return;
//place TMRobot有Tray无Wafer, Load无Tray
canPlace = _tmRobot.HasTray(0) && _tmRobot.NoWafer(0) && _load.NoTray(0) && _load.HasWafer(0);
// TMRobot有Tray无Wafer, Load有Wafer无Tray准备TMRobot放Tray到Load
canPlace = _tmRobot.HasTray(0) && _tmRobot.NoWafer(0)
&& _load.NoTray(0) && _load.HasWafer(0);
if (canPlace)
{
// 如果 Wafer还没Purge先Purge Wafer
if (!_load.HasPurged)
{
if (_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0)
&& !_unload.IsInPumping)
{
// Group以后执行吹扫动作
_load.Purge(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
_load.GetWaferInfo(0).NextSequenceStep++;
return;
}
return;
}
if (_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping)
{
if (_tmRobot.Place(_load.Module, 0, Hand.Blade1))
@ -2042,16 +2052,28 @@ namespace SicRT.Modules
return;
//pick TM无Tray,需要Process,下一个位置没有Tray
bool canPick = _tmRobot.NoTray(0) && _load.CheckWaferNeedProcess(0) &&
!_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0) &&
_load.CheckWaferNextStepModuleNoTray(0);
bool canPick = _tmRobot.NoTray(0) && _load.CheckWaferNeedProcess(0);
if (canPick)
{
//需要完成组合和Purge
// 没组合先组合
if (!_load.CheckWaferTrayGrouped())
return;
// 没Purge先Purge
if (!_load.HasPurged)
{
if (_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0)
&& !_unload.IsInPumping)
{
// Group以后执行吹扫动作
_load.Purge(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
_load.GetWaferInfo(0).NextSequenceStep++;
return;
}
return;
}
if (_load.IsReadyForPick(ModuleName.TMRobot, 0) && !_unload.IsInPumping)
{
@ -2156,43 +2178,47 @@ namespace SicRT.Modules
if (!_buffer.IsAvailable)
return;
//place 最后没有新的wafer需要工艺时完成工艺后的Tray放入Buffer中
canPalce = _tmRobot.HasTray(0) && _tmRobot.NoWafer(0);
if (canPalce)
// TMRobot有Tray没wafer
var canPlaceTrayToBuffer =
_tmRobot.HasTray(0)
&& _tmRobot.NoWafer(0)
&& (!_load.CheckWaferNeedProcess(0)
|| (_load.CheckWaferNeedProcess(0)
&& _trayRobot.HasTray(0)
&& _trayRobot.IsReadyForPlace(ModuleName.LoadLock, 0)));
if (canPlaceTrayToBuffer)
{
// TMRobot有Tray并且Tray已消耗完Load空则准备将Tray返回Cassette
if (_tmRobot.HasTrayAndExceedProcessCount(0) && _load.NoTray(0) && _load.NoWafer(0))
return;
if (!_tmRobot.CheckWaferNeedProcess(0)
&& GetWaferInJobQueue() == null
&& !_load.CheckWaferNeedProcess(0)
&& !_aligner.CheckWaferNeedProcess(0)
&& !_waferRobot.CheckWaferNeedProcess(0))
{
SlotItem bufferEmptySlot = null;
for (int i = 0; i < 3; i++)
{
if (_buffer.NoTray(i) && _buffer.NoWafer(i))
{
bufferEmptySlot = new SlotItem(ModuleName.Buffer, i);
break;
}
}
// 如果Load已经准备好接收Tray则不要将Tray放如Buffer
if (_load.HasWafer(0) && _load.IsReadyForPlace(ModuleName.TMRobot, 0))
return;
if (bufferEmptySlot == null)
SlotItem bufferEmptySlot = null;
for (int i = 0; i < 3; i++)
{
if (_buffer.NoTray(i) && _buffer.NoWafer(i))
{
bufferEmptySlot = new SlotItem(ModuleName.Buffer, i);
break;
}
}
if (bufferEmptySlot == null)
{
return;
}
if (_buffer.IsReadyForPlace(ModuleName.TMRobot, bufferEmptySlot.Slot))
{
if (_tmRobot.Place(_buffer.Module, bufferEmptySlot.Slot, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
if (_buffer.IsReadyForPlace(ModuleName.TMRobot, bufferEmptySlot.Slot))
{
if (_tmRobot.Place(_buffer.Module, bufferEmptySlot.Slot, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
@ -2251,6 +2277,7 @@ namespace SicRT.Modules
continue;
}
// 取Wafer准备送入PM
if (_buffer.CheckWaferNextStepModuleNoTray(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
@ -2275,9 +2302,8 @@ namespace SicRT.Modules
//pick 工艺开始时,如果Buffer中有Tray时,优先取Buffer中的Tray而不是Cst中Tray
canPick = _tmRobot.NoTray(0)
&& _load.IsReadyForPlace(ModuleName.TMRobot, 0)
&& _load.NoTray(0)
//&& _load.HasWafer(0)
&& _trayRobot.NoTray(0) && _trayRobot.CheckTaskDone()
&& ((GetWaferInJobQueue() != null || _aligner.CheckWaferNeedProcess(0) || _waferRobot.CheckWaferNeedProcess(0)) || _load.CheckWaferNeedProcess(0));
if (canPick)
{
@ -2301,7 +2327,7 @@ namespace SicRT.Modules
{
if (_buffer.HasTray(i) && _buffer.NoWafer(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i) && _load.IsReadyForPlace(ModuleName.TMRobot, 0))
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i) && _load.CheckWaferNeedProcess(0))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{

View File

@ -57,17 +57,12 @@ namespace SicRT.Scheduler
_task == TaskType.Pump || _task == TaskType.Purge || _task == TaskType.PrepareTransfer;
/// <summary>
/// 是否执行放Wafer后TM放Tray前的Purge。
/// 是否执行Purge。
/// <para>如果Tray来自TMRobot放完Wafer马上Purge。</para>
/// <para>如果Tray来自TrayCassette放完Tray以后统一Purge。</para>
/// </summary>
public bool HasPurgedAfterWaferPlaced { get; private set; }
/// <summary>
/// 是否已执行组合后、TM取盘前的Purge.
/// <para>无论Tray来自TMRobot还是TrayRobotGroup以后一定要Purge。</para>
/// <para>Purge次数使用Sequence中的配置。</para>
public bool HasPurgedAfterGrouped { get; private set; }
public bool HasPurged { get; private set; }
#endregion
@ -157,8 +152,7 @@ namespace SicRT.Scheduler
{
lock (SyncRoot)
{
HasPurgedAfterWaferPlaced = false;
HasPurgedAfterGrouped = false;
HasPurged = false;
}
}
@ -195,20 +189,20 @@ namespace SicRT.Scheduler
}
/// <summary>
/// Wafer放好后如果Tray将从TMRobot喂进来执行此Purge。
/// <para>Purge次数有Configuration\LoadLock\Purge中的相关次数决定。</para>
/// Purge次数由Sequence中的设定决定
///<para></para>
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public bool PurgeAfterWaferPlaced(params object[] args)
public bool Purge(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task, " Purge after wafer placed was ignored since the cycle is zero");
HasPurgedAfterGrouped = true;
LogTaskStart(_task, " Purge was ignored since the cycle is zero");
HasPurged = true;
return true;
}
@ -216,39 +210,8 @@ namespace SicRT.Scheduler
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $" Purge after wafer placed");
HasPurgedAfterWaferPlaced = true;
return true;
}
return false;
}
}
/// <summary>
/// 当Wafer和Tray组合完毕后执行此Purge。
/// <para>组合完毕后无条件支持此PurgePurge次数有Sequence设定。</para>
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public bool PurgeAfterGrouped(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task, " Purge after Grouping was ignored since the cycle is zero");
HasPurgedAfterGrouped = true;
return true;
}
_entityTaskToken = _ll.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $"Purge after grouping");
HasPurgedAfterGrouped = true;
LogTaskStart(_task, $"Purging");
HasPurged = true;
return true;
}

View File

@ -40,6 +40,7 @@ namespace SicRT.Modules.Schedulers
TransferTarget,
Cooling,
CoolingAndPurge,
WarmUp,
Vent,
@ -530,6 +531,14 @@ namespace SicRT.Modules.Schedulers
}
}
public virtual bool CoolingAndPurge(bool coolingType, int coolingTime, int purgeLoopCount, int purgePumpDelay)
{
lock (SyncRoot)
{
return true;
}
}
public virtual bool Aligning()
{
lock (SyncRoot)

View File

@ -186,6 +186,24 @@ namespace SicRT.Scheduler
}
}
public override bool CoolingAndPurge(bool coolingType, int coolingTime, int purgeLoopCount, int purgePumpDelay)
{
lock (SyncRoot)
{
_entityTaskToken = _unL.InvokeCoolingAndPurge(coolingTime, purgeLoopCount, purgePumpDelay);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.CoolingAndPurge;
_purgedBefTrayPicking = true;
LogTaskStart(_task, $"{Module} cooling&purge {coolingTime} seconds");
}
_coolingCompleted = _entityTaskToken != (int)FSM_MSG.NONE;
return _entityTaskToken != (int)FSM_MSG.NONE;
}
}
public override bool Cooling(bool coolingType, int coolingTime)
{
lock (SyncRoot)
@ -383,26 +401,26 @@ namespace SicRT.Scheduler
}
}
public int? GetWaferPurgeCount(int slot)
public int GetWaferPurgeCount(int slot)
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return null;
return 0;
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return null;
return 0;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return null;
return 0;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(Module))
return null;
return 0;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("PurgeCount"))
return null;
return 0;
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PurgeCount"].ToString(),
@ -411,30 +429,30 @@ namespace SicRT.Scheduler
return purgeCount;
}
return null;
return 0;
}
}
public int? GetWaferPumpDelayTime(int slot)
public int GetWaferPumpDelayTime(int slot)
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return null;
return 0;
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return null;
return 0;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return null;
return 0;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(Module))
return null;
return 0;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("PumpDelayTime"))
return null;
return 0;
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PumpDelayTime"]
@ -443,7 +461,7 @@ namespace SicRT.Scheduler
return pumpDelayTime;
}
return null;
return 0;
}
}
@ -468,6 +486,9 @@ namespace SicRT.Scheduler
case TaskType.Cooling:
ret = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.CoolingAndPurge:
ret = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Vent:
ret = _unL.CheckAcked(_entityTaskToken);
break;

View File

@ -554,11 +554,11 @@ namespace SicSimulator.Instances
if (isSlowVent)
{
if (pressure < 300)
if (pressure < 400)
{
pressure += (2 * _simSpeed);
}
else if (pressure < 400)
else if (pressure < 450)
{
pressure += (10 * _simSpeed);
}
@ -626,11 +626,11 @@ namespace SicSimulator.Instances
if (isSlowVent)
{
if (unloadPressure < 300)
if (unloadPressure < 400)
{
unloadPressure += (2 * _simSpeed);
}
else if (unloadPressure < 400)
else if (unloadPressure < 450)
{
unloadPressure += (10 * _simSpeed);
}

View File

@ -820,7 +820,7 @@
VerticalContentAlignment="Center"
Background="{DynamicResource Table_BG_Title}"
BorderBrush="{DynamicResource Table_BD}"
Content="ColingTime(s)"
Content="CoolingTime(s)"
FontFamily="Arial"
FontSize="12" />