Sic04/SicRT/Equipments/AutoTransfer.cs

3417 lines
126 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Media.Imaging;
using Aitex.Core.Common;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.RecipeCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.DBCore;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using SicRT.Equipments.Schedulers;
using SicRT.Modules.Schedulers;
using SicRT.Scheduler;
namespace SicRT.Modules
{
public partial class AutoTransfer : SchedulerModuleFactory
{
public class TrayInfo
{
public int TrayModule { get; set; }
public int TraySlot { get; set; }
public int TrayProcessCount { get; set; }
}
private List<ControlJobInfo> _lstNeedMapJob = new List<ControlJobInfo>();
private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
private List<TrayInfo> _lstProcessedTrayInfo = new List<TrayInfo>(); //保存石墨盘的进入腔体的信息(最多4次工艺需要换盘)
private int _maxTrayCount = 2; //可以同时运行的石墨盘总数
private bool _cassProcessOnebyOne = false; //Cassette是左右交互取片还是一个Cassette取完再取另一个
private R_TRIG NotifyTrayExhausted = new R_TRIG();
private const string LogSource = "Scheduler";
private SchedulerDBCallback _dbCallback;
//private const string StatsNameTotalRunningWafer = "TotalRunningWafer";
public bool CassetteFromAToB => SC.GetValue<bool>("System.Scheduler.CassetteFromAToB");
private bool _isCycleMode;
private int _cycleSetPoint = 0;
private int _cycledCount = 0;
private int _cycledWafer = 0;
private string _curRecipeName = "";
private string _curSequenceName = "";
private bool _isModuleErrorPrevious;
private bool[] _isPMErrorPrevious = new bool[2];
private string _timeBuffer1 { get; set; }
private string _timeBuffer2 { get; set; }
private string _timeBuffer3 { get; set; }
private Dictionary<string, DateTime> _bufferWaferInfo = new Dictionary<string, DateTime>();
private string _sAutoTransferConditionText;
public string AutoTransferConditionText
{
get
{
return _sAutoTransferConditionText;
}
set
{
_sAutoTransferConditionText = value;
}
}
private string _sWhichCondition;
public string WhichCondition
{
get
{
return _sWhichCondition;
}
set
{
_sWhichCondition = value;
}
}
//
public AutoTransfer()
{
_dbCallback = new SchedulerDBCallback();
DATA.Subscribe("Scheduler.IsCycleMode", () => _isCycleMode);
DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
DATA.Subscribe("Scheduler.RecipeName", () => _curRecipeName);
DATA.Subscribe("Scheduler.SequenceName", () => _curSequenceName);
DATA.Subscribe("Scheduler.TimeBuffer1", () => _timeBuffer1);
DATA.Subscribe("Scheduler.TimeBuffer2", () => _timeBuffer2);
DATA.Subscribe("Scheduler.TimeBuffer3", () => _timeBuffer3);
//显示所需条件信息用
DATA.Subscribe("Scheduler.AutoTransferConditionText", () => AutoTransferConditionText);
//要显示哪个任务的条件
DATA.Subscribe("Scheduler.WhichCondition", () => WhichCondition);
//DATA.Subscribe("CassAL.SlotSequenceList", () => currentSlotSequenceList["CassAL"]);
DATA.Subscribe("CassAL.LocalJobName", () =>
{
var jb = _lstControlJobs.FirstOrDefault(x => x.Module == "CassAL");
if (jb != null)
return jb.Name;
return "";
});
DATA.Subscribe("CassAL.LocalJobStatus", () =>
{
var jb = _lstControlJobs.FirstOrDefault(x => x.Module == "CassAL");
if (jb != null)
return jb.State.ToString();
return "";
});
//DATA.Subscribe("CassAR.SlotSequenceList", () => currentSlotSequenceList["CassAR"]);
DATA.Subscribe("CassAR.LocalJobName", () =>
{
var jb = _lstControlJobs.FirstOrDefault(x => x.Module == "CassAR");
if (jb != null)
return jb.Name;
return "";
});
DATA.Subscribe("CassAR.LocalJobStatus", () =>
{
var jb = _lstControlJobs.FirstOrDefault(x => x.Module == "CassAR");
if (jb != null)
return jb.State.ToString();
return "";
});
OP.Subscribe($"{ModuleName.TM}.ResetTask", (string cmd, object[] args) =>
{
_tmRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.EFEM}.ResetTask", (string cmd, object[] args) =>
{
_waferRobot.ResetTask();
_trayRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.WaferRobot}.ResetTask", (string cmd, object[] args) =>
{
_waferRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.TrayRobot}.ResetTask", (string cmd, object[] args) =>
{
_trayRobot.ResetTask();
return true;
});
}
public bool HasJobRunning
{
get { return _lstControlJobs.Count > 0; }
}
public void Clear()
{
_tmRobot.ResetTask();
foreach (var pm in _lstPms)
{
pm.ResetTask();
}
foreach (var cass in _lstCassettes)
{
cass.ResetTask();
}
_load.ResetTask();
_unload.ResetTask();
_buffer.ResetTask();
_cassetteBL.ResetTask();
_lstControlJobs.Clear();
_lstProcessJobs.Clear();
_bufferWaferInfo.Clear();
}
public void ResetTask()
{
if (!_load.IsOnline)
{
_load.ResetTask();
}
if (!_unload.IsOnline)
{
_unload.ResetTask();
}
if (!_buffer.IsOnline)
{
_buffer.ResetTask();
}
if (!_cassetteBL.IsOnline)
{
_cassetteBL.ResetTask();
}
foreach (var pm in _lstPms)
{
if (!pm.IsOnline)
{
pm.ResetTask();
}
}
foreach (var cass in _lstCassettes)
{
if (!cass.IsOnline)
{
cass.ResetTask();
}
}
}
public void GetConfig()
{
_cycledCount = 0;
_isCycleMode = SC.GetValue<bool>("System.IsCycleMode");
_cycleSetPoint = _isCycleMode ? SC.GetValue<int>("System.CycleCount") : 0;
_maxTrayCount = _lstPms.Count * 2;
}
#region Job Management
public bool CreateJob(Dictionary<string, object> param)
{
string reason = "";
string[] slotSequence = (string[])param["SlotSequence"];
string jobId = (string)param["JobId"];
string module = (string)param["Module"];
bool autoStart = (bool)param["AutoStart"];
string lotId = jobId;
if (param.ContainsKey("LotId"))
lotId = (string)param["LotId"];
if (CheckModuleHaveWaferWithNoJob(out reason))
{
EV.PostWarningLog(LogSource, $"{reason}");
return false;
}
if (!ValidateSequence(slotSequence, out reason))
{
EV.PostWarningLog(LogSource, $"{reason}");
return false;
}
if (slotSequence.Length != 25)
{
reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 25";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (string.IsNullOrEmpty(jobId))
{
jobId = "CJ_Local_" + module + DateTime.Now;
}
if (_lstControlJobs.Exists(x => x.Name == jobId))
{
reason = $"LotID : {jobId} already created";
EV.PostWarningLog(LogSource, reason);
return false;
}
ControlJobInfo cj = new ControlJobInfo();
cj.Name = jobId;
cj.Module = module;
cj.LotName = jobId;
cj.LotInnerId = Guid.NewGuid();
cj.LotWafers = new List<WaferInfo>();
cj.SetState(EnumControlJobState.WaitingForStart);
Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
Dictionary<string, List<Tuple<ModuleName, int>>> seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
Dictionary<string, string> indexSequence = new Dictionary<string, string>();
bool enableGroupBySequence = SC.GetValue<bool>("System.Scheduler.GroupWaferBySequence");
string WaferAssociationInfo = $"WaferAssociationInfo({module}):";
for (int i = 0; i < 25; i++)
{
WaferAssociationInfo = WaferAssociationInfo + string.Format(" slot{0} -- {1};", i + 1, slotSequence[i]);
if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
continue;
string groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString();
indexSequence[groupName] = slotSequence[i];
if (!seqSlot.ContainsKey(groupName))
{
seqSlot[groupName] = new bool[25];
}
if (!seqSlotWafers.ContainsKey(groupName))
{
seqSlotWafers[groupName] = new List<Tuple<ModuleName, int>>();
}
seqSlot[groupName][i] = true;
if (!WaferManager.Instance.CheckHasWafer(module, i))
{
reason = $"job wafer: {module} slot {i + 1} not in the carrier";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), i, WaferStatus.Normal))
{
reason = $"job wafer: {module} slot {i + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Status}";
EV.PostWarningLog(LogSource, reason);
return false;
}
var wafer = WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i);
if (wafer == null || wafer.IsEmpty)
{
reason = $"specifies wafer: {module} slot {i + 1} not in the carrier";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.ProcessState != EnumWaferProcessStatus.Idle)
{
reason = $"specifies wafer: {module} slot {i + 1} process state is not idle";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.ProcessJob != null)
{
reason = $"specifies wafer: {module} slot {i + 1} ProcessJob is not null";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.SubstE90Status != EnumE90Status.NeedProcessing)
{
reason = $"specifies wafer: {module} slot {i + 1} SubstE90Status is not NeedProcessing";
EV.PostWarningLog(LogSource, reason);
return false;
}
seqSlotWafers[groupName].Add(Tuple.Create(ModuleHelper.Converter(module), i));
cj.LotWafers.Add(WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i));
WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).PPID = slotSequence[i];
}
//currentSlotSequenceList[module] = slotSequence.Reverse().ToList();
EV.PostInfoLog(LogSource, WaferAssociationInfo);
if (seqSlotWafers.Count == 0)
{
reason = $"Can not create job, no wafer assigned";
EV.PostWarningLog(LogSource, reason);
return false;
}
List<ProcessJobInfo> pjs = new List<ProcessJobInfo>();
string[] seqs = seqSlot.Keys.ToArray();
for (int i = 0; i < seqs.Length; i++)
{
ProcessJobInfo pj = new ProcessJobInfo();
pj.Name = jobId + "_" + (i + 1);
pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]);
pj.ControlJobName = cj.Name;
//pj.LotName = lotId;
pj.SlotWafers = seqSlotWafers[seqs[i]];
pj.SetState(EnumProcessJobState.Queued);
//if (!CheckSequencePmReady(pj.Sequence, null, out _, out string innerReason))
//{
// reason = $"no valid chamber for the {innerReason}";
// EV.PostWarningLog(LogSource, reason);
// return false;
//}
//if (!CheckSequenceRecipeFileValid(pj.Sequence, out reason))
//{
// reason = $"recipe file not valid in the sequence, {reason}";
// EV.PostWarningLog(LogSource, reason);
// return false;
//}
//if (!CheckSequenceOrderOk(pj.Sequence, out reason))
//{
// reason = $"sequence path not valid, {reason}";
// EV.PostWarningLog(LogSource, reason);
// return false;
//}
pjs.Add(pj);
}
foreach (var pj in pjs)
{
cj.ProcessJobNameList.Add(pj.Name);
_lstProcessJobs.Add(pj);
}
_lstControlJobs.Add(cj);
int totalWafer = 0;
foreach (var pj in pjs)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
wafer.ProcessJob = pj;
WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), jobId);
WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, jobId);
totalWafer++;
}
}
CarrierManager.Instance.DeleteCarrier(cj.Module);
CarrierManager.Instance.CreateCarrier(cj.Module);
CarrierManager.Instance.UpdateCarrierId(cj.Module, $"{cj.Module} {DateTime.Now}");
CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
return true;
}
public bool CreateJobEx(Dictionary<string, object> param)
{
string reason = "";
string[] slotSequence = (string[])param["SlotSequence"];
string jobId = (string)param["JobId"];
string module = (string)param["Module"];
bool autoStart = (bool)param["AutoStart"];
if (slotSequence.Length != 25)
{
reason = $"slot sequence parameter not valid, slot count is {slotSequence.Length}, should be 25";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (!ValidateSequence(slotSequence, out reason))
{
EV.PostWarningLog(LogSource, $"{reason}");
return false;
}
if (string.IsNullOrEmpty(jobId))
{
jobId = "CJ_Local_" + module;
}
for (int i = 0; i < 25; i++)
{
if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
{
continue;
}
}
if (CheckModuleHaveWaferWithNoJob(out reason))
{
return false;
}
//bool cassAHasWafer = false;
//bool cassBHasWafer = false;
//for (int i = 0; i < 25; i++)
//{
// if (_cassetteAL.HasWafer(i))
// {
// cassAHasWafer = true;
// break;
// }
//}
//for (int i = 0; i < 25; i++)
//{
// if (_cassetteAR.HasWafer(i))
// {
// cassBHasWafer = true;
// break;
// }
//}
////从CassetteA出发运行流程后回到另一个Cassette,需要一个Cassette有片子一个Cassette没有片子
//if (_cassetteFromAToB)
//{
// if (cassAHasWafer && cassBHasWafer)
// {
// EV.PostWarningLog(LogSource, $"Cassette AL and Cassette AR both have wafer,Can not Run Sequence From CassetteAL to CassetteAR!");
// return;
// }
//}
//for (int i = 0; i < 25; i++)
//{
// if (_cassetteAL.HasWafer(i))
// {
// WaferInfo wafer = _cassetteAL.GetWaferInfo(i);
// if (wafer.ProcessState == EnumWaferProcessStatus.Idle)
// {
// wafer.NextSequenceStep = 0;
// }
// }
// if (_cassetteAR.HasWafer(i))
// {
// WaferInfo wafer = _cassetteAR.GetWaferInfo(i);
// if (wafer.ProcessState == EnumWaferProcessStatus.Idle)
// {
// wafer.NextSequenceStep = 0;
// }
// }
//}
Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
Dictionary<string, List<int>> seqSlotWafers = new Dictionary<string, List<int>>();
Dictionary<string, string> indexSequence = new Dictionary<string, string>();
bool enableGroupBySequence = false;
for (int i = 0; i < 25; i++)
{
if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
continue;
string groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString();
indexSequence[groupName] = slotSequence[i];
if (!seqSlot.ContainsKey(groupName))
{
seqSlot[groupName] = new bool[25];
}
if (!seqSlotWafers.ContainsKey(groupName))
{
seqSlotWafers[groupName] = new List<int>();
}
seqSlot[groupName][i] = true;
seqSlotWafers[groupName].Add(i);
}
if (seqSlotWafers.Count == 0)
{
reason = $"Can not create job, no wafer assigned";
EV.PostWarningLog(LogSource, reason);
return false;
}
List<ProcessJobInfo> pjs = new List<ProcessJobInfo>();
string[] seqs = seqSlot.Keys.ToArray();
List<string> pjIDs = new List<string>();
for (int i = 0; i < seqs.Length; i++)
{
var name = jobId + "_" + (i + 1);
if (!CreateProcessJob(name, indexSequence[seqs[i]], seqSlotWafers[seqs[i]], autoStart)) //ProcessJob创建失败直接返回不再创建ControlJob
{
return false;
}
pjIDs.Add(name);
}
if (!CreateControlJob(jobId, module, pjIDs, autoStart))
{
foreach (var pjName in pjIDs)
{
var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
if (pj != null)
_lstProcessJobs.Remove(pj);
}
}
return true;
}
private bool ValidateSequence(string[] seqs, out string reason)
{
reason = string.Empty;
bool isAllSequenceNull = true;
for (int i = 0; i < seqs.Length; i++)
{
if (string.IsNullOrEmpty(seqs[i]))
continue;
var sequence = SequenceInfoHelper.GetInfo(seqs[i]);
if ((sequence == null || sequence.Steps == null || sequence.Steps.Count == 0) && !string.IsNullOrEmpty(sequence.Name))
{
reason = $"Invalid sequence {seqs[i]}";
return false;
}
isAllSequenceNull = false;
if (sequence.Steps != null)
{
int currentIndex = 0;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Aligner)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Aligner";
return false;
}
else
{
if (sequence.Steps[currentIndex].AlignAngle < 0 || sequence.Steps[currentIndex].AlignAngle > 360)
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Aligner angle parameter is not valid";
return false;
}
}
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Load)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Load";
return false;
}
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Buffer)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Buffer";
return false;
}
else
{
if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("SlotSelection")
|| string.IsNullOrEmpty(sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString())
|| sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString().Contains("3"))
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer SlotSelection parameter is not valid";
return false;
}
if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("BufferType") || !sequence.Steps[currentIndex].StepParameter["BufferType"].ToString().Contains("Heat"))
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer BufferType parameter is not valid";
return false;
}
}
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules.Any(pm => !ModuleHelper.IsPm(pm)))
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be PM";
return false;
}
if (sequence.Steps.Count == 7)
{
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Buffer)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Buffer";
return false;
}
else
{
if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("SlotSelection")
|| sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString() != "3")
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer SlotSelection parameter is not valid";
return false;
}
if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("BufferType") || !sequence.Steps[currentIndex].StepParameter["BufferType"].ToString().Contains("Cooling"))
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer BufferType parameter is not valid";
return false;
}
}
}
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.UnLoad)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Unload";
return false;
}
currentIndex++;
if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Aligner)
{
reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Load";
return false;
}
else
{
if (sequence.Steps[0].AlignAngle < 0 || sequence.Steps[0].AlignAngle > 360)
{
reason = $"Invalid sequence {seqs[i]}, Aligner angle parameter is not valid";
return false;
}
}
}
}
if (isAllSequenceNull)
{
reason = $"Invalid sequence, sequence are all null ";
return false;
}
return true;
}
public bool CreateControlJob(string jobId, string module, List<string> pjIDs, bool isAutoStart)
{
if (_lstControlJobs.Exists(x => x.Name == jobId))
{
EV.PostWarningLog(LogSource, $"{jobId} is already created");
return false;
}
if (!ModuleHelper.IsCassette(ModuleHelper.Converter(module)))
{
EV.PostWarningLog(LogSource, $"{module} should be Cassete");
return false;
}
if (_lstProcessJobs.Count <= 0) //判断上一步ProcessJob是否创建成功
{
EV.PostWarningLog(LogSource, $"process job is not exist");
return false;
}
ControlJobInfo cj = new ControlJobInfo();
cj.Name = jobId;
cj.Module = module;
cj.LotName = jobId;
cj.LotInnerId = Guid.NewGuid();
cj.LotWafers = new List<WaferInfo>();
cj.SetState(EnumControlJobState.WaitingForStart);
int totalWafer = 0;
foreach (var pjName in pjIDs)
{
var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
if (pj == null)
{
LOG.Info($"not find {pjName} while create control job");
continue;
}
var slotWafers = new List<Tuple<ModuleName, int>>();
foreach (var slotWafer in pj.SlotWafers)
{
var _module = GetModule(module);
if (!_module.HasWafer(slotWafer.Item2))
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} not in the carrier");
return false;
}
if (!_module.CheckWaferStatus(slotWafer.Item2, WaferStatus.Normal))
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} status is {_module.GetWaferInfo(slotWafer.Item2).Status}");
return false;
}
if (_module.GetWaferInfo(slotWafer.Item2).ProcessState != EnumWaferProcessStatus.Idle)
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} process status is {_module.GetWaferInfo(slotWafer.Item2).ProcessState}");
return false;
}
slotWafers.Add(Tuple.Create(ModuleHelper.Converter(module), slotWafer.Item2));
totalWafer++;
}
pj.ControlJobName = cj.Name;
cj.ProcessJobNameList.Add(pj.Name);
pj.SlotWafers = slotWafers;
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
cj.LotWafers.Add(wafer);
wafer.ProcessJob = pj;
wafer.ProcessJobID = pj.Sequence.Name;
WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), jobId);
WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, jobId);
}
}
_lstControlJobs.Add(cj);
CarrierManager.Instance.DeleteCarrier(cj.Module);
CarrierManager.Instance.CreateCarrier(cj.Module);
CarrierManager.Instance.UpdateCarrierId(cj.Module, $"{cj.Module} {DateTime.Now}");
CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
return true;
}
public bool CreateProcessJob(string jobId, string sequenceName, List<int> slotNumbers/*0 based*/, bool isAutoStart)
{
var sequenceInfo = SequenceInfoHelper.GetInfo(sequenceName);
//模块顺序检查
List<int> lstLoad = new List<int>();
List<int> lstBuffer = new List<int>();
List<int> lstUnLoad = new List<int>();
List<int> lstPM = new List<int>();
for (int i = 0; i < sequenceInfo.Steps.Count; i++)
{
if (sequenceInfo.Steps[i].StepModules.Count == 0)
{
return false;
}
if (sequenceInfo.Steps[i].StepModules.Any(pm => ModuleHelper.IsPm(pm)))
{
lstPM.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(load => load == ModuleName.Load || load == ModuleName.LoadLock))
{
lstLoad.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(unload => unload == ModuleName.UnLoad))
{
lstUnLoad.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(buff => buff == ModuleName.Buffer))
{
lstBuffer.Add(i);
}
}
if (lstPM.Count <= 0)
{
EV.PostWarningLog(LogSource, $"Sequence must have pm step info!");
return false;
}
if (lstLoad.Count > 1)
{
EV.PostWarningLog(LogSource, $"Sequence can not contain {lstLoad.Count} Load Step!");
return false;
}
if (lstUnLoad.Count > 1)
{
EV.PostWarningLog(LogSource, $"Sequence can not contain {lstUnLoad.Count} UnLoad Step!");
return false;
}
if (lstBuffer.Count > 0)
{
foreach (int bufferId in lstBuffer)
{
if (lstLoad.Count == 1)
{
if (bufferId < lstLoad[0])
{
EV.PostWarningLog(LogSource, $"Sequence Load Step Must Before Buffer Step!");
return false;
}
}
if (lstUnLoad.Count == 1)
{
if (bufferId > lstUnLoad[0])
{
EV.PostWarningLog(LogSource, $"Sequence Buffer Step Must Before UnLoad Step!");
return false;
}
}
}
}
var slotWafers = new List<Tuple<ModuleName, int>>();
foreach (var slot in slotNumbers)
{
slotWafers.Add(Tuple.Create(ModuleName.System, slot));
}
ProcessJobInfo pj = new ProcessJobInfo();
pj.Name = jobId;
pj.Sequence = sequenceInfo;
pj.SlotWafers = slotWafers;
pj.SetState(EnumProcessJobState.Queued);
_lstProcessJobs.Add(pj);
return true;
}
internal void StopJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"stop job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
pj.SetState(EnumProcessJobState.Stopping);
}
}
if (_cycleSetPoint > 0)
{
_cycleSetPoint = _cycledCount;
}
}
}
internal void AbortJob(string jobName)
{
ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
if (cj == null)
{
EV.PostWarningLog(LogSource, $"abort job rejected, not found job with id {jobName}");
return;
}
int unprocessed_cj = 0;
int aborted_cj = 0;
List<ProcessJobInfo> pjAbortList = new List<ProcessJobInfo>();
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
pj.SetState(EnumProcessJobState.Aborting);
pjAbortList.Add(pj);
int unprocessed = 0;
int aborted = 0;
WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
foreach (var waferInfo in wafers)
{
waferInfo.ProcessJob = null;
waferInfo.NextSequenceStep = 0;
if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
{
unprocessed++;
unprocessed_cj++;
}
}
JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
}
}
foreach (var pj in pjAbortList)
{
_lstProcessJobs.Remove(pj);
}
_lstControlJobs.Remove(cj);
_dbCallback.LotFinished(cj);
JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
}
public void ResumeJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"resume job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Paused)
{
cj.SetState(EnumControlJobState.Executing);
}
}
}
internal void PauseJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"pause job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
cj.SetState(EnumControlJobState.Paused);
}
}
}
internal void StartJob(string jobName)
{
GetConfig();
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}");
// return;
//}
////StartPreprocess();
//if (_isCycleMode)
//{
// if (CheckAllJobDone())
// {
// _cycledWafer = 0;
// _cycledCount = 0;
// }
//}
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.WaitingForStart)
{
cj.BeginTime = DateTime.Now;
cj.LotInnerId = Guid.NewGuid();
_dbCallback.LotCreated(cj);
cj.SetState(EnumControlJobState.Executing);
}
}
}
#endregion
/// <summary>
/// Start Auto Transfer
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public Result Start(params object[] objs)
{
GetConfig();
_cycledWafer = 0;
_cycledCount = 0;
//_totalWaferWhenStart = StatsDataManager.Instance.GetValue(StatsNameTotalRunningWafer);
bool hasPmOnline = false;
foreach (var schedulerPm in _lstPms)
{
if (schedulerPm.IsOnline && !schedulerPm.IsError)
{
hasPmOnline = true;
break;
}
}
if (_pm1.IsError)
{
EV.PostWarningLog("Scheduler", "can not change to auto mode, at least one process chamber be online and no error");
return Result.FAIL;
}
if (_pm1.IsService)
{
EV.PostWarningLog("Scheduler", "can not change to auto mode, PM is Service Mode");
return Result.FAIL;
}
if (!hasPmOnline)
{
EV.PostWarningLog("Scheduler", "can not change to auto mode, at least one process chamber be online and no error");
return Result.FAIL;
}
if (!_tmRobot.IsOnline || _tmRobot.IsError)
{
EV.PostWarningLog("Scheduler", "can not change to auto mode, TM robot should be online and no error");
return Result.FAIL;
}
return Result.RUN;
}
public Result Monitor()
{
NotifyTrayExhausted.CLK = CheckTrayExhausted();
if (NotifyTrayExhausted.Q)
{
EV.PostAlarmLog("System", "Tray ProcessCount Exhausted , No Tray for next Process !");
}
ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
if (cjActive != null)
{
MonitorModuleTasks();
}
MonitorModuleError();
MonitorModuleState();
MonitorJobTasks();
MonitorCleanTasks();
return Result.RUN;
}
#region Job task
public Result MonitorJobTasks()
{
UpdateProcessJobStatus();
UpdateControlJobStatus();
StartNewJob();
return Result.RUN;
}
protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
{
for (int i = 0; i < pj.SlotWafers.Count; ++i)
{
WaferInfo wafer = GetModule(GetWaferReturnedCassette(pj.SlotWafers[i].Item1)).GetWaferInfo(pj.SlotWafers[i].Item2);
if (wafer.IsEmpty)
return false;
if (checkAllProcessed && GetModule(GetWaferReturnedCassette(pj.SlotWafers[i].Item1)).CheckWaferNeedProcess(pj.SlotWafers[i].Item2))
return false;
if (wafer.ProcessJob == null || wafer.ProcessJob.InnerId != pj.InnerId)
{
return false;
}
}
return true;
}
private ModuleName GetWaferReturnedCassette(ModuleName moduleFrom)
{
if (CassetteFromAToB)
{
if (moduleFrom == ModuleName.CassAL)
{
return ModuleName.CassAR;
}
else if (moduleFrom == ModuleName.CassAR)
{
return ModuleName.CassAL;
}
}
return moduleFrom;
}
protected bool CheckAllDummyWaferReturned()
{
foreach (var schedulerPm in _lstPms)
{
if (WaferManager.Instance.CheckWaferIsDummy(schedulerPm.Module, 0))
return false;
}
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 0))
return false;
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 1))
return false;
return true;
}
protected bool CheckAllPmCleaned(ProcessJobInfo pj)
{
foreach (var schedulerPm in _lstPms)
{
if (GetModule(schedulerPm.Module).CheckNeedRunClean(out _, out _))
{
foreach (var sequenceStepInfo in pj.Sequence.Steps)
{
if (sequenceStepInfo.StepModules.Contains(schedulerPm.Module))
return false;
}
}
}
return true;
}
private void UpdateProcessJobStatus()
{
foreach (var pj in _lstProcessJobs)
{
if (pj.State == EnumProcessJobState.Processing)
{
if (CheckAllWaferReturned(pj, true) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned())
{
//if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
if (_unload.IsAvailable && _buffer.IsAvailable && _tmRobot.IsAvailable && _load.IsAvailable
&& _waferRobot.IsAvailable && _unload.NoTray(0)
&& _waferRobot.IsAvailable && _tmRobot.NoTray(0)
&& _waferRobot.IsAvailable && _load.NoTray(0))
{
pj.SetState(EnumProcessJobState.ProcessingComplete);
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
}
}
}
else if (pj.State == EnumProcessJobState.Stopping)
{
if (CheckAllWaferReturned(pj, false) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned())
{
//if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
if (_unload.IsAvailable && _buffer.IsAvailable && _tmRobot.IsAvailable && _load.IsAvailable
&& _waferRobot.IsAvailable && _unload.NoTray(0)
&& _waferRobot.IsAvailable && _tmRobot.NoTray(0)
&& _waferRobot.IsAvailable && _load.NoTray(0))
{
pj.SetState(EnumProcessJobState.ProcessingComplete);
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
}
}
}
}
}
private void UpdateControlJobStatus()
{
if (_lstControlJobs.Count == 0)
return;
bool allControlJobComplete = true;
List<ControlJobInfo> cjRemoveList = new List<ControlJobInfo>();
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
bool allPjCompleted = true;
foreach (var pjName in cj.ProcessJobNameList)
{
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
if (pj == null)
{
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
continue;
}
if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
{
allPjCompleted = false;
break;
}
}
if (allPjCompleted)
{
cj.SetState(EnumControlJobState.Completed);
int unprocessed_cj = 0;
int aborted_cj = 0;
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
int unprocessed = 0;
int aborted = 0;
WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
foreach (var waferInfo in wafers)
{
waferInfo.ProcessJob = null;
waferInfo.NextSequenceStep = 0;
if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
{
unprocessed++;
unprocessed_cj++;
}
}
JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
}
}
JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
_dbCallback.LotFinished(cj);
}
}
if (cj.State == EnumControlJobState.Completed)
{
cjRemoveList.Add(cj);
}
allControlJobComplete = allControlJobComplete && cj.State == EnumControlJobState.Completed;
}
if (_isCycleMode && _cycledCount < _cycleSetPoint)
{
int countPerCycle = 0;
int countProcessed = 0;
foreach (var pj in _lstProcessJobs)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
countPerCycle++;
WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
if (!wafer.IsEmpty && !GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2))
countProcessed++;
}
}
_cycledWafer = _cycledCount * countPerCycle + countProcessed;
//StatsDataManager.Instance.SetValue(StatsNameTotalRunningWafer, _totalWaferWhenStart + _cycledWafer);
if (allControlJobComplete)
{
_cycledCount++;
if (_cycledCount < _cycleSetPoint)
{
foreach (var cj in _lstControlJobs)
{
cj.SetState(EnumControlJobState.Executing);
}
foreach (var pj in _lstProcessJobs)
{
pj.SetState(EnumProcessJobState.Queued);
pj.InnerId = Guid.NewGuid();
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
wafer.ProcessJob = null;
wafer.NextSequenceStep = 0;
wafer.ProcessState = EnumWaferProcessStatus.Idle;
}
}
}
}
}
foreach (var cj in cjRemoveList)
{
List<ProcessJobInfo> pjRemoveList = new List<ProcessJobInfo>();
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
pjRemoveList.Add(pj);
}
foreach (var pj in pjRemoveList)
{
_lstProcessJobs.Remove(pj);
}
_lstControlJobs.Remove(cj);
}
ControlJobInfo cjActived = null;
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
cjActived = cj;
break;
}
}
}
private void StartNewJob()
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pjName in cj.ProcessJobNameList)
{
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
if (pj == null)
{
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
continue;
}
if (pj.State == EnumProcessJobState.Queued)
{
ActiveProcessJob(pj);
}
}
}
}
}
public bool CheckAllJobDone()
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
return false;
}
if (_lstControlJobs.Count == 0)
{
return true;
}
return false;
}
private bool ActiveProcessJob(ProcessJobInfo pj)
{
//_lstPms.Clear();
//for (int i = 0; i < pj.Sequence.Steps.Count; i++)
//{
// SequenceStepInfo stepInfo = pj.Sequence.Steps[i];
// foreach (var module in stepInfo.StepModules)
// {
// if (ModuleHelper.IsPm(module) && _lstPms.Exists(x => x.Module == module))
// {
// _lstPms.Add(_lstPms.Find(x => x.Module == module));
// }
// }
//}
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
wafer.ProcessJob = pj;
wafer.NextSequenceStep = 0;
WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString());
}
ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName);
CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
JobDataRecorder.StartPJ(pj.InnerId.ToString(), null, cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
pj.SetState(EnumProcessJobState.Processing);
return true;
}
#endregion
#region Module task
public Result MonitorModuleTasks()
{
//Load和UnLoad不能同时抽气
//System.Diagnostics.Debug.Assert(!((_tmRobot.IsInPumping && _load.IsInPumping) || (_tmRobot.IsInPumping && _unload.IsInPumping) || (_unload.IsInPumping && _load.IsInPumping)),$"检测到 _load.IsInPumping :{_load.IsInPumping}, _unload.IsInPumping :{_unload.IsInPumping}, _tmRobot.IsInPumping :{_tmRobot.IsInPumping}");
if ((_tmRobot.IsInPumping && _load.IsInPumping)
|| (_tmRobot.IsInPumping && _unload.IsInPumping)
|| (_unload.IsInPumping && _load.IsInPumping))
EV.PostAlarmLog("Schedule", $"检测到 _load.IsInPumping :{_load.IsInPumping}, _unload.IsInPumping :{_unload.IsInPumping}, _tmRobot.IsInPumping :{_tmRobot.IsInPumping}");
MonitorPMTask();
MonitorBufferTask();
MonitorAlignerTask();
MonitorTmRobotTask();
MonitorWaferRobotTask();
MonitorTrayRobotTask();
MonitorLoadTask();
MonitorUnLoadTask();
return Result.RUN;
}
private void MonitorBufferTask()
{
if (!_buffer.IsAvailable)
{
return;
}
for (int i = 0; i < 3; i++)
{
bool canExcute = _buffer.HasWafer(i) && _buffer.CheckWaferNextStepIsThis(_buffer.Module, i);
if (canExcute)
{
WaferInfo bufferWafer = _buffer.GetWaferInfo(i);
int bufferSetValue = 0;
if (!GetWaferSequenceNextValue(ModuleName.Buffer, i, "BufferType", out string strBufferType))
{
continue;
}
if (!GetWaferSequenceNextValue(ModuleName.Buffer, i, "SetValue", out string strBufferSetValue))
{
continue;
}
if (!Int32.TryParse(strBufferSetValue, out bufferSetValue))
{
continue;
}
WaferInfo wafer = _buffer.GetWaferInfo(i);
//分别判断冷却和加热方式温度是否达到
if (strBufferType == "HeatByTemp")
{
if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
{
DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
//选择By温度5秒后再判断温度
if (pastTime > 5)
{
if (_buffer.GetTemperature() >= bufferSetValue)
wafer.NextSequenceStep++;
_bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
}
}
else
{
_bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
}
}
else if (strBufferType == "HeatByTime")
{
if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
{
DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
if (i == 0)
{
_timeBuffer1 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
else if (i == 1)
{
_timeBuffer2 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
if (i == 2)
{
_timeBuffer3 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
if (pastTime > bufferSetValue)
{
wafer.NextSequenceStep++;
_bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
}
}
else
{
_bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
}
}
else if (strBufferType == "CoolingByTime")
{
if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
{
DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
if (i == 0)
{
_timeBuffer1 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
else if (i == 1)
{
_timeBuffer2 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
if (i == 2)
{
_timeBuffer3 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
}
if (pastTime > bufferSetValue)
{
wafer.NextSequenceStep++;
_bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
}
}
else
{
_bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
}
}
return;
}
}
//Place和Pick条件都一样
if (!_buffer.IsReadyForPlace(ModuleName.TMRobot, 0))
{
_buffer.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
}
}
private void MonitorLoadTask()
{
if (!_load.IsAvailable)
{
return;
}
bool canExcute = _load.HasWafer(0) && _load.HasTrayAndNotExceedProcessCount(0);
if (canExcute)
{
if (!_load.CheckWaferTrayGrouped())
{
_load.GroupWaferTray();
return;
}
else if (_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.Purge(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
_load.GetWaferInfo(0).NextSequenceStep++;
return;
}
}
if (_load.HasWafer(0) && _load.HasTrayAndNotExceedProcessCount(0))
{
//有Wafer和石墨盘等待TM来取,此时Unload必须不在动作
if (!_load.IsReadyForPick(ModuleName.TMRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
return;
}
}
else if ((_tmRobot.NoWafer(0) && _tmRobot.HasTrayAndExceedProcessCount(0))
|| (_buffer.NoWafer(0) && _buffer.HasTrayAndExceedProcessCount(0))
|| (_buffer.NoWafer(1) && _buffer.HasTrayAndExceedProcessCount(1))
|| (_buffer.NoWafer(2) && _buffer.HasTrayAndExceedProcessCount(2)))
{
if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
else if (_load.NoWafer(0))
{
//Load只有石墨盘,要么是WaferRobot来放,要么是TrayRobot来取
if (!_load.IsReadyForPlace(ModuleName.WaferRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Place, 0);
return;
}
}
else if (_load.HasTrayAndExceedProcessCount(0))
{
if (!_load.IsReadyForPick(ModuleName.TrayRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TrayRobot, EnumTransferType.Pick, 0);
return;
}
}
else
{
//啥也没有,要么是等工艺做完TMRobot来放(TM手上有Tray,无Wafer),要么是还没做工艺等TrayRobot来放
if (_tmRobot.HasTray(0) && _tmRobot.NoWafer(0)
|| _unload.HasTray(0)
|| (_buffer.HasTray(0) && _buffer.NoWafer(0))
|| (_buffer.HasTray(1) && _buffer.NoWafer(1))
|| (_buffer.HasTray(2) && _buffer.NoWafer(2)))
{
if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
else
{
if (!_load.IsReadyForPlace(ModuleName.TrayRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TrayRobot, EnumTransferType.Place, 0);
return;
}
}
}
}
private void MonitorUnLoadTask()
{
if (!_unload.IsAvailable)
{
return;
}
//UnLoad
if (_unload.FirstDetectWaferArrive(0) || _unload.FirstDetectWaferLeave(0))
{
_unload.ResetPurgedAndSeparatedStatus();
}
bool canExcuteUnLoad = _unload.HasWafer(0); //&& _unload.GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Completed; //并且闸板阀关上
if (canExcuteUnLoad)
{
if (!_unload.CheckCoolingCompleted())
{
GetWaferSequenceCoolingTime(_unload.Module, 0, out int coolingTime);
_unload.Cooling(true, coolingTime);
return;
}
if (_unload.CheckCoolingCompleted() && !_unload.CheckWaferTraySeparated())
{
_unload.SeparateWaferTray();
return;
}
if (_unload.CheckWaferNextStepIsThis(ModuleName.UnLoad, 0) && _unload.NoTray(0) && _unload.CheckCoolingCompleted() && _unload.CheckWaferTraySeparated() && !_unload.CheckPurged() && !_load.IsInPumping && !_tmRobot.IsInPumping)
{
_unload.Purge(_unload.GetWaferPurgeCount(0), _unload.GetWaferPumpDelayTime(0));
_unload.GetWaferInfo(0).NextSequenceStep++;
return;
}
}
if (_unload.HasTray(0))
{
if (!_unload.CheckPurged() && _unload.CheckWaferTraySeparated() && !_unload.IsReadyForPick(ModuleName.TMRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
{
_unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
return;
}
}
else if (_unload.HasWafer(0))
{
if (_unload.CheckPurged() && _unload.CheckWaferTraySeparated() && !_unload.IsReadyForPick(ModuleName.WaferRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
{
_unload.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0);
return;
}
}
else
{
if (!_unload.IsReadyForPlace(ModuleName.TMRobot, 0) && !_load.IsInPumping && !_tmRobot.IsInPumping)
{
_unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
}
private void MonitorAlignerTask()
{
if (!_aligner.IsAvailable)
{
return;
}
if (_aligner.HasWafer(0) && _aligner.CheckWaferNextStepIsThis(ModuleName.Aligner, 0))
{
_aligner.Aligning();
_aligner.GetWaferInfo(0).NextSequenceStep++;
}
}
private void MonitorPMTask()
{
foreach (var pm in _lstPms)
{
if (!pm.IsAvailable)
continue;
if (_pm1.HasWafer(0))
{
if (_pm1.CheckNeedRunClean(out bool withWafer, out string recipe) && withWafer
&& GetModule(pm.Module).GetWaferInfo(0).Status == WaferStatus.Dummy
&& GetModule(pm.Module).GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Wait)
{
pm.Process(recipe, true, withWafer);
continue;
}
if (GetModule(pm.Module).CheckWaferNeedProcess(0, pm.Module))
{
WaferInfo wafer = GetModule(pm.Module).GetWaferInfo(0);
if (pm.Process(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].RecipeName, false, true))
{
GetModule(pm.Module).GetWaferInfo(0).NextSequenceStep++;
continue;
}
}
else
{
if (!pm.IsReadyForPick(ModuleName.TMRobot, 0))
{
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
}
}
}
else
{
if (GetModule(pm.Module).CheckNeedRunClean(out bool withWafer, out string recipe) && !withWafer)
{
pm.Process(recipe, true, withWafer);
continue;
}
if (!pm.IsReadyForPlace(ModuleName.TMRobot, 0))
{
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
}
}
}
}
private void MonitorTmRobotTask()
{
if (!_tmRobot.IsAvailable)
return;
foreach (var pm in _lstPms)
{
if (pm.IsWaitTransfer(ModuleName.TMRobot))
pm.StopWaitTransfer(ModuleName.TMRobot);
}
if (_buffer.IsWaitTransfer(ModuleName.TMRobot))
_buffer.StopWaitTransfer(ModuleName.TMRobot);
if (_load.IsWaitTransfer(ModuleName.TMRobot))
_load.StopWaitTransfer(ModuleName.TMRobot);
if (_unload.IsWaitTransfer(ModuleName.TMRobot))
_unload.StopWaitTransfer(ModuleName.TMRobot);
MonitorTmRobotPMTask();
MonitorTmRobotBufferTask();
MonitorTmRobotLoadTask();
MonitorTmRobotUnLoadTask();
}
private void MonitorWaferRobotTask()
{
foreach (var cass in _lstCassettes)
{
if (cass.IsWaitTransfer(ModuleName.WaferRobot))
cass.StopWaitTransfer(ModuleName.WaferRobot);
}
if (_aligner.IsWaitTransfer(ModuleName.WaferRobot))
_aligner.StopWaitTransfer(ModuleName.WaferRobot);
if (_load.IsWaitTransfer(ModuleName.WaferRobot))
_load.StopWaitTransfer(ModuleName.WaferRobot);
if (_unload.IsWaitTransfer(ModuleName.WaferRobot))
_unload.StopWaitTransfer(ModuleName.WaferRobot);
MonitorWaferRobotCassetteTask();
MonitorWaferRobotUnLoadTask();
MonitorWaferRobotAligerTask();
MonitorWaferRobotLoadTask();
}
private void MonitorTrayRobotTask()
{
if (_cassetteBL.IsWaitTransfer(ModuleName.TrayRobot))
_cassetteBL.StopWaitTransfer(ModuleName.TrayRobot);
if (_load.IsWaitTransfer(ModuleName.TrayRobot))
_load.StopWaitTransfer(ModuleName.TrayRobot);
MonitorTrayRobotLoadTask();
MonitorTrayRobotCassetteTask();
}
private void MonitorTmRobotLoadTask()
{
if (!_load.IsAvailable)
return;
if (!_tmRobot.IsAvailable)
return;
//place Robot有Tray无Wafer,Load无Tray
bool canPlace = _tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0) && _load.NoTray(0);
if (canPlace)
{
if (_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping)
{
if (_tmRobot.Place(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
if (!_load.IsAvailable)
return;
if (!_tmRobot.IsAvailable)
return;
//place Robot有Tray无Wafer,Load无Tray
canPlace = _tmRobot.HasTray(0) && _tmRobot.NoWafer(0) && _load.NoTray(0) && _load.HasWafer(0);
if (canPlace)
{
if (_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping)
{
if (_tmRobot.Place(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
if (!_load.IsAvailable)
return;
if (!_tmRobot.IsAvailable)
return;
//pick TM无Tray,需要Process,下一个位置没有Tray
bool canPick = _tmRobot.NoTray(0) && _load.CheckWaferNeedProcess(0) && !_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0) && _load.CheckWaferNextStepModuleNoTray(0);
if (canPick)
{
//需要完成组合和Purge
if (!_load.CheckWaferTrayGrouped())
{
return;
}
if (_load.IsReadyForPick(ModuleName.TMRobot, 0) && !_unload.IsInPumping)
{
if (_tmRobot.Pick(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
private void MonitorTmRobotUnLoadTask()
{
if (!_unload.IsAvailable)
return;
if (!_tmRobot.IsAvailable)
return;
//UnLoad取盘只关心LoadLock是否有空位
//place Robot有Wafer,UnLoad无Tray无Wafer
bool canPlaceUnLoad = _tmRobot.HasWafer(0)
&& _unload.NoTray(0)
&& _unload.NoWafer(0)
&& (_aligner.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0) || _unload.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0) || _tmRobot.CheckWaferSequenceStepDone(0))
;//&& _tmRobot.GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Completed;
if (canPlaceUnLoad)
{
if (_unload.IsReadyForPlace(ModuleName.TMRobot, 0) && !_load.IsInPumping)
{
if (_tmRobot.Place(_unload.Module, 0, Hand.Blade1))
{
_unload.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
if (!_unload.IsAvailable)
return;
if (!_tmRobot.IsAvailable)
return;
//pick UnLoad有Tray,TM无Tray,LoadLock没有Tray,UnLoad分离完成
bool canPickUnLoad = _tmRobot.NoTray(0)
&& _unload.HasTray(0)
&& _load.NoTray(0);
//&& _unload.GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Completed;
if (canPickUnLoad)
{
//需要UnLoad把石墨盘和Wafer分离完成
if (!_unload.CheckWaferTraySeparated())
{
return;
}
if (_unload.IsReadyForPick(ModuleName.TMRobot, 0) && !_load.IsInPumping)
{
if (_tmRobot.Pick(_unload.Module, 0, Hand.Blade1))
{
_unload.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
private void MonitorTmRobotBufferTask()
{
if (!_tmRobot.IsAvailable)
return;
if (!_buffer.IsAvailable)
return;
//place Buffer位置没有Tray,Robot有Wafer,下一步骤是Buffer
bool canPalce = _tmRobot.HasWafer(0) && _buffer.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0);
if (canPalce)
{
SlotItem bufferEmptySlot = GetEmptyBufferSlot(_tmRobot.GetWaferInfo(0));
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;
}
}
return;
}
if (!_tmRobot.IsAvailable)
return;
if (!_buffer.IsAvailable)
return;
//place 最后没有新的wafer需要工艺时完成工艺后的Tray放入Buffer中
canPalce = _tmRobot.HasTray(0) && _tmRobot.NoWafer(0);
if (canPalce)
{
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;
}
}
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 (!_tmRobot.IsAvailable)
return;
if (!_buffer.IsAvailable)
return;
//pick 当前步(UnLoad没有Wafer),Buffer有Tray,机械手没有Tray
bool canPick = _tmRobot.NoTray(0);
if (canPick)
{
for (int i = 0; i < 3; i++)
{
if (_buffer.HasTray(i) && !_buffer.CheckWaferNextStepIsThis(ModuleName.Buffer, i))
{
int bufferSetValue = 0;
if (!GetWaferSequenceCurrentValue(ModuleName.Buffer, i, "BufferType", out string strBufferType))
{
continue;
}
if (!GetWaferSequenceCurrentValue(ModuleName.Buffer, i, "SetValue", out string strBufferSetValue))
{
continue;
}
if (!Int32.TryParse(strBufferSetValue, out bufferSetValue))
{
continue;
}
//分别判断冷却和加热方式温度是否达到
if (strBufferType == "HeatByTemp" && _buffer.GetTemperature() < bufferSetValue)
{
continue;
}
else if (strBufferType == "CoolingByTemp" && _buffer.GetTemperature() > bufferSetValue)
{
continue;
}
//如果已经完成所有步骤或者下一步需要经过UnLoad,UnLoad不允许有盘
if (_buffer.CheckWaferSequenceStepDone(i) || _unload.CheckWaferNextStepIsThis(ModuleName.Buffer, i) || _aligner.CheckWaferNextStepIsThis(ModuleName.Buffer, i))
{
if (_unload.HasWafer(0) || _unload.HasTray(0))
{
continue;
}
}
//下一步如果去PM1判断PM1是否准备好
if (_pm1.CheckWaferNextStepIsThis(ModuleName.Buffer, i))
{
if (!_pm1.IsAvailable || _pm1.HasTray(0) || _pm1.HasWafer(0) || !_pm1.IsReadyForPlace(ModuleName.TMRobot, 0) ||
!_pm1.CheckBufferToPMTemp())
continue;
}
if (_buffer.CheckWaferNextStepModuleNoTray(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
}
if (!_tmRobot.IsAvailable)
return;
if (!_buffer.IsAvailable)
return;
//pick 工艺开始时,如果Buffer中有Tray时,优先取Buffer中的Tray而不是Cst中Tray
canPick = _tmRobot.NoTray(0)
&& _load.IsReadyForPlace(ModuleName.TMRobot, 0)
&& _load.NoTray(0)
//&& _load.HasWafer(0)
&& ((GetWaferInJobQueue() != null || _aligner.CheckWaferNeedProcess(0) || _waferRobot.CheckWaferNeedProcess(0)) || _load.CheckWaferNeedProcess(0));
if (canPick)
{
//优先取出超过ProcessCount的Tray
for (int i = 0; i < 3; i++)
{
if (_buffer.HasTray(i) && _buffer.NoWafer(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i) && _buffer.HasTrayAndExceedProcessCount(i))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
for (int i = 0; i < 3; i++)
{
if (_buffer.HasTray(i) && _buffer.NoWafer(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i) && _load.IsReadyForPlace(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
}
private void MonitorTmRobotPMTask()
{
if (!_tmRobot.IsAvailable)
return;
//place to pm
bool blade0HasWaferAndNeedProcess = _tmRobot.HasWafer(0) && _tmRobot.CheckWaferNeedProcess(0);
if (blade0HasWaferAndNeedProcess)
{
foreach (var pm in _lstPms)
{
if (!pm.IsAvailable
|| !GetModule(pm.Module).NoWafer(0)
|| !pm.IsReadyForPlace(ModuleName.TMRobot, 0)
|| !pm.CheckTempBelow900())
continue;
//bool cleanRequired = CheckNeedRunClean(pm.Module, out bool withWafer, out _);
//if (cleanRequired)
//{
// if (!withWafer)
// continue;
// bool blade0DummyPlace = _tmRobot.HasWafer(0)
// && CheckWaferNeedProcess(ModuleName.TMRobot, 0, pm.Module)
// && WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 0);
//bool blade1DummyPlace =_tmRobot.HasWafer(1)
// && CheckWaferNeedProcess(ModuleName.TMRobot, 1, pm.Module)
// && WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 1);
// if (blade0DummyPlace || blade1DummyPlace)
// {
// Hand placeBlade = blade0DummyPlace ? Hand.Blade1 : Hand.Blade2;
// if (blade0DummyPlace && blade1DummyPlace)
// {
// if ( _tmRobot.GetWaferInfo(1).OriginSlot <
// _tmRobot.GetWaferInfo(0).OriginSlot)
// {
// placeBlade = Hand.Blade2;
// }
// }
// if (_tmRobot.Place(pm.Module, 0, placeBlade))
// {
// pm.WaitTransfer(ModuleName.TMRobot);
// return;
// }
// }
// continue;
//}
bool blade0Place = _tmRobot.HasWafer(0) && _tmRobot.CheckWaferNeedProcess(0, pm.Module);
if (blade0Place)
{
Hand placeBlade = Hand.Blade1;
if (_tmRobot.Place(pm.Module, 0, placeBlade))
{
pm.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
if (!_tmRobot.IsAvailable)
return;
//pick from pm
if (_tmRobot.NoWafer(0) && _tmRobot.NoTray(0))
{
Hand pickBlade = Hand.Blade1;
ModuleName pickPm = ModuleName.System;
foreach (var schedulerPm in _lstPms)
{
//增加温度低于900才能Pick的限制
if (!schedulerPm.IsAvailable
|| GetModule(schedulerPm.Module).NoWafer(0)
|| GetModule(schedulerPm.Module).CheckWaferNeedProcess(0, schedulerPm.Module)
|| _tmRobot.HasWafer((int)pickBlade)
|| !schedulerPm.CheckTempBelow900())
continue;
//如果下一步是Buffer
if (_buffer.CheckWaferNextStepIsThis(schedulerPm.Module, 0))
{
SlotItem bufferEmptySlot = GetEmptyBufferSlot(GetModule(schedulerPm.Module).GetWaferInfo(0));
if (bufferEmptySlot == null)
{
return;
}
}
else if (_unload.HasWafer(0) || _unload.HasTray(0))
{
return;
}
pickPm = schedulerPm.Module;
break;
}
if (pickPm != ModuleName.System)
{
SchedulerModule pm = GetModule(pickPm.ToString());
if (pm.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(pm.Module, 0, pickBlade))
{
pm.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
private void MonitorWaferRobotLoadTask()
{
if (!_waferRobot.IsAvailable)
return;
if (!_load.IsAvailable)
return;
//place Load没有Wafer有Tray,Robot有Wafer,步骤没有完成,下一步不是Aligner (其它:SlitValve都关了,大气)
bool canPlace = _waferRobot.HasWafer(0)
&& _load.NoWafer(0)
&& _load.NoTray(0)
&& _waferRobot.GetWaferInfo(0).Status != WaferStatus.Dummy
&& !_aligner.CheckWaferNextStepIsThis(ModuleName.WaferRobot, 0)
&& _waferRobot.CheckWaferNeedProcess(0);
if (canPlace)
{
if (_load.IsReadyForPlace(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Place(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
private void MonitorWaferRobotUnLoadTask()
{
if (!_waferRobot.IsAvailable)
return;
if (!_unload.IsAvailable)
return;
//pick UnLoad有Wafer没有Tray,Robot没有Wafer,步骤都完成了或者下一步的模块没有片子 (其它:UnLoad 夹爪夹住,顶针下降,SlitValve都关了,大气)
bool canPick = _waferRobot.NoWafer(0)
&& _unload.HasWafer(0)
&& _unload.NoTray(0)
&& (_unload.CheckWaferNextStepModuleNoWafer(0) || _unload.CheckWaferSequenceStepDone(0))
&& _unload.GetWaferInfo(0).Status != WaferStatus.Dummy;
if (canPick)
{
//下一步是Aligner并且Aligner上不允许有片子
if (_aligner.CheckWaferNextStepIsThis(ModuleName.UnLoad, 0))
{
if (_aligner.HasWafer(0))
{
return;
}
}
if (_unload.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_unload.Module, 0, Hand.Blade1))
{
_unload.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
private void MonitorWaferRobotAligerTask()
{
if (!_waferRobot.IsAvailable || !_aligner.IsAvailable)
{
return;
}
//place 任务还没完成,下一步是Aligner,Robot有片子,Aligner没片子
bool canPlaceAligner = _aligner.NoWafer(0)
&& _waferRobot.HasWafer(0)
&& (_aligner.CheckWaferNextStepIsThis(ModuleName.WaferRobot, 0) || _waferRobot.CheckWaferSequenceStepDone(0))
&& _waferRobot.GetWaferInfo(0).Status != WaferStatus.Dummy;
if (canPlaceAligner)
{
if (_aligner.IsReadyForPlace(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Place(_aligner.Module, 0, Hand.Blade1))
{
_aligner.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
if (!_waferRobot.IsAvailable || !_aligner.IsAvailable)
{
return;
}
//pick Robot没片子,Aligner有片子
bool canPickAligner = _aligner.HasWafer(0)
&& _waferRobot.NoWafer(0)
&& _aligner.GetWaferInfo(0).Status != WaferStatus.Dummy
&& !_aligner.CheckWaferNextStepIsThis(ModuleName.Aligner, 0)
&& _load.CheckWaferNextStepIsThis(ModuleName.Aligner, 0)
&& _load.IsReadyForPlace(ModuleName.WaferRobot, 0);
//pick Aligner wafer to load
if (canPickAligner)
{
//需要运行工艺,Load不能有片子Load不能有Tray
if (_aligner.CheckWaferNeedProcess(0))
{
if (_load.HasWafer(0)
|| _load.HasTray(0)
|| _tmRobot.HasTrayAndExceedProcessCount(0)
|| _buffer.HasTrayAndExceedProcessCount(0)
|| _buffer.HasTrayAndExceedProcessCount(1)
|| _buffer.HasTrayAndExceedProcessCount(2))
{
return;
}
}
if (_aligner.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_aligner.Module, 0, Hand.Blade1))
{
_aligner.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
//pick Aligner wafer to cst
bool canPick = _aligner.HasWafer(0)
&& _waferRobot.NoWafer(0)
&& _aligner.GetWaferInfo(0).Status != WaferStatus.Dummy
&& !_aligner.CheckWaferNextStepIsThis(ModuleName.Aligner, 0)
&& _aligner.CheckWaferSequenceStepDone(0);
//WaferRobot从Aligner Pick Wafer不应检查Load腔条件
if (canPick)
{
if (_aligner.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_aligner.Module, 0, Hand.Blade1))
{
_aligner.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
private void MonitorWaferRobotCassetteMapTask()
{
//if (!_waferRobot.IsAvailable)
// return;
//if (_waferRobot.HasWafer(0))
//{
// return;
//}
//else
//{
// ControlJobInfo cjActive = _lstNeedMapJob.Find(x => x.State == EnumControlJobState.WaitingForStart);
// if (cjActive != null)
// {
// if (_waferRobot.Map(ModuleHelper.Converter(cjActive.Module)))
// {
// }
// }
//}
}
private void MonitorWaferRobotCassetteTask()
{
if (!_waferRobot.IsAvailable)
return;
//place 任务完成了,Robot有片子,Cassette没有片子
bool canPlaceCassette = _waferRobot.HasWafer(0)
&& _waferRobot.GetWaferInfo(0).Status != WaferStatus.Dummy
&& _waferRobot.CheckWaferSequenceStepDone(0);
if (canPlaceCassette)
{
WaferInfo wafer = _waferRobot.GetWaferInfo(0);
if (GetWaferReturnedCassette((ModuleName)wafer.OriginStation) == ModuleName.CassAL)
{
if (_cassetteAL.IsAvailable && _cassetteAL.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot))
{
if (_waferRobot.Place(_cassetteAL.Module, wafer.OriginSlot, Hand.Blade1))
{
_cassetteAL.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
else if (GetWaferReturnedCassette((ModuleName)wafer.OriginStation) == ModuleName.CassAR)
{
if (_cassetteAR.IsAvailable && _cassetteAR.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot))
{
if (_waferRobot.Place(_cassetteAR.Module, wafer.OriginSlot, Hand.Blade1))
{
_cassetteAR.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
if (!_waferRobot.IsAvailable)
return;
//pick Robot没有片子,下一步的模块没有片子
bool canPick = _waferRobot.NoWafer(0);
SlotItem position = GetWaferInJobQueue();
if (canPick && position != null)
{
//下一步是Aligner并且Aligner上不允许有片子
if (_aligner.CheckWaferNextStepIsThis(position.Module, position.Slot))
{
if (_aligner.HasWafer(0))
{
return;
}
////如果UnLoad有Wafer,而且下一步是Aligner,则不能取
//if (CheckWaferNextStepIsAligner(ModuleName.UnLoad, 0))
//{
// return;
//}
}
else if (_load.HasWafer(0)
|| _load.NoTray(0)
|| _load.HasTrayAndExceedProcessCount(0)
|| !_load.IsReadyForPlace(ModuleName.WaferRobot, 0)
|| _tmRobot.HasTrayAndExceedProcessCount(0)
|| _buffer.HasTrayAndExceedProcessCount(0)
|| _buffer.HasTrayAndExceedProcessCount(1)
|| _buffer.HasTrayAndExceedProcessCount(2))
{
return;
}
if (GetRunWaferCount() >= _maxTrayCount)//超过可以运行的石墨盘最大数
{
return;
}
if (position.Module == ModuleName.CassAR)
{
if (_cassetteAR.IsAvailable && _cassetteAR.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(position.Module, position.Slot, Hand.Blade1))
{
_cassetteAR.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
else if (position.Module == ModuleName.CassAL)
{
if (_cassetteAL.IsAvailable && _cassetteAL.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(position.Module, position.Slot, Hand.Blade1))
{
_cassetteAL.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
}
private void MonitorTrayRobotLoadTask()
{
//----------------------------------
string s = "";
if (WhichCondition == "TrayRobotLoad")
{
s += AddC("_trayRobot.IsAvailable", _trayRobot.IsAvailable.ToString(), "True");
s += AddC("_load.IsAvailable", _load.IsAvailable.ToString(), "True");
s += "canPlace:\r\n";
s += AddC("_load.NoTray(0)", _load.NoTray(0).ToString(), "True");
s += AddC("_trayRobot.HasTray(0)", _trayRobot.HasTray(0).ToString(), "True");
}
AutoTransferConditionText = s;
//----------------------------------
//
if (!_trayRobot.IsAvailable)
return;
if (!_load.IsAvailable)
return;
//place UnLoad没有Tray,Load没有Tray,Robot有Tray,Cassette或Aligner有任务未完成
bool canPlace = _load.NoTray(0)
&& _trayRobot.HasTrayAndNotExceedProcessCount(0)
&& _unload.NoTray(0)
&& _load.HasWafer(0)
&& (GetWaferInJobQueue() != null || (_aligner.HasWafer(0) && _aligner.CheckWaferNeedProcess(0)) || (_waferRobot.HasWafer(0) && _waferRobot.CheckWaferNeedProcess(0)) || (_load.HasWafer(0) && _load.CheckWaferNeedProcess(0)));
if (canPlace)
{
//TMRobot有Tray无Wafer也不能放
if (_tmRobot.NoWafer(0) && _tmRobot.HasTray(0))
{
return;
}
if (_load.IsReadyForPlace(ModuleName.TrayRobot, 0))
{
if (_trayRobot.Place(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TrayRobot);
return;
}
}
}
if (!_trayRobot.IsAvailable)
return;
if (!_load.IsAvailable)
return;
//pick Load有Tray,判断CassatteA和Aligner还有片子没有跑PM工艺就不需要Pick
bool canPick = _load.HasTrayAndExceedProcessCount(0);
if (canPick)
{
//if (_load.HasTray(0) )// && _load.GetWaferInfo(0).TrayProcessCount < _trayMaxProcessCount)
//{
//if (GetWaferInJobQueue() != null)
//{
// return;
//}
//}
SlotItem emptyTraySlot = GetTrayOrignSlot(ModuleName.LoadLock, 0);// GetEmptyTraySlot(13); //先取Wafer再取石墨盘
if (emptyTraySlot != null && _load.HasTrayAndExceedProcessCount(0))
{
if (_load.IsReadyForPick(ModuleName.TrayRobot, 0))
{
if (_trayRobot.Pick(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TrayRobot);
return;
}
}
}
}
}
private void MonitorTrayRobotCassetteTask()
{
if (!_trayRobot.IsAvailable)
return;
if (!_cassetteBL.IsAvailable)
return;
//place Robot有盘 其它逻辑跟Load的Pick一致
bool canPlace = _trayRobot.HasTrayAndExceedProcessCount(0)
|| _load.HasTray(0)
|| (GetWaferInJobQueue() == null && _aligner.NoWafer(0) && _waferRobot.NoWafer(0) && _load.NoWafer(0));
if (canPlace)
{
SlotItem slotItem = GetTrayOrignSlot(ModuleName.TrayRobot, 0); //GetEmptyTraySlot(13);
if (slotItem != null)
{
if (_cassetteBL.IsReadyForPlace(ModuleName.TrayRobot, slotItem.Slot))
{
if (_trayRobot.Place(slotItem.Module, slotItem.Slot, Hand.Blade1))
{
_cassetteBL.WaitTransfer(ModuleName.TrayRobot);
return;
}
}
}
}
//pick Casstte有Tray,UnLoad没有Tray,Load没有Tray(各个腔体运行的石墨盘总数小于设定值)
if (GetCurrentTrayCount() >= _maxTrayCount)
{
return;
}
if (!_trayRobot.IsAvailable)
return;
if (!_cassetteBL.IsAvailable)
return;
if (CheckHasTrayAndNoWafer(new List<Tuple<ModuleName, int>>()
{
new Tuple<ModuleName, int>(ModuleName.Buffer,0),
new Tuple<ModuleName, int>(ModuleName.Buffer,1),
new Tuple<ModuleName, int>(ModuleName.Buffer,2),
new Tuple<ModuleName, int>(ModuleName.TMRobot,0),
new Tuple<ModuleName, int>(ModuleName.LoadLock,0),
})) return;
bool canPick = (_aligner.HasWafer(0) && _aligner.CheckWaferNeedProcess(0))
|| (_waferRobot.HasWafer(0) && _waferRobot.CheckWaferNeedProcess(0))
|| (_load.HasWafer(0) && _load.CheckWaferNeedProcess(0))
|| GetWaferInJobQueue() != null;
if (canPick)
{
SlotItem slotItem = GetTraySlot(8);
if (slotItem != null && _load.NoTray(0) && _trayRobot.NoTray(0))
{
if (_cassetteBL.IsReadyForPick(ModuleName.TrayRobot, slotItem.Slot))
{
if (_trayRobot.Pick(slotItem.Module, slotItem.Slot, Hand.Blade1))
{
_cassetteBL.WaitTransfer(ModuleName.TrayRobot);
return;
}
}
}
}
}
#endregion
#region Logic Check
/// <summary>
/// 获得Buffer的方式和数值
/// </summary>
/// <param name="module"></param>
/// <param name="slot"></param>
/// <param name="coolingType"></param>
/// <param name="setValue"></param>
/// <returns></returns>
private bool GetWaferSequenceNextValue(ModuleName module, int slot, string nodeName, out string nodeValue)
{
nodeValue = "";
if (!GetModule(module).HasWafer(slot))
return false;
WaferInfo wafer = GetModule(module).GetWaferInfo(slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
return false;
nodeValue = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[nodeName].ToString();
if (String.IsNullOrEmpty(nodeValue))
{
return false;
}
return true;
}
private bool GetWaferSequenceCurrentValue(ModuleName module, int slot, string nodeName, out string nodeValue)
{
nodeValue = "";
if (!GetModule(module).HasWafer(slot))
return false;
WaferInfo wafer = GetModule(module).GetWaferInfo(slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepModules.Contains(module))
return false;
nodeValue = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepParameter[nodeName].ToString();
if (String.IsNullOrEmpty(nodeValue))
{
return false;
}
return true;
}
private bool GetWaferSequenceCoolingTime(ModuleName module, int slot, out int coolingTime)
{
coolingTime = 0;
if (!WaferManager.Instance.CheckHasWafer(module, slot))
return false;
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
return false;
if (!int.TryParse(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"].ToString(),
out coolingTime))
{
coolingTime = 0;
//coolingTime = SC.GetValue<int>("Unload.DefaultCoolingTime");
//EV.PostWarningLog("Scheduler", $"Sequence step Unload cooling time is not valid, instead with the SC default value {coolingTime} seconds");
return false;
}
return true;
}
private bool CheckHasTrayAndNoWafer(List<Tuple<ModuleName, int>> needCheckPositions)
{
foreach (var positionTuple in needCheckPositions)
{
var module = GetModule(positionTuple.Item1);
if (module.HasTray(positionTuple.Item2) && module.NoWafer(positionTuple.Item2))
{
return true;
}
}
return false;
}
private bool CheckTrayExhausted()
{
return !(_buffer.HasTrayAndNotExceedProcessCount(0)
| _buffer.HasTrayAndNotExceedProcessCount(1)
| _buffer.HasTrayAndNotExceedProcessCount(2)
| _cassetteBL.HasTrayAndNotExceedProcessCount(0)
| _cassetteBL.HasTrayAndNotExceedProcessCount(1)
| _cassetteBL.HasTrayAndNotExceedProcessCount(2)
| _cassetteBL.HasTrayAndNotExceedProcessCount(3)
| _cassetteBL.HasTrayAndNotExceedProcessCount(4)
| _cassetteBL.HasTrayAndNotExceedProcessCount(5)
| _cassetteBL.HasTrayAndNotExceedProcessCount(6)
| _cassetteBL.HasTrayAndNotExceedProcessCount(7)
| _load.HasTrayAndNotExceedProcessCount(0)
| _unload.HasTrayAndNotExceedProcessCount(0)
| _tmRobot.HasTrayAndNotExceedProcessCount(0)
| _trayRobot.HasTrayAndNotExceedProcessCount(0)
| _pm1.HasTrayAndNotExceedProcessCount(0));
}
public bool CheckBufferWaferHasJob()
{
WaferInfo wafer = _buffer.GetWaferInfo(0);
if (wafer.IsEmpty)
{
return false;
}
if (wafer.ProcessJob == null)
{
return false;
}
ProcessJobInfo pj = _lstProcessJobs.Find(x => x.InnerId == wafer.ProcessJob.InnerId);
if (pj == null)
{
return false;
}
return true;
}
public bool CheckWaferProcessModuleIsAvailable(ModuleName waferModule, int waferSlot)
{
WaferInfo wafer = GetModule(waferModule).GetWaferInfo(waferSlot);
if (wafer.IsEmpty)
return false;
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
//foreach (var module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
//{
//if (GetModule(module).NoWafer(0)
// && _lstPms.Find(x => x.Module == module).IsAvailable
// && !CheckNeedRunClean(module, out bool _, out string _))
// return true;
//}
foreach (var step in wafer.ProcessJob.Sequence.Steps)
{
foreach (var module in step.StepModules)
{
if (module.ToString().StartsWith("PM")
&& GetModule(module).NoWafer(0)
&& _lstPms.Find(x => x.Module == module).IsAvailable
&& !GetModule(module).CheckNeedRunClean(out bool _, out string _))
return true;
}
}
return false;
}
private SlotItem GetWaferInJobQueue()
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
if (pjSlotWafer.Item1 == ModuleName.CassAL || pjSlotWafer.Item1 == ModuleName.CassAR)
{
if (GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2))
return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
}
}
}
}
}
}
return null;
}
private SlotItem GetTraySlot(int slotCount)
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
for (int i = 0; i < slotCount; i++)
{
if (_cassetteBL.HasTrayAndNotExceedProcessCount(i))
{
return new SlotItem(ModuleName.CassBL, i);
}
}
}
}
return null;
}
private SlotItem GetTrayOrignSlot(ModuleName module, int slot)
{
WaferInfo wafer = GetModule(module).GetWaferInfo(slot);
if (wafer != null && GetModule(module).HasTray(slot) && _cassetteBL.NoTray(wafer.TrayOriginSlot))
{
return new SlotItem(ModuleName.CassBL, wafer.TrayOriginSlot);
}
return null;
}
//private SlotItem GetEmptyTraySlot(int slotCount)
//{
// foreach (var cj in _lstControlJobs)
// {
// if (cj.State == EnumControlJobState.Executing)
// {
// for (int i = 0; i < slotCount; i++)
// {
//if (_cassetteBL.NoTray(i))
// {
// return new SlotItem(ModuleName.CassBL, i);
// }
// }
// }
// }
// return null;
//}
/// <summary>
/// 获取空位置
/// </summary>
/// <param name="isHeat"></param>
/// <returns></returns>
private SlotItem GetEmptyBufferSlot(WaferInfo wafer)
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
string strSots = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["SlotSelection"].ToString();
if (strSots == null)
{
return null;
}
string[] slots = strSots.Split(',');
for (int i = 0; i < slots.Length; i++)
{
int slot = 0;
if (Int32.TryParse(slots[i], out slot))
{
if (_buffer.NoTray(slot - 1))
{
return new SlotItem(ModuleName.Buffer, slot - 1);
}
}
}
}
}
return null;
}
/// <summary>
/// 获取各个模块的Wafer总数量
/// </summary>
/// <returns></returns>
private int GetRunWaferCount()
{
int waferCount = 0;
if (_load.HasWafer(0))
{
waferCount++;
}
if (_unload.HasWafer(0))
{
waferCount++;
}
if (_tmRobot.HasWafer(0))
{
waferCount++;
}
foreach (SchedulerPM pm in _lstPms)
{
if (GetModule(pm.Module).HasWafer(0))
{
waferCount++;
}
}
for (int i = 0; i < 3; i++)
{
if (_buffer.HasWafer(i))
{
waferCount++;
}
}
return waferCount;
}
/// <summary>
/// 获取各个模块的石墨盘总数量
/// </summary>
/// <returns></returns>
private int GetCurrentTrayCount()
{
int trayCount = 0;
if (_load.HasTray(0))
{
trayCount++;
}
if (_unload.HasTray(0))
{
trayCount++;
}
if (_tmRobot.HasTray(0))
{
trayCount++;
}
foreach (SchedulerPM pm in _lstPms)
{
if (GetModule(pm.Module).HasTray(0))
{
trayCount++;
}
}
for (int i = 0; i < 3; i++)
{
if (_buffer.HasTray(i))
{
trayCount++;
}
}
return trayCount;
}
/// <summary>
/// 获取ProcessJob可以同时运行工艺的Wafer总数
/// </summary>
/// <returns></returns>
private int GetCurrentWaferCount()
{
int waferCountDiv = 0;
int cassWaferCount = 0;
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
{
cassWaferCount += pj.SlotWafers.Count;
foreach (var pjSlotWafer in pj.SlotWafers)
{
var module = GetModule(pjSlotWafer.Item1);
if (module.HasWafer(pjSlotWafer.Item2) && !module.CheckWaferNeedProcess(pjSlotWafer.Item2))
{
waferCountDiv++;
}
}
}
}
}
}
return cassWaferCount - waferCountDiv;
//int waferCount = 0;
//if (_load.HasWafer(0))
//{
// waferCount++;
//}
//for (int i = 0; i < 3; i++)
//{
//if (_buffer.HasWafer(i))
// {
// waferCount++;
// }
//}
//if (_waferRobot.CheckWaferNeedProcess(0) )
//{
// waferCount++;
//}
//if (_aligner.CheckWaferNeedProcess(0) )
//{
// waferCount++;
//}
//for (int i=0;i<25;i++)
//{
// if (CheckWaferNeedProcess(ModuleName.CassAL, i))
// {
// waferCount++;
// }
// if (CheckWaferNeedProcess(ModuleName.CassAR, i))
// {
// waferCount++;
// }
//}
//return waferCount;
}
#endregion
#region Module error
public Result MonitorModuleError()
{
bool isModuleError = false;
bool[] isPMError = new bool[2];
for (int i = 0; i < isPMError.Length; i++)
{
isPMError[i] = false;
}
if (_tmRobot.IsError)
isModuleError = true;
for (int i = 0; i < _lstPms.Count; i++) // PM出错不影响其他腔体的传片
{
if (_lstPms[i].IsError)
isPMError[i] = true;
}
if (isModuleError && !_isModuleErrorPrevious)
{
//var jb1 = _lstControlJobs.Find(x => x.Module == "LP1");
//if (jb1 != null)
// PauseJob(jb1.Name);
//var jb2 = _lstControlJobs.Find(x => x.Module == "LP2");
//if (jb2 != null)
// PauseJob(jb2.Name);
}
else if (!isModuleError && _isModuleErrorPrevious)
{
Reset();
//CloseDoor();
}
for (int i = 0; i < _lstPms.Count; i++)
{
if (!isPMError[i] && _isPMErrorPrevious[i])
{
_lstPms[i].ResetTask();
}
_isPMErrorPrevious[i] = isPMError[i];
}
_isModuleErrorPrevious = isModuleError;
return Result.RUN;
}
public Result MonitorModuleState()
{
bool controlJobExecuting = false;
bool isModuleBusy = false;
foreach (var controlJob in _lstControlJobs)
{
if (controlJob.State == EnumControlJobState.Executing)
controlJobExecuting = true;
}
//if (!controlJobExecuting)
// return Result.RUN;
//if (_tmRobot.IsOnline && _tmRobot.Entity.IsBusy)
// isModuleBusy = true;
//if (_efemRobot.IsOnline && _efemRobot.Entity.IsBusy)
// isModuleBusy = true;
//foreach (var pm in _lstPms) // PM出错不影响其他腔体的传片
//{
// if (pm.IsOnline && pm.Entity.IsBusy)
// isModuleBusy = true;
//}
//foreach (var ll in _lstLls)
//{
// if (ll.IsOnline && ll.Entity.IsBusy)
// isModuleBusy = true;
//}
//foreach (var lp in _lstLps)
//{
// if (lp.IsOnline && lp.Entity.IsBusy)
// isModuleBusy = true;
//}
//if (_aligner.IsOnline && _aligner.Entity.IsBusy)
// isModuleBusy = true;
//if (isModuleBusy)
//{
// _timer.Stop();
// _started = false;
//}
//else
//{
// if (!_started)
// {
// _timer.Start(_deadLockTimeout * 1000);
// _started = true;
// }
//}
//_trigDeadLock.CLK = _timer.IsTimeout();
//if (_trigDeadLock.Q)
//{
// EV.PostWarningLog("System", "A deadlock has occurred");
//}
return Result.RUN;
}
public Result MonitorCleanTasks()
{
//if (!_isInited)
//{
// _isInited = true;
// InitClean();
//}
//foreach (var pm in _lstPms)
//{
// pm.MonitorCleanTasks();
//}
return Result.RUN;
}
private bool CheckModuleHaveWaferWithNoJob(out string reason)
{
reason = "";
if (_lstControlJobs.Count > 0)
{
reason = "lstControlJobs.Count > 0";
return false;
}
else
{
if (_buffer.HasWafer(0) || _buffer.HasWafer(1) || _buffer.HasWafer(2))
{
reason = $"Buffer have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_tmRobot.HasWafer(0))
{
reason = $"TmRobot have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_aligner.HasWafer(0))
{
reason = $"Aligner have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_waferRobot.HasWafer(0))
{
reason = $"WaferRobot have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_load.HasWafer(0))
{
reason = $"Load have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_load.HasTray(0))
{
reason = $"Load have Tray!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_unload.HasWafer(0))
{
reason = $"UnLoad have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_unload.HasTray(0))
{
reason = $"UnLoad have Tray!";
EV.PostWarningLog(LogSource, reason);
return true;
}
return false;
}
}
#endregion
/// <summary>
/// Add condition string
/// </summary>
/// <param name="s"></param>
/// <param name="v"></param>
/// <returns></returns>
private string AddC(string s, string v, string sShould)
{
return (s + ":" + v + ", Should be:" + sShould + "\r\n");
}
}
}