|
@@ -13,12 +13,14 @@ using Aitex.Core.RT.Log;
|
|
|
using Aitex.Core.RT.SCCore;
|
|
|
using Aitex.Core.Util;
|
|
|
using Aitex.Sorter.Common;
|
|
|
+using Aitex.Core.RT.RecipeCenter;
|
|
|
using Venus_RT.Modules;
|
|
|
using Venus_RT.Modules.PMs;
|
|
|
using MECF.Framework.Common.Equipment;
|
|
|
using MECF.Framework.Common.Schedulers;
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
|
using Venus_RT.Devices;
|
|
|
+using Venus_Core;
|
|
|
|
|
|
namespace Venus_RT.Scheduler
|
|
|
{
|
|
@@ -27,7 +29,7 @@ namespace Venus_RT.Scheduler
|
|
|
{
|
|
|
public override bool IsAvailable
|
|
|
{
|
|
|
- get { return _entity.IsIdle && (_entity.IsOnline || !Singleton<RouteManager>.Instance.IsAutoMode) && CheckTaskDone() && !_waitCompletejobClean; }
|
|
|
+ get { return _entity.IsIdle && (_entity.IsOnline || !Singleton<RouteManager>.Instance.IsAutoMode) && CheckTaskDone(); }
|
|
|
|
|
|
}
|
|
|
public override bool IsOnline
|
|
@@ -58,6 +60,13 @@ namespace Venus_RT.Scheduler
|
|
|
private DeviceTimer _timerProcess = new DeviceTimer();
|
|
|
private JetPMBase _pm;
|
|
|
|
|
|
+ private int _idleCleanOpt = 0;
|
|
|
+ private int _idleCleanHourSetPoint;
|
|
|
+ private int _idleCleanWaferSetPoint;
|
|
|
+ private int _idleCleanWaferCount;
|
|
|
+ private string _idleCleanRecipe;
|
|
|
+ private DateTime _lastRunTime = new DateTime();
|
|
|
+
|
|
|
private float _paramTemp;
|
|
|
|
|
|
public float Temperature
|
|
@@ -75,49 +84,21 @@ namespace Venus_RT.Scheduler
|
|
|
}
|
|
|
|
|
|
|
|
|
- public RD_TRIG IdlePurgeTrig { get; set; }
|
|
|
- public Stopwatch IdlePurgeTimer { get; set; }
|
|
|
- public int IdlePurgeTime { get; set; }
|
|
|
- public int IdlePurgeNextRunTime { get; set; }
|
|
|
-
|
|
|
- public RD_TRIG IdleCleanTrig { get; set; }
|
|
|
- public Stopwatch IdleCleanTimer { get; set; }
|
|
|
- public int IdleCleanTime { get; set; }
|
|
|
- public int IdleCleanNextRunTime { get; set; }
|
|
|
-
|
|
|
- private bool _waitPreJobClean;
|
|
|
- private bool _waitCompletejobClean;
|
|
|
-
|
|
|
- private R_TRIG _trigIdleCleanFailed = new R_TRIG();
|
|
|
- private R_TRIG _trigIdlePurgeFailed = new R_TRIG();
|
|
|
-
|
|
|
- public RD_TRIG PreJobCleanTrig { get; set; }
|
|
|
- public Stopwatch PreJobCleanTimer { get; set; }
|
|
|
- public int PreJobCleanTime { get; set; }
|
|
|
-
|
|
|
public SchedulerPM(ModuleName chamber) : base(chamber.ToString())
|
|
|
{
|
|
|
_entity = Singleton<RouteManager>.Instance.GetPM(chamber);
|
|
|
|
|
|
_pm = DEVICE.GetDevice<JetPMBase>(Module.ToString());
|
|
|
|
|
|
-
|
|
|
- IdlePurgeTrig = new RD_TRIG();
|
|
|
- IdlePurgeTimer = new Stopwatch();
|
|
|
-
|
|
|
- IdleCleanTrig = new RD_TRIG();
|
|
|
- IdleCleanTimer = new Stopwatch();
|
|
|
-
|
|
|
- PreJobCleanTrig = new RD_TRIG();
|
|
|
- PreJobCleanTimer = new Stopwatch();
|
|
|
-
|
|
|
EventWaferArrived += WaferArrived;
|
|
|
+
|
|
|
+ LoadIdleCleanOpt();
|
|
|
}
|
|
|
|
|
|
public void InitClean()
|
|
|
{
|
|
|
- DATA.Subscribe($"{Module}.IdlePurgeNextRunTime", () => IdlePurgeNextRunTime);
|
|
|
- DATA.Subscribe($"{Module}.IdleCleanNextRunTime", () => IdleCleanNextRunTime);
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public override bool IsReadyForPick(ModuleName robot, int slot, Hand blade)
|
|
@@ -325,10 +306,7 @@ namespace Venus_RT.Scheduler
|
|
|
|
|
|
public void PreJobClean()
|
|
|
{
|
|
|
- var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
|
|
|
- var enablePreJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnablePreJobClean");
|
|
|
|
|
|
- _waitPreJobClean = enableJobClean && enablePreJobClean;
|
|
|
}
|
|
|
|
|
|
public bool PreJobProcess(string recipeName)
|
|
@@ -341,13 +319,6 @@ namespace Venus_RT.Scheduler
|
|
|
return _entityTaskToken != (int)FSM_MSG.NONE;
|
|
|
}
|
|
|
|
|
|
- public void CompleteJobClean()
|
|
|
- {
|
|
|
- var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
|
|
|
- var enableCompleteJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnableCompleteJobClean");
|
|
|
-
|
|
|
- _waitCompletejobClean = enableJobClean && enableCompleteJobClean;
|
|
|
- }
|
|
|
|
|
|
public bool CompleteJobProcess(string recipeName)
|
|
|
{
|
|
@@ -362,281 +333,99 @@ namespace Venus_RT.Scheduler
|
|
|
private void WaferArrived(object sender, EventArgs e)
|
|
|
{
|
|
|
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, 0);
|
|
|
- string attr = $"{Module}Recipe";
|
|
|
- string recipeName = string.Empty;
|
|
|
- if(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(Module))
|
|
|
- {
|
|
|
- recipeName = (string)wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[attr];
|
|
|
- }
|
|
|
- else
|
|
|
+ string recipeName = wafer.ProcessJob.Sequence.GetRecipe(Module);
|
|
|
+ if(recipeName.Length > 0)
|
|
|
{
|
|
|
- recipeName = (string)wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepParameter[attr];
|
|
|
+ Process(recipeName, false, true, wafer);
|
|
|
}
|
|
|
-
|
|
|
- Process((string)recipeName, false, true, wafer);
|
|
|
}
|
|
|
|
|
|
#region clean task
|
|
|
|
|
|
- internal void ResetIdlePurgeTime()
|
|
|
- {
|
|
|
- IdlePurgeTimer.Restart();
|
|
|
- }
|
|
|
-
|
|
|
- internal void ResetIdleCleanTime()
|
|
|
- {
|
|
|
- IdleCleanTimer.Restart();
|
|
|
- }
|
|
|
-
|
|
|
- public bool ResetClean(bool resetPurge, bool resetClean, bool jobClean)
|
|
|
- {
|
|
|
- if (resetPurge)
|
|
|
- {
|
|
|
- IdlePurgeTrig.RST = true;
|
|
|
- IdlePurgeTimer.Stop();
|
|
|
- IdlePurgeTime = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (resetClean)
|
|
|
- {
|
|
|
- IdleCleanTrig.RST = true;
|
|
|
- IdleCleanTimer.Stop();
|
|
|
- IdleCleanTime = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (jobClean)
|
|
|
- {
|
|
|
- _waitPreJobClean = false;
|
|
|
- _waitCompletejobClean = false;
|
|
|
- PreJobCleanTrig.RST = true;
|
|
|
- PreJobCleanTimer.Stop();
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public void MonitorCleanTasks()
|
|
|
+ private void LoadIdleCleanOpt()
|
|
|
{
|
|
|
- var hasWafer = WaferManager.Instance.CheckHasWafer(Module, 0);
|
|
|
- var enablePurge = false;
|
|
|
- var enableClean = SC.GetValue<bool>($"{Module}.IdleClean.IsEnabled");
|
|
|
-
|
|
|
- #region Idle Purge
|
|
|
-
|
|
|
- IdlePurgeTrig.CLK = (IsIdle || _task != TaskType.IdlePurgeProcess) && enablePurge && !hasWafer;
|
|
|
- if (IdlePurgeTrig.R)
|
|
|
- {
|
|
|
- LOG.Write( eEvent.INFO_PM, Module, $"{Module} idle purge start calc elapse time");
|
|
|
- IdlePurgeTimer.Restart();
|
|
|
- }
|
|
|
+
|
|
|
+ _idleCleanOpt = SC.GetValue<int>($"{Module}.IdleClean.Option");
|
|
|
+ _idleCleanHourSetPoint = SC.GetValue<int>($"{Module}.IdleClean.IdleCleanTime");
|
|
|
+ _idleCleanWaferSetPoint = SC.GetValue<int>($"{Module}.IdleClean.IdleCleanWaferCount");
|
|
|
+ _idleCleanWaferCount = SC.GetValue<int>($"{Module}.IdleClean.WaferCountSinceLastClean");
|
|
|
+ _idleCleanRecipe = SC.GetStringValue($"{Module}.IdleClean.IdleCleanRecipe");
|
|
|
|
|
|
- if (IdlePurgeTrig.T)
|
|
|
+ string lastRun = SC.GetStringValue($"{Module}.IdleClean.LastRunTime");
|
|
|
+ if (lastRun.Length > 10)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} idle purge stopped calc elapse time");
|
|
|
-
|
|
|
- ResetClean(true, false, false);
|
|
|
- }
|
|
|
-
|
|
|
- if (IdlePurgeTimer.IsRunning)
|
|
|
- {
|
|
|
- IdlePurgeTime = (int)IdlePurgeTimer.ElapsedMilliseconds / 1000;
|
|
|
- int idlePurgeTimeSetPoint = SC.GetValue<int>($"{Module}.IdlePurge.IdlePurgeTime");
|
|
|
- var nextRunTime = idlePurgeTimeSetPoint - IdlePurgeTime;
|
|
|
- if (nextRunTime < 0)
|
|
|
- nextRunTime = 0;
|
|
|
-
|
|
|
- if (enablePurge)
|
|
|
+ try
|
|
|
{
|
|
|
- if (nextRunTime <= 0 && IsAvailable)
|
|
|
- {
|
|
|
- var recipe = SC.GetStringValue($"{Module}.IdlePurge.IdlePurgeRecipe");
|
|
|
-
|
|
|
- if (string.IsNullOrEmpty(recipe))
|
|
|
- {
|
|
|
- _trigIdlePurgeFailed.CLK = true;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Idle purge can not run, recipe is empty");
|
|
|
- ResetClean(true, false, false);
|
|
|
- }
|
|
|
- else if (hasWafer)
|
|
|
- {
|
|
|
- _trigIdlePurgeFailed.CLK = true;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Idle purge can not run, has wafer");
|
|
|
- ResetClean(true, false, false);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- _trigIdlePurgeFailed.CLK = false;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Start run idle purge recipe {recipe}");
|
|
|
- IdlePurgeProcess("ALD\\Process\\" + recipe);
|
|
|
- }
|
|
|
-
|
|
|
- if (_trigIdlePurgeFailed.Q)
|
|
|
- {
|
|
|
- LOG.Write(eEvent.WARN_PM, Module, "Can not run idle purge recipe");
|
|
|
- }
|
|
|
- }
|
|
|
+ _lastRunTime = DateTime.Parse(lastRun);
|
|
|
}
|
|
|
- else
|
|
|
+ catch (Exception _)
|
|
|
{
|
|
|
- nextRunTime = 0;
|
|
|
+ lastRun = string.Empty;
|
|
|
}
|
|
|
-
|
|
|
- IdlePurgeNextRunTime = nextRunTime;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- IdlePurgeNextRunTime = 0;
|
|
|
}
|
|
|
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region Idle Clean
|
|
|
-
|
|
|
- IdleCleanTrig.CLK = (IsIdle || _task != TaskType.IdleCleanProcess) && enableClean && !hasWafer;
|
|
|
- if (IdleCleanTrig.R)
|
|
|
+ if (lastRun.Length <= 10)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} idle clean start calc elapse time");
|
|
|
-
|
|
|
- IdleCleanTimer.Restart();
|
|
|
- }
|
|
|
-
|
|
|
- if (IdleCleanTrig.T)
|
|
|
- {
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} idle clean stopped calc elapse time");
|
|
|
-
|
|
|
- ResetClean(false, true, false);
|
|
|
+ _lastRunTime = DateTime.Now;
|
|
|
+ SC.SetItemValueFromString($"{Module}.IdleClean.LastRunTime", _lastRunTime.ToString());
|
|
|
}
|
|
|
|
|
|
- if (IdleCleanTimer.IsRunning)
|
|
|
- {
|
|
|
- IdleCleanTime = (int)IdleCleanTimer.ElapsedMilliseconds / 1000;
|
|
|
-
|
|
|
- int idleCleanTimeSetPoint = SC.GetValue<int>($"{Module}.IdleClean.IdleCleanTime");
|
|
|
-
|
|
|
-
|
|
|
- var nextRunTime = idleCleanTimeSetPoint - IdleCleanTime;
|
|
|
- if (nextRunTime < 0)
|
|
|
- nextRunTime = 0;
|
|
|
-
|
|
|
- if (enableClean)
|
|
|
- {
|
|
|
- if (nextRunTime <= 0 && IsAvailable)
|
|
|
- {
|
|
|
- var recipe = SC.GetStringValue($"{Module}.IdleClean.IdleCleanRecipe");
|
|
|
-
|
|
|
- if (string.IsNullOrEmpty(recipe))
|
|
|
- {
|
|
|
- _trigIdleCleanFailed.CLK = true;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Idle clean can not run, recipe is empty");
|
|
|
- ResetClean(false, true, false);
|
|
|
- }
|
|
|
- else if (hasWafer)
|
|
|
- {
|
|
|
- _trigIdleCleanFailed.CLK = true;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Idle clean can not run, has wafer");
|
|
|
- ResetClean(false, true, false);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- _trigIdleCleanFailed.CLK = false;
|
|
|
-
|
|
|
- LOG.Write(eEvent.INFO_PM, Module, $"{Module} Start run idle Clean recipe {recipe}");
|
|
|
- IdleCleanProcess($"{Module}\\" + recipe);
|
|
|
- }
|
|
|
-
|
|
|
- if (_trigIdleCleanFailed.Q)
|
|
|
- {
|
|
|
- EV.PostWarningLog(Module.ToString(), "Can not run idle clean recipe");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- nextRunTime = 0;
|
|
|
- }
|
|
|
-
|
|
|
- IdleCleanNextRunTime = nextRunTime;
|
|
|
- }
|
|
|
- else
|
|
|
+
|
|
|
+ string recipeContent = RecipeFileManager.Instance.LoadRecipe(Module.ToString(), _idleCleanRecipe, false);
|
|
|
+ Recipe recipe = Recipe.Load(recipeContent);
|
|
|
+ if (recipe == null)
|
|
|
{
|
|
|
- IdleCleanNextRunTime = 0;
|
|
|
+ _idleCleanRecipe = string.Empty;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ public void WaferProcessDone()
|
|
|
+ {
|
|
|
+ _lastRunTime = DateTime.Now;
|
|
|
+ SC.SetItemValueFromString($"{Module}.IdleClean.LastRunTime", _lastRunTime.ToString());
|
|
|
|
|
|
- #region PreJob Clean
|
|
|
+ _idleCleanWaferCount++;
|
|
|
+ SC.SetItemValue($"{Module}.IdleClean.IdleCleanWaferCount", _idleCleanWaferCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ResetIdleCleanCounter()
|
|
|
+ {
|
|
|
+ _lastRunTime = DateTime.Now;
|
|
|
+ SC.SetItemValueFromString($"{Module}.IdleClean.LastRunTime", _lastRunTime.ToString());
|
|
|
|
|
|
- var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
|
|
|
- var enablePreJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnablePreJobClean");
|
|
|
- var enableCompleteJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnableCompleteJobClean");
|
|
|
+ _idleCleanWaferCount = 0;
|
|
|
+ SC.SetItemValue($"{Module}.IdleClean.IdleCleanWaferCount", _idleCleanWaferCount);
|
|
|
+ }
|
|
|
|
|
|
- if (enableJobClean && enableCompleteJobClean && _waitCompletejobClean && IsIdle)
|
|
|
+ public bool RunIdleCleanTask()
|
|
|
+ {
|
|
|
+ if(_idleCleanOpt == 1)
|
|
|
{
|
|
|
- var recipe = SC.GetStringValue($"{Module}.JobClean.CompleteJobCleanRecipe");
|
|
|
-
|
|
|
- if (string.IsNullOrEmpty(recipe))
|
|
|
- {
|
|
|
- EV.PostWarningLog(Module.ToString(), "complete job clean can not run, recipe is empty");
|
|
|
- }
|
|
|
- else if (hasWafer)
|
|
|
+ TimeSpan span = DateTime.Now - _lastRunTime;
|
|
|
+ if(span.TotalHours >= _idleCleanHourSetPoint)
|
|
|
{
|
|
|
- EV.PostWarningLog(Module.ToString(), "complete job clean can not run, has wafer");
|
|
|
+ Process(_idleCleanRecipe, true, false, null);
|
|
|
+ ResetIdleCleanCounter();
|
|
|
+ return true;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- EV.PostInfoLog(Module.ToString(), $"Start run complete job clean recipe {recipe}");
|
|
|
- CompleteJobProcess($"{Module}\\" + recipe);
|
|
|
- }
|
|
|
-
|
|
|
- _waitCompletejobClean = false;
|
|
|
}
|
|
|
-
|
|
|
- PreJobCleanTrig.CLK = enableJobClean && enablePreJobClean && IsIdle;
|
|
|
-
|
|
|
- if (PreJobCleanTrig.R)
|
|
|
- {
|
|
|
- PreJobCleanTimer.Restart();
|
|
|
- }
|
|
|
-
|
|
|
- if(PreJobCleanTrig.T)
|
|
|
+ else if(_idleCleanOpt == 2)
|
|
|
{
|
|
|
- ResetClean(false, false, true);
|
|
|
- }
|
|
|
-
|
|
|
- if (PreJobCleanTimer.IsRunning && _waitPreJobClean)
|
|
|
- {
|
|
|
- PreJobCleanTime = (int)PreJobCleanTimer.ElapsedMilliseconds / 1000;
|
|
|
- int PreJobCleanIdleTimeSP = SC.GetValue<int>($"{Module}.JobClean.IdleCleanTime");
|
|
|
- if(PreJobCleanTime >= PreJobCleanIdleTimeSP)
|
|
|
+ if(_idleCleanWaferCount >= _idleCleanWaferSetPoint)
|
|
|
{
|
|
|
- var recipe = SC.GetStringValue($"{Module}.JobClean.PreJobCleanRecipe");
|
|
|
-
|
|
|
- if (string.IsNullOrEmpty(recipe))
|
|
|
- {
|
|
|
- EV.PostWarningLog(Module.ToString(), "pre job clean can not run, recipe is empty");
|
|
|
- }
|
|
|
- else if (hasWafer)
|
|
|
- {
|
|
|
- EV.PostWarningLog(Module.ToString(), "pre job clean can not run, has wafer");
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- EV.PostInfoLog(Module.ToString(), $"Start run pre job clean recipe {recipe}");
|
|
|
- PreJobProcess($"{Module}\\" + recipe);
|
|
|
- }
|
|
|
+ Process(_idleCleanRecipe, true, false, null);
|
|
|
+ ResetIdleCleanCounter();
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- #endregion
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
}
|