2023-03-14 17:20:31 +08:00
|
|
|
|
using Aitex.Core.RT.Device;
|
2023-03-03 15:42:13 +08:00
|
|
|
|
using Aitex.Core.RT.Event;
|
2023-04-13 15:35:13 +08:00
|
|
|
|
using Aitex.Core.RT.Log;
|
2023-03-03 15:42:13 +08:00
|
|
|
|
using Aitex.Core.RT.Routine;
|
|
|
|
|
using Aitex.Core.RT.SCCore;
|
|
|
|
|
using MECF.Framework.Common.Equipment;
|
|
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
|
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
|
2023-04-13 15:35:13 +08:00
|
|
|
|
using SicModules.LLs.Routines;
|
|
|
|
|
using SicModules.TMs.Routines.Base;
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
2023-04-13 15:35:13 +08:00
|
|
|
|
namespace SicModules.TMs.Routines
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
|
|
|
|
public class TMRobotPlaceRoutine : TMBaseRoutine
|
|
|
|
|
{
|
|
|
|
|
enum RoutineStep
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
WaitOpenSlitValveInterlock,
|
|
|
|
|
OpenSlitValve,
|
|
|
|
|
|
|
|
|
|
CheckBeforePlace,
|
|
|
|
|
Place,
|
|
|
|
|
PrepareTransfer,
|
|
|
|
|
|
|
|
|
|
Extend,
|
|
|
|
|
Handoff,
|
|
|
|
|
HandoffDelay,
|
|
|
|
|
Retract,
|
|
|
|
|
UpdateWaferInfoByHandoff,
|
|
|
|
|
|
|
|
|
|
RequestWaferPresent,
|
|
|
|
|
BeforePlaceRequestWaferPresent,
|
|
|
|
|
AfterPlaceRequestWaferPresent,
|
|
|
|
|
CheckWaferInfoByRobotSensor,
|
|
|
|
|
BeforePlaceCheckWaferInfoByRobotSensor,
|
|
|
|
|
AfterPlaceCheckWaferInfoByRobotSensor,
|
|
|
|
|
RequestAWCData,
|
|
|
|
|
SetRobortExtendToDo,
|
|
|
|
|
ClearRobortExtendToDo,
|
|
|
|
|
|
|
|
|
|
WaitCloseSlitValveInterlock,
|
|
|
|
|
CloseSlitValve,
|
|
|
|
|
WaitPMSensor,
|
|
|
|
|
PostTransfer,
|
|
|
|
|
OpenShutter,
|
|
|
|
|
CloseShutter,
|
|
|
|
|
Delay1,
|
|
|
|
|
Delay2,
|
|
|
|
|
VceMoveToSlot,
|
|
|
|
|
RobotGotoNotWait,
|
|
|
|
|
PrepareTransferNotWait,
|
|
|
|
|
CheckRobotReady,
|
|
|
|
|
CheckTransferPrepared,
|
|
|
|
|
LoadRatation,
|
|
|
|
|
TrayClamp,
|
|
|
|
|
TrayUnClamp,
|
|
|
|
|
TimeDelay1,
|
|
|
|
|
TimeDelay2,
|
|
|
|
|
TimeDelay3,
|
|
|
|
|
SuspectorCheck
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ModuleName _target;
|
|
|
|
|
private int _targetSlot;
|
|
|
|
|
private RobotArmEnum _blade;
|
|
|
|
|
private int _placeTimeout;
|
|
|
|
|
private bool _requestAWCData;
|
|
|
|
|
|
|
|
|
|
private bool _autoHand;
|
|
|
|
|
private TMSlitValveRoutine _openSlitValveRoutine = new TMSlitValveRoutine();
|
|
|
|
|
private TMSlitValveRoutine _closeSlitValveRoutine = new TMSlitValveRoutine();
|
|
|
|
|
//private VCEMoveToSlotRoutine _vceMoveToSlotRoutine;
|
|
|
|
|
|
|
|
|
|
private LoadLockTrayClawRoutine _trayClamp = new LoadLockTrayClawRoutine();
|
|
|
|
|
private LoadLockTrayClawRoutine _trayUnClamp = new LoadLockTrayClawRoutine();
|
|
|
|
|
private SicTM _tm;
|
|
|
|
|
|
|
|
|
|
public TMRobotPlaceRoutine()
|
|
|
|
|
{
|
|
|
|
|
Module = "TMRobot";
|
|
|
|
|
Name = "Place";
|
|
|
|
|
_tm = DEVICE.GetDevice<SicTM>($"{ ModuleName.System.ToString()}.{ ModuleName.TM.ToString()}");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Init(ModuleName target, int targetSlot, RobotArmEnum blade)
|
|
|
|
|
{
|
|
|
|
|
Init(target, targetSlot, blade, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Init(ModuleName target, int targetSlot, int blade)
|
|
|
|
|
{
|
|
|
|
|
Init(target, targetSlot, blade == 0 ? RobotArmEnum.Blade1 : RobotArmEnum.Blade2, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Init(ModuleName target, int targetSlot)
|
|
|
|
|
{
|
|
|
|
|
Init(target, targetSlot, RobotArmEnum.Blade1, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Init(ModuleName target, int targetSlot, RobotArmEnum blade, bool autoHand)
|
|
|
|
|
{
|
|
|
|
|
_autoHand = autoHand;
|
|
|
|
|
_target = target;
|
|
|
|
|
_targetSlot = targetSlot;
|
|
|
|
|
_blade = blade;
|
|
|
|
|
|
|
|
|
|
_openSlitValveRoutine.Init(target.ToString(), true);
|
|
|
|
|
_closeSlitValveRoutine.Init(target.ToString(), false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Result Start(params object[] objs)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
if (RobotDevice.RobotState != RobotStateEnum.Idle)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, TMRobot Is Not IDLE");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
_placeTimeout = SC.GetValue<int>("TMRobot.PlaceTimeout");
|
|
|
|
|
_requestAWCData = SC.GetValue<bool>("System.RequestAWCDataAfterPlace");
|
|
|
|
|
|
|
|
|
|
if (!WaferManager.Instance.CheckNoTray(_target, _targetSlot))
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, should no tray at {_target}, {_targetSlot + 1}");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_autoHand)
|
|
|
|
|
{
|
|
|
|
|
if (WaferManager.Instance.CheckHasWafer(Module, 0))
|
|
|
|
|
{
|
|
|
|
|
_blade = RobotArmEnum.Blade1;
|
|
|
|
|
}
|
|
|
|
|
else if (WaferManager.Instance.CheckHasWafer(Module, 1))
|
|
|
|
|
{
|
|
|
|
|
_blade = RobotArmEnum.Blade2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, Robot both arm no wafer");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int slot = _blade == RobotArmEnum.Blade1 ? 0 : 1;
|
|
|
|
|
if (WaferManager.Instance.CheckNoTray(ModuleHelper.Converter(Module), slot))
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, Robot arm {slot + 1} no tray");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//顶针必须在低位
|
|
|
|
|
if (_target == ModuleName.LoadLock || _target == ModuleName.Load)
|
|
|
|
|
{
|
|
|
|
|
if (!LoadLift.IsDown)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, Load Lift must in down Position!");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (_target == ModuleName.UnLoad)
|
|
|
|
|
{
|
|
|
|
|
if (!UnLoadLift.IsDown)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, UnLoad Lift must in down Position!");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Place之前先,根据Sensor检测是否有盘
|
|
|
|
|
if (!SC.GetValue<bool>("System.IsSimulatorMode"))
|
|
|
|
|
{
|
|
|
|
|
if (_target ==ModuleName.LoadLock&& SensorLLTrayPresence.Value)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, LLTrayPresence sensor has tray");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
if (_target == ModuleName.UnLoad && SensorUnloadWaferPresence.Value)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place, UnloadWaferPresence sensor has wafer");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
if (ModuleHelper.IsBuffer(_target) && _targetSlot == 2&& SensorBufferHighWaferPresence.Value)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place,BufferHighWaferPresence sensor check has wafer");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
if (ModuleHelper.IsBuffer(_target) && _targetSlot == 1&& SensorBufferMiddleWaferPresence.Value)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place,BufferMiddleWaferPresence sensor check has wafer");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
if (ModuleHelper.IsBuffer(_target) && _targetSlot == 0&& SensorBufferLowWaferPresence.Value)
|
|
|
|
|
{
|
|
|
|
|
EV.PostWarningLog(Module, $"Can not place,BufferLowWaferPresence sensor check has wafer");
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_trayClamp.Init(true);
|
|
|
|
|
_trayUnClamp.Init(false);
|
|
|
|
|
Notify($"Start, Place to {_target} slot {_targetSlot + 1}, by {(_blade == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}");
|
|
|
|
|
|
|
|
|
|
return Result.RUN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Abort()
|
|
|
|
|
{
|
|
|
|
|
_tm.CloseAllVentPumpValue();
|
|
|
|
|
if (!IsPicking)
|
|
|
|
|
{
|
|
|
|
|
RobotDevice.Stop();
|
|
|
|
|
}
|
|
|
|
|
Notify("Abort");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Result Monitor()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
WaitSlitValveOpenInterlock((int)RoutineStep.WaitOpenSlitValveInterlock, TMDevice.GetSlitValve(_target), _placeTimeout);
|
|
|
|
|
RobotGotoNotWait((int)RoutineStep.RobotGotoNotWait, RobotDevice, _target, _targetSlot, _blade, _placeTimeout);
|
|
|
|
|
|
|
|
|
|
//如果是Buffer腔,则不需要打开闸板阀动作
|
|
|
|
|
if (_target != ModuleName.Buffer)
|
|
|
|
|
{
|
|
|
|
|
ExecuteRoutine((int)RoutineStep.OpenSlitValve, _openSlitValveRoutine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//如果是PM腔,放盘前检查传感器DI_ReactorSuspectorCheck
|
|
|
|
|
//如果有,则不能放盘
|
|
|
|
|
if (ModuleHelper.IsPm(_target))
|
|
|
|
|
{
|
|
|
|
|
CheckReactorSuspector((int)RoutineStep.SuspectorCheck, _target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CheckRobotReady((int)RoutineStep.CheckRobotReady, RobotDevice, _placeTimeout);
|
|
|
|
|
|
|
|
|
|
CheckBeforePlace((int)RoutineStep.CheckBeforePlace, _target, _targetSlot, _blade);
|
|
|
|
|
RobotRequestWaferPresent((int)RoutineStep.BeforePlaceRequestWaferPresent, RobotDevice, _blade, _placeTimeout);
|
|
|
|
|
CheckWaferInfoByRobotRQ((int)RoutineStep.BeforePlaceCheckWaferInfoByRobotSensor, RobotDevice, _blade, 10);
|
|
|
|
|
|
|
|
|
|
WaitPMReadySensor((int)RoutineStep.WaitPMSensor, _target, 5);
|
2023-03-14 16:12:44 +08:00
|
|
|
|
SetRobotExtendToDO((int)RoutineStep.SetRobortExtendToDo, _target, 2);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
|
|
|
|
CheckRobotReady((int)RoutineStep.CheckRobotReady, RobotDevice, _placeTimeout);
|
|
|
|
|
Place((int)RoutineStep.Place, RobotDevice, _target, _targetSlot, _blade, _placeTimeout);
|
|
|
|
|
IsPicking = false;
|
|
|
|
|
TimeDelay((int)RoutineStep.TimeDelay1, 1);
|
|
|
|
|
RobotRequestWaferPresent((int)RoutineStep.RequestWaferPresent, RobotDevice, _blade, _placeTimeout);
|
|
|
|
|
CheckWaferInfoByRobotRQ((int)RoutineStep.CheckWaferInfoByRobotSensor, RobotDevice, _blade, 10);
|
|
|
|
|
|
|
|
|
|
if (_requestAWCData)
|
|
|
|
|
{
|
|
|
|
|
RobotRequestWaferAWCData((int)RoutineStep.RequestAWCData, RobotDevice, _placeTimeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClearRobortExtendToDO((int)RoutineStep.ClearRobortExtendToDo);
|
|
|
|
|
TimeDelay((int)RoutineStep.TimeDelay2, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (_target == ModuleName.Load || _target == ModuleName.LoadLock)
|
|
|
|
|
{
|
|
|
|
|
//对中
|
|
|
|
|
ExecuteRoutine((int)RoutineStep.TrayClamp, _trayClamp); //夹爪关闭
|
|
|
|
|
TimeDelay((int)RoutineStep.TimeDelay3, 1);//延迟1s
|
|
|
|
|
ExecuteRoutine((int)RoutineStep.TrayUnClamp, _trayUnClamp); //夹爪打开
|
|
|
|
|
//ExecuteRoutine((int)RoutineStep.LoadRatation, loadRotationHomeRoutine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////如果是PM腔,放完盘后检查传感器DI_ReactorSuspectorCheck
|
|
|
|
|
//if (ModuleHelper.IsPm(_target))
|
|
|
|
|
//{
|
|
|
|
|
// CheckReactorSuspector((int)RoutineStep.SuspectorCheck);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//如果是Buffer腔,则不需要打开闸板阀动作
|
|
|
|
|
if (_target != ModuleName.Buffer)
|
|
|
|
|
{
|
|
|
|
|
ExecuteRoutine((int)RoutineStep.CloseSlitValve, _closeSlitValveRoutine);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (RoutineBreakException)
|
|
|
|
|
{
|
|
|
|
|
return Result.RUN;
|
|
|
|
|
}
|
|
|
|
|
catch (RoutineFaildException ex)
|
|
|
|
|
{
|
|
|
|
|
LOG.Error(ex.ToString());
|
|
|
|
|
RobotDevice.Stop();
|
|
|
|
|
return Result.FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Notify($"Finish, Place to {_target} slot {_targetSlot + 1}, by {_blade}");
|
|
|
|
|
|
|
|
|
|
return Result.DONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|