diff --git a/FrameworkLocal/SimulatorCore/IoProviders/SimulatorIO.cs b/FrameworkLocal/SimulatorCore/IoProviders/SimulatorIO.cs index d71e879..cf0d7ab 100644 --- a/FrameworkLocal/SimulatorCore/IoProviders/SimulatorIO.cs +++ b/FrameworkLocal/SimulatorCore/IoProviders/SimulatorIO.cs @@ -11,6 +11,8 @@ namespace MECF.Framework.Simulator.Core.IoProviders { private Random _rd = new Random(); + private readonly object _syncRoot = new object(); + public ObservableCollection DiItemList { get; set; } public ObservableCollection DoItemList { get; set; } public ObservableCollection AiItemList { get; set; } @@ -63,94 +65,97 @@ namespace MECF.Framework.Simulator.Core.IoProviders void Init() { - if (DiItemList == null) + lock (_syncRoot) { - List diItems = IO.GetDiList(_source); - if (diItems != null) + if (DiItemList == null) { - DiItemList = new ObservableCollection(); - foreach (var diItem in diItems) + List diItems = IO.GetDiList(_source); + if (diItems != null) { - NotifiableIoItem item = new NotifiableIoItem() + DiItemList = new ObservableCollection(); + 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 doItems = IO.GetDoList(_source); - if (doItems != null) + if (DoItemList == null) { - DoItemList = new ObservableCollection(); - foreach (var ioItem in doItems) + List doItems = IO.GetDoList(_source); + if (doItems != null) { - NotifiableIoItem item = new NotifiableIoItem() + DoItemList = new ObservableCollection(); + 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 aiItems = IO.GetAiList(_source); - if (aiItems != null) + if (AiItemList == null) { - AiItemList = new ObservableCollection(); - foreach (var ioItem in aiItems) + List aiItems = IO.GetAiList(_source); + if (aiItems != null) { - NotifiableIoItem item = new NotifiableIoItem() + AiItemList = new ObservableCollection(); + 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 aoItems = IO.GetAoList(_source); - if (aoItems != null) + if (AoItemList == null) { - AoItemList = new ObservableCollection(); - foreach (var ioItem in aoItems) + List aoItems = IO.GetAoList(_source); + if (aoItems != null) { - NotifiableIoItem item = new NotifiableIoItem() + AoItemList = new ObservableCollection(); + 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(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(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(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(plcBuffer.ShortValue, x => (short)x)); - } - }} - } - } - - - - - return true; } diff --git a/FrameworkLocal/UIClient/CenterViews/DataLogs/DataHistory/DataViewModel.cs b/FrameworkLocal/UIClient/CenterViews/DataLogs/DataHistory/DataViewModel.cs index 7e0850b..4477f4e 100644 --- a/FrameworkLocal/UIClient/CenterViews/DataLogs/DataHistory/DataViewModel.cs +++ b/FrameworkLocal/UIClient/CenterViews/DataLogs/DataHistory/DataViewModel.cs @@ -482,7 +482,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory } /// - /// 根据左侧选项查询数据 + /// 根据DataLog界面左侧项目树中选择的项目查询数据 /// /// 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; } + /// + /// IO节点在数据库中的表名比较特殊,需要特殊处理。 + /// + /// + /// + /// + /// + /// + private static DataTable SearchSingleDbTable(TreeNode module, DateRangeHelper dateRange, + CancellationTokenSource cancellation = null, + IProgress 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; + } + /// /// 渲染图表。 /// diff --git a/Modules/Mainframe/LLs/Routines/LoadLockPurgeRoutine.cs b/Modules/Mainframe/LLs/Routines/LoadLockPurgeRoutine.cs index 21b883c..517c5fe 100644 --- a/Modules/Mainframe/LLs/Routines/LoadLockPurgeRoutine.cs +++ b/Modules/Mainframe/LLs/Routines/LoadLockPurgeRoutine.cs @@ -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() diff --git a/Modules/Mainframe/Mainframe.csproj b/Modules/Mainframe/Mainframe.csproj index 7644a22..ee55e5d 100644 --- a/Modules/Mainframe/Mainframe.csproj +++ b/Modules/Mainframe/Mainframe.csproj @@ -149,6 +149,7 @@ + diff --git a/Modules/Mainframe/UnLoads/Routines/UnLoadCoolingAndPurgeRoutine.cs b/Modules/Mainframe/UnLoads/Routines/UnLoadCoolingAndPurgeRoutine.cs new file mode 100644 index 0000000..b2a2ded --- /dev/null +++ b/Modules/Mainframe/UnLoads/Routines/UnLoadCoolingAndPurgeRoutine.cs @@ -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("UnLoad.CoolingTimeFallback"); + _purgeCount = SC.GetValue("UnLoad.Purge.CyclePurgeCount"); + _pumpDelayTime = SC.GetValue("UnLoad.Purge.PumpDelayTime"); + } + + _routineTimeOut = SC.GetValue("UnLoad.Purge.RoutineTimeOut"); + _pumpSwitchPressure = SC.GetValue("UnLoad.Pump.SlowFastPumpSwitchPressure"); + _pumpBasePressure = SC.GetValue("UnLoad.Purge.PumpBasePressure"); + _pumpTimeOut = SC.GetValue("UnLoad.Purge.PumpTimeOut"); + _ventBasePressure = SC.GetValue("UnLoad.Purge.VentBasePressure"); + _ventDelayTime = SC.GetValue("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("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; + } + } +} diff --git a/Modules/Mainframe/UnLoads/Routines/UnLoadPurgeRoutine.cs b/Modules/Mainframe/UnLoads/Routines/UnLoadPurgeRoutine.cs index ead05ca..63b22e4 100644 --- a/Modules/Mainframe/UnLoads/Routines/UnLoadPurgeRoutine.cs +++ b/Modules/Mainframe/UnLoads/Routines/UnLoadPurgeRoutine.cs @@ -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() diff --git a/Modules/Mainframe/UnLoads/UnLoadModule.cs b/Modules/Mainframe/UnLoads/UnLoadModule.cs index 17a7806..7c8acf6 100644 --- a/Modules/Mainframe/UnLoads/UnLoadModule.cs +++ b/Modules/Mainframe/UnLoads/UnLoadModule.cs @@ -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)) diff --git a/Modules/Mainframe/UnLoads/UnLoadModuleBase.cs b/Modules/Mainframe/UnLoads/UnLoadModuleBase.cs index 549ebdf..1e43a24 100644 --- a/Modules/Mainframe/UnLoads/UnLoadModuleBase.cs +++ b/Modules/Mainframe/UnLoads/UnLoadModuleBase.cs @@ -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); diff --git a/SicRT/Config/System.sccfg b/SicRT/Config/System.sccfg index a192861..a413ce4 100644 --- a/SicRT/Config/System.sccfg +++ b/SicRT/Config/System.sccfg @@ -1459,8 +1459,6 @@ - - @@ -1506,7 +1504,8 @@ - + + diff --git a/SicRT/Equipments/AutoTransfer.cs b/SicRT/Equipments/AutoTransfer.cs index 3dadc49..30a1ebb 100644 --- a/SicRT/Equipments/AutoTransfer.cs +++ b/SicRT/Equipments/AutoTransfer.cs @@ -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($"{ModuleName.LoadLock}.Purge.CyclePurgeCountAfterWaferPlaced"); - var delay = SC.GetValue($"{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)) { diff --git a/SicRT/Equipments/Schedulers/SchedulerLoadLock.cs b/SicRT/Equipments/Schedulers/SchedulerLoadLock.cs index 4b811f3..f876c87 100644 --- a/SicRT/Equipments/Schedulers/SchedulerLoadLock.cs +++ b/SicRT/Equipments/Schedulers/SchedulerLoadLock.cs @@ -57,17 +57,12 @@ namespace SicRT.Scheduler _task == TaskType.Pump || _task == TaskType.Purge || _task == TaskType.PrepareTransfer; /// - /// 是否执行放Wafer后,TM放Tray前的Purge。 + /// 是否执行Purge。 /// 如果Tray来自TMRobot,放完Wafer马上Purge。 /// 如果Tray来自TrayCassette,放完Tray以后统一Purge。 /// - public bool HasPurgedAfterWaferPlaced { get; private set; } - - /// - /// 是否已执行组合后、TM取盘前的Purge. - /// 无论Tray来自TMRobot还是TrayRobot,Group以后一定要Purge。 - /// Purge次数使用Sequence中的配置。 - 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 } /// - /// Wafer放好后,如果Tray将从TMRobot喂进来,执行此Purge。 - /// Purge次数有Configuration\LoadLock\Purge中的相关次数决定。 + /// Purge,次数由Sequence中的设定决定。 + /// /// /// /// - 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; - } - } - - /// - /// 当Wafer和Tray组合完毕后,执行此Purge。 - /// 组合完毕后无条件支持此Purge,Purge次数有Sequence设定。 - /// - /// - /// - 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; } diff --git a/SicRT/Equipments/Schedulers/SchedulerModule.cs b/SicRT/Equipments/Schedulers/SchedulerModule.cs index eeacefa..7065bdc 100644 --- a/SicRT/Equipments/Schedulers/SchedulerModule.cs +++ b/SicRT/Equipments/Schedulers/SchedulerModule.cs @@ -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) diff --git a/SicRT/Equipments/Schedulers/SchedulerUnLoad.cs b/SicRT/Equipments/Schedulers/SchedulerUnLoad.cs index 2541cfa..3254455 100644 --- a/SicRT/Equipments/Schedulers/SchedulerUnLoad.cs +++ b/SicRT/Equipments/Schedulers/SchedulerUnLoad.cs @@ -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; diff --git a/SicSimulator/Instances/SimulatorSystem.cs b/SicSimulator/Instances/SimulatorSystem.cs index 8d14f3d..b46536a 100644 --- a/SicSimulator/Instances/SimulatorSystem.cs +++ b/SicSimulator/Instances/SimulatorSystem.cs @@ -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); } diff --git a/SicUI/Models/Maintenances/TM/TMView.xaml b/SicUI/Models/Maintenances/TM/TMView.xaml index d1631cb..7c66d99 100644 --- a/SicUI/Models/Maintenances/TM/TMView.xaml +++ b/SicUI/Models/Maintenances/TM/TMView.xaml @@ -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" />