281 lines
10 KiB
C#
281 lines
10 KiB
C#
using System;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Event;
|
|
using Aitex.Core.RT.Routine;
|
|
using Aitex.Core.RT.SCCore;
|
|
using Aitex.Core.Util;
|
|
using Aitex.Sorter.Common;
|
|
using MECF.Framework.Common.Equipment;
|
|
using MECF.Framework.Common.Schedulers;
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks;
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
|
|
|
|
namespace Mainframe.TMs
|
|
{
|
|
public class TMRobotPickAndPlaceRoutine : TMBaseRoutine
|
|
{
|
|
enum RoutineStep
|
|
{
|
|
WaitOpenSlitValveInterlock,
|
|
|
|
OpenSlitValve,
|
|
|
|
CheckBeforePick,
|
|
Pick,
|
|
PickLiftMove,
|
|
PickExtend,
|
|
PickHandoff,
|
|
PickHandoffDelay,
|
|
PickRetract,
|
|
PickUpdateWaferInfoByHandoff,
|
|
PickRequestWaferPresent,
|
|
PickCheckWaferInfoByRobotSensor,
|
|
PickWaitCloseSlitValveInterlock,
|
|
PickRequestAWCData,
|
|
|
|
CheckBeforePlace,
|
|
Place,
|
|
PlaceLiftMove,
|
|
PlaceExtend,
|
|
PlaceHandoff,
|
|
PlaceHandoffDelay,
|
|
PlaceRetract,
|
|
PlaceUpdateWaferInfoByHandoff,
|
|
PlaceRequestWaferPresent,
|
|
PlaceCheckWaferInfoByRobotSensor,
|
|
PlaceWaitCloseSlitValveInterlock,
|
|
PlaceRequestAWCData,
|
|
|
|
CloseSlitValve,
|
|
|
|
PostTransfer,
|
|
}
|
|
|
|
private Hand _pickBlade;
|
|
private Hand _placeBlade;
|
|
private ModuleName _targetModule;
|
|
private int _pickSlot;
|
|
private int _placeSlot;
|
|
private int _pickTimeout;
|
|
private int _placeTimeout;
|
|
private int _postTransferTimeout;
|
|
private TMSlitValveRoutine _openSlitValveRoutine = new TMSlitValveRoutine();
|
|
private TMSlitValveRoutine _closeSlitValveRoutine = new TMSlitValveRoutine();
|
|
|
|
private bool _requestAWCDataPick;
|
|
private bool _requestAWCDataPlace;
|
|
|
|
public TMRobotPickAndPlaceRoutine()
|
|
{
|
|
Module = "TMRobot";
|
|
Name = "Swap";
|
|
}
|
|
|
|
public void Init(ModuleName targetModule, int pickSlot, int placeSlot, Hand pickBlade, Hand placeBlade)
|
|
{
|
|
_pickBlade = pickBlade;
|
|
_placeBlade = placeBlade;
|
|
_targetModule = targetModule;
|
|
_pickSlot = pickSlot;
|
|
_placeSlot = placeSlot;
|
|
_openSlitValveRoutine.Init(targetModule.ToString(), true);
|
|
_closeSlitValveRoutine.Init(targetModule.ToString(), false);
|
|
}
|
|
|
|
public override Result Start(params object[] objs)
|
|
{
|
|
Reset();
|
|
|
|
_pickTimeout = SC.GetValue<int>("TMRobot.PickTimeout");
|
|
_placeTimeout = SC.GetValue<int>("TMRobot.PlaceTimeout");
|
|
_postTransferTimeout = SC.GetValue<int>($"{_targetModule}.PostTransferTimeout");
|
|
_requestAWCDataPick = SC.GetValue<bool>("System.RequestAWCDataAfterPick");
|
|
_requestAWCDataPlace = SC.GetValue<bool>("System.RequestAWCDataAfterPlace");
|
|
|
|
if (!WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, (int) _pickBlade))
|
|
{
|
|
EV.PostWarningLog(Module, $"Can not pick by {_pickBlade}, found wafer on");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if (!WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, (int)_placeBlade))
|
|
{
|
|
EV.PostWarningLog(Module, $"Can not place by {_placeBlade}, no wafer on");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if (_pickSlot != _placeSlot)
|
|
{
|
|
if (!WaferManager.Instance.CheckHasWafer(_targetModule, _pickSlot))
|
|
{
|
|
EV.PostWarningLog(Module, $"Can not pick from {_targetModule} slot {_pickSlot + 1}, no wafer on");
|
|
return Result.FAIL;
|
|
}
|
|
if (!WaferManager.Instance.CheckNoWafer(_targetModule, _placeSlot))
|
|
{
|
|
EV.PostWarningLog(Module, $"Can not place to {_targetModule} slot {_placeSlot + 1}, found wafer on");
|
|
return Result.FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!WaferManager.Instance.CheckHasWafer(_targetModule, _placeSlot))
|
|
{
|
|
{
|
|
EV.PostWarningLog(Module, $"Can not pick&place from {_targetModule} slot {_placeSlot + 1}, no wafer on");
|
|
return Result.FAIL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Notify("Start");
|
|
|
|
return Result.RUN;
|
|
}
|
|
|
|
public override void Abort()
|
|
{
|
|
Notify("Abort");
|
|
}
|
|
|
|
|
|
public override Result Monitor()
|
|
{
|
|
try
|
|
{
|
|
//Open slit valve
|
|
//WaitSlitValveOpenInterlock((int)RoutineStep.WaitOpenSlitValveInterlock, TMDevice.GetSlitValve(_targetModule), _pickTimeout);
|
|
|
|
//ExecuteRoutine((int)RoutineStep.OpenSlitValve, _openSlitValveRoutine);
|
|
|
|
//if (ModuleHelper.IsLoadLock(_targetModule))
|
|
//{
|
|
// LLLiftMove((int)RoutineStep.PickLiftMove, DEVICE.GetDevice<LoadLock>(_targetModule.ToString()), _pickSlot, _pickTimeout);
|
|
//}
|
|
////Pick
|
|
//CheckBeforePick((int)RoutineStep.CheckBeforePick, _targetModule, _pickSlot, _pickBlade);
|
|
|
|
//if (ModuleHelper.IsPm(_targetModule) && DEVICE.GetDevice<PM>(_targetModule.ToString()).IsActiveHandoff)
|
|
//{
|
|
// PickExtend((int)RoutineStep.PickExtend, RobotDevice, _targetModule, _pickSlot, _pickBlade, _pickTimeout);
|
|
|
|
// TransferHandoff((int)RoutineStep.PickHandoff, DEVICE.GetDevice<PM>(_targetModule.ToString()), EnumTransferType.Pick, _pickTimeout);
|
|
// Delay((int)RoutineStep.PickHandoffDelay, 2);
|
|
|
|
// UpdateWaferInfoDueHandoff((int)RoutineStep.PickUpdateWaferInfoByHandoff, _targetModule, _pickSlot, ModuleHelper.Converter(Module), (int)_pickBlade);
|
|
|
|
// PickRetract((int)RoutineStep.PickRetract, RobotDevice, _targetModule, _pickSlot, _pickBlade, _pickTimeout);
|
|
//}
|
|
//else
|
|
//{
|
|
// Pick((int)RoutineStep.Pick, RobotDevice, _targetModule, _pickSlot, _pickBlade, _pickTimeout);
|
|
//}
|
|
|
|
//RobotRequestWaferPresent((int)RoutineStep.PickRequestWaferPresent, RobotDevice, _pickTimeout);
|
|
|
|
//CheckWaferInfoByRobotSensor((int)RoutineStep.PickCheckWaferInfoByRobotSensor, RobotDevice, _pickBlade);
|
|
|
|
//if (_requestAWCDataPick)
|
|
//{
|
|
// RobotRequestWaferAWCData((int)RoutineStep.PickRequestAWCData, RobotDevice, _pickTimeout);
|
|
//}
|
|
|
|
////Place
|
|
//if (ModuleHelper.IsLoadLock(_targetModule))
|
|
//{
|
|
// LLLiftMove((int)RoutineStep.PlaceLiftMove, DEVICE.GetDevice<LoadLock>(_targetModule.ToString()), _placeSlot, _placeTimeout);
|
|
//}
|
|
|
|
//CheckBeforePlace((int)RoutineStep.CheckBeforePlace, _targetModule, _placeSlot, _placeBlade);
|
|
|
|
//if (ModuleHelper.IsPm(_targetModule) && DEVICE.GetDevice<PM>(_targetModule.ToString()).IsActiveHandoff)
|
|
//{
|
|
// PlaceExtend((int)RoutineStep.PlaceExtend, RobotDevice, _targetModule, _placeSlot, _placeBlade, _placeTimeout);
|
|
|
|
// TransferHandoff((int)RoutineStep.PlaceHandoff, DEVICE.GetDevice<PM>(_targetModule.ToString()), EnumTransferType.Place, _placeTimeout);
|
|
|
|
// Delay((int)RoutineStep.PlaceHandoffDelay, 2);
|
|
|
|
|
|
// UpdateWaferInfoDueHandoff((int)RoutineStep.PlaceUpdateWaferInfoByHandoff, ModuleHelper.Converter(Module), (int)_placeBlade, _targetModule, _placeSlot);
|
|
|
|
// PlaceRetract((int)RoutineStep.PlaceRetract, RobotDevice, _targetModule, _placeSlot, _placeBlade, _placeTimeout);
|
|
//}
|
|
//else
|
|
//{
|
|
|
|
// Place((int)RoutineStep.Place, RobotDevice, _targetModule, _placeSlot, _placeBlade, _placeTimeout);
|
|
//}
|
|
|
|
//RobotRequestWaferPresent((int)RoutineStep.PlaceRequestWaferPresent, RobotDevice, _placeTimeout);
|
|
|
|
//CheckWaferInfoByRobotSensor((int)RoutineStep.PlaceCheckWaferInfoByRobotSensor, RobotDevice, _placeBlade);
|
|
|
|
//if (_requestAWCDataPlace)
|
|
//{
|
|
// RobotRequestWaferAWCData((int)RoutineStep.PlaceRequestAWCData, RobotDevice, _placeTimeout);
|
|
//}
|
|
////Close slit valve
|
|
//WaitSlitValveCloseInterlock((int)RoutineStep.PlaceWaitCloseSlitValveInterlock, TMDevice.GetSlitValve(_targetModule), _placeTimeout);
|
|
|
|
//ExecuteRoutine((int)RoutineStep.CloseSlitValve, _closeSlitValveRoutine);
|
|
|
|
//if (ModuleHelper.IsPm(_targetModule) && DEVICE.GetDevice<PM>(_targetModule.ToString()).IsNeedPostTransfer)
|
|
//{
|
|
// PostTransfer((int)RoutineStep.PostTransfer, DEVICE.GetDevice<PM>(_targetModule.ToString()), EnumTransferType.Place, _postTransferTimeout);
|
|
//}
|
|
}
|
|
catch (RoutineBreakException)
|
|
{
|
|
return Result.RUN;
|
|
}
|
|
catch (RoutineFaildException)
|
|
{
|
|
return Result.FAIL;
|
|
}
|
|
|
|
Notify("Finished");
|
|
|
|
return Result.DONE;
|
|
}
|
|
|
|
protected void LLLiftMove(int id, LoadLock ll, int slot, int timeout)
|
|
{
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
{
|
|
Notify($"Move {ll.Name} Lift to {slot + 1}");
|
|
if (!ll.SetLift(slot, out string reason))
|
|
{
|
|
Stop(reason);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}, () =>
|
|
{
|
|
|
|
return ll.CheckLift(slot);
|
|
}, timeout * 1000);
|
|
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
|
{
|
|
Stop($"Timeout, over {timeout} seconds");
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|