Sic04/SicRT/Equipments/ReturnAllWafer.cs

811 lines
28 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.Collections.Generic;
using Aitex.Core.Common;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using SicRT.Modules.Schedulers;
using SicRT.Scheduler;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
namespace SicRT.Modules
{
public class ReturnAllWafer : SchedulerModuleFactory
{
//private bool needAligner = false;
Dictionary<ModuleName, int> _checkPosition = new Dictionary<ModuleName, int>()
{
{ModuleName.PM1, 1},
{ModuleName.LoadLock, 1},
{ModuleName.UnLoad, 1},
{ModuleName.WaferRobot, 1},
{ModuleName.TrayRobot, 1},
{ModuleName.TMRobot, 1},
{ModuleName.Aligner, 1},
};
private readonly R_TRIG _trigLoadUnLoadAllPumpAlarm = new R_TRIG();
private readonly R_TRIG _trigWaferNoOriginWarn = new R_TRIG();
public ReturnAllWafer()
{
}
public Result Start()
{
if (!_tmRobot.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, TmRobot is not available!");
return Result.FAIL;
}
if (!_trayRobot.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, TrayRobot is not available!");
return Result.FAIL;
}
if (!_waferRobot.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, WaferRobot is not available!");
return Result.FAIL;
}
if (!_load.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, Load is not available!");
return Result.FAIL;
}
if (!_unload.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, UnLoad is not available!");
return Result.FAIL;
}
if (!_buffer.IsAvailable)
{
EV.PostWarningLog("Scheduler", "can not return wafer, Buffer is not available!");
return Result.FAIL;
}
return Result.RUN;
}
public Result Monitor()
{
MonitorModuleTasks();
if (MonitorTaskDone())
{
return Result.DONE;
}
return Result.RUN;
}
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}");
_trigLoadUnLoadAllPumpAlarm.CLK = (_unload.IsInPumping && _load.IsInPumping);
if (_trigLoadUnLoadAllPumpAlarm.Q)
EV.PostAlarmLog("Scheduler", $"Detected that Load and UnLoad are pumping at the same timeLoad Task: {_load.GetTaskRunning()}, UnLoad Task: {_unload.GetTaskRunning()}");
MonitorPMTask();
MonitorLoadTask();
MonitorUnLoadTask();
MonitorBufferTask();
MonitorAlignerTask();
MonitorTmRobotTask();
MonitorWaferRobotTask();
MonitorTrayRobotTask();
return Result.RUN;
}
private bool MonitorTaskDone()
{
foreach (var positions in _checkPosition)
{
for (int i = 0; i < positions.Value; i++)
{
if (CheckWaferCouldBeReturn(positions.Key, i))
{
return false;
}
}
}
if (_buffer.HasWafer(0) || _buffer.HasWafer(1) || _buffer.HasWafer(2))
return false;
if (_buffer.HasTrayAndExceedProcessCount(0) || _buffer.HasTrayAndExceedProcessCount(1) || _buffer.HasTrayAndExceedProcessCount(2))
return false;
if (!_tmRobot.IsAvailable)
return false;
if (!_waferRobot.IsAvailable)
return false;
if (!_trayRobot.IsAvailable)
return false;
return true;
}
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();
MonitorWaferRobotAligerTask();
MonitorWaferRobotLoadTask();
MonitorWaferRobotUnLoadTask();
}
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))
{
if (_tmRobot.Place(_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);
if (canPlaceUnLoad)
{
if (_unload.IsReadyForPlace(ModuleName.TMRobot, 0))
{
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,UnLoad分离完成
bool canPickUnLoad = _tmRobot.NoTray(0)
&& _unload.HasTray(0)
&& _unload.CheckWaferTraySeparated();
if (canPickUnLoad)
{
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 次数未耗尽的Tray放入Buffer中
bool canPalce = _tmRobot.NoWafer(0) && _tmRobot.HasTrayAndNotExceedProcessCount(0);
if (canPalce)
{
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) && _unload.NoTray(0) && _unload.NoWafer(0);
if (canPick)
{
for (int i = 0; i < 3; i++)
{
if (_buffer.HasTray(i) && _buffer.HasWafer(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
if (_buffer.HasTrayAndExceedProcessCount(i))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, i))
{
if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
}
private void MonitorTmRobotPMTask()
{
if (!_tmRobot.IsAvailable)
return;
//pick from pm
if (_tmRobot.NoWafer(0) && _tmRobot.NoTray(0) && _unload.NoWafer(0) && _unload.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)
|| _tmRobot.HasWafer((int)pickBlade)
|| !schedulerPm.CheckTempBelow900())
continue;
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;
bool canPick = _waferRobot.NoWafer(0)
&& _load.HasWafer(0);
//&& _load.CheckWaferTraySeparated();
if (canPick)
{
if (_load.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_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);
if (canPick)
{
if (_unload.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_unload.Module, 0, Hand.Blade1))
{
_unload.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
private void MonitorWaferRobotAligerTask()
{
if (_load.HasWafer(0) && _load.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner)
_load.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;
if (_unload.HasWafer(0) && _unload.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner)
_unload.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;
if (_waferRobot.HasWafer(0) && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.System)
_waferRobot.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner;
if (!_waferRobot.IsAvailable)
return;
if (!_aligner.IsAvailable)
return;
//place 任务还没完成,下一步是Aligner,Robot有片子,Aligner没片子
bool canPlaceAligner = _aligner.NoWafer(0)
&& _waferRobot.HasWafer(0)
&& _waferRobot.GetWaferInfo(0).NextStation == (int)ModuleName.Aligner;
if (canPlaceAligner)
{
if (_aligner.IsReadyForPlace(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Place(_aligner.Module, 0, Hand.Blade1))
{
_aligner.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
if (!_waferRobot.IsAvailable)
return;
if (!_aligner.IsAvailable)
return;
//pick Robot没片子,Aligner有片子
bool canPickAligner = _aligner.HasWafer(0)
&& _waferRobot.NoWafer(0);
if (canPickAligner)
{
if (_aligner.IsReadyForPick(ModuleName.WaferRobot, 0))
{
if (_waferRobot.Pick(_aligner.Module, 0, Hand.Blade1))
{
_aligner.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
private void MonitorWaferRobotCassetteTask()
{
if (!_waferRobot.IsAvailable)
return;
//place
bool canPlaceCassette = _waferRobot.HasWafer(0)&& _waferRobot.GetWaferInfo(0).NextStation!=(int)ModuleName.Aligner;
if (canPlaceCassette)
{
WaferInfo wafer = _waferRobot.GetWaferInfo(0);
_trigWaferNoOriginWarn.CLK = (wafer.OriginStation != (int)ModuleName.CassAL &&
wafer.OriginStation != (int)ModuleName.CassAR);
// Wafer来源不明提示用户
if (_trigWaferNoOriginWarn.Q)
{
EV.PostWarningLog("ReturnAllWafer",
"Unknown origin station of wafer on Wafer Robot");
return;
}
if (wafer.OriginStation == (int)ModuleName.CassAL)
{
if (_cassetteAL.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot) &&
WaferManager.Instance.CheckNoWafer(ModuleName.CassAL, wafer.OriginSlot))
{
if (_waferRobot.Place(_cassetteAL.Module, wafer.OriginSlot, Hand.Blade1))
{
_cassetteAL.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
else if (wafer.OriginStation == (int)ModuleName.CassAR)
{
if (_cassetteAR.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot) &&
WaferManager.Instance.CheckNoWafer(ModuleName.CassAR, wafer.OriginSlot))
{
if (_waferRobot.Place(_cassetteAR.Module, wafer.OriginSlot, Hand.Blade1))
{
_cassetteAR.WaitTransfer(ModuleName.WaferRobot);
return;
}
}
}
}
}
private void MonitorTrayRobotLoadTask()
{
if (!_trayRobot.IsAvailable)
return;
if (!_load.IsAvailable)
return;
//先取Wafer再取石墨盘
bool canPick = _load.HasTray(0) && _load.NoWafer(0);
if (canPick)
{
SlotItem emptyTraySlot = GetTrayOrignSlot(ModuleName.LoadLock, 0);
if (emptyTraySlot != null)
{
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.HasTray(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;
}
}
}
}
}
private void MonitorBufferTask()
{
if (!_buffer.IsAvailable)
{
return;
}
if (!_buffer.IsReadyForPick(ModuleName.TMRobot, 0))
{
_buffer.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
}
}
private void MonitorAlignerTask()
{
if (!_aligner.IsAvailable)
{
return;
}
if (_aligner.HasWafer(0) && _aligner.GetWaferInfo(0).NextStation==(int)ModuleName.Aligner)
{
_aligner.Aligning();
_aligner.GetWaferInfo(0).NextStation = (int)ModuleName.System;
}
}
private void MonitorPMTask()
{
foreach (var pm in _lstPms)
{
if (!pm.IsAvailable)
continue;
if (pm.NoTray(0) && pm.NoWafer(0))
continue;
if (!pm.IsReadyForPick(ModuleName.TMRobot, 0))
{
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
}
}
}
private void MonitorLoadTask()
{
if (!_load.IsAvailable)
{
return;
}
if (_load.HasWafer(0))
{
if (/*_load.CheckWaferTraySeparated() &&*/ !_load.IsReadyForPick(ModuleName.WaferRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0);
return;
}
}
else if (_load.HasTray(0))
{
if (/*_load.CheckWaferTraySeparated() &&*/ !_load.IsReadyForPick(ModuleName.TrayRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TrayRobot, EnumTransferType.Pick, 0);
return;
}
}
else if (_tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0))
{
if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_unload.IsInPumping && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
}
private void MonitorUnLoadTask()
{
if (!_unload.IsAvailable)
{
return;
}
// 如果有Wafer有Tray先检查是否分离
if (_unload.HasWafer(0) && _unload.HasTray(0))
{
if (!_unload.CheckWaferTraySeparated())
{
_unload.SeparateWaferTray();
return;
}
}
if (_unload.HasTray(0)) // UnLoad有Tray先让TMRobot取Tray
{
if (_unload.CheckWaferTraySeparated())
{
// 如果Sequence下一步是UnLoad,并且W&T已冷却和分离
if (!_unload.CheckPurgedBeforeTrayPicking()
&& !_load.IsInPumping)
{
var cycle = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.CyclePurgeCount");
var pumpDelay = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.PumpDelayTime");
_unload.PurgeBeforeTrayPicking(cycle, pumpDelay);
return;
}
if (_unload.CheckPurgedBeforeTrayPicking()
&& !_unload.IsReadyForPick(ModuleName.TMRobot, 0)
&& !_load.IsInPumping)
{
// UnLoad中有Tray则准备好让TMRobot来取
_unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
return;
}
}
}
else if (_unload.HasWafer(0)) // 如果没TrayWaferRobot取Wafer
{
if (_unload.CheckWaferTraySeparated() )
{
// 如果取Wafer前还未Purge先Purge
if (!_unload.CheckPurgedBeforeWaferPicking()
&& !_load.IsInPumping)
{
var cycle = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.CyclePurgeCount");
var pumpDelay = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.PumpDelayTime");
_unload.PurgeBeforeWaferPicking(cycle, pumpDelay);
return;
}
if (_unload.CheckPurgedBeforeWaferPicking()
&& !_unload.IsReadyForPick(ModuleName.WaferRobot, 0)
&& !_load.IsInPumping)
{
// 准备好让WaferRobot来取
_unload.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0);
}
}
return;
}
else // 如果UnLoad里啥也没有则准备好下次TMRobot喂 W&T
{
// 如果Wafer取完后还没有Purge先Purge
if (!_unload.CheckPurgedAfterWaferPicked() && !_load.IsInPumping)
{
var cycle = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.CyclePurgeCount");
var pumpDelay = SC.GetValue<int>($"{ModuleName.UnLoad}.Purge.PumpDelayTime");
_unload.PurgeAfterWaferPicked(cycle, pumpDelay);
}
// 如果Wafer取完后还没有Purge则终止后去操作。
if (!_unload.CheckPurgedAfterWaferPicked())
return;
if (!_load.IsInPumping
&& !_unload.IsReadyForPlace(ModuleName.TMRobot, 0)
&& !_load.IsInPumping)
{
_unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
}
private SlotItem GetEmptyTraySlot()
{
for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.CassBL).Length; i++)
{
if (WaferManager.Instance.CheckNoTray(ModuleName.CassBL, 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 bool CheckWaferCouldBeReturn(ModuleName module, int slot)
{
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
if (!wafer.IsEmpty)
{
return true;
}
else if (wafer.TrayState == WaferTrayStatus.Normal)
{
return true;
}
return false;
}
}
}