2023-04-13 15:35:13 +08:00
|
|
|
|
using System;
|
|
|
|
|
using Aitex.Core.RT.Device;
|
2023-03-03 15:42:13 +08:00
|
|
|
|
using Aitex.Core.RT.Routine;
|
|
|
|
|
using MECF.Framework.Common.Equipment;
|
|
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
2023-05-11 08:49:44 +08:00
|
|
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HiWinAligner;
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
2023-04-13 15:35:13 +08:00
|
|
|
|
namespace SicModules.Aligners.Routines.Base
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
|
|
|
|
public class AlignerBaseRoutine : ModuleRoutine, IRoutine
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
private HwAlignerGuide _alignerDevice = null;
|
|
|
|
|
|
2023-03-13 17:37:55 +08:00
|
|
|
|
protected AlignerBaseRoutine() : base(ModuleName.Aligner.ToString())
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
2023-05-15 14:04:17 +08:00
|
|
|
|
_alignerDevice = DEVICE.GetDevice<HwAlignerGuide>($"TM.HiWinAligner");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-03-13 17:37:55 +08:00
|
|
|
|
public override void Abort()
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//清除Aligner报警
|
|
|
|
|
protected void AlignerERS(int id,int timeout)
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
|
|
|
{
|
|
|
|
|
Notify($"Aligner ERS");
|
2023-05-11 08:49:44 +08:00
|
|
|
|
_alignerDevice.Set("ERS");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
return true;
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
return !_alignerDevice.IsBusy;
|
|
|
|
|
|
|
|
|
|
}, timeout * 1000);
|
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else if (ret.Item2 == Result.TIMEOUT)
|
|
|
|
|
{
|
|
|
|
|
Stop($"Aligner ERS Timeout, over {timeout} seconds");
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//初始化变量
|
|
|
|
|
protected void ResetVar(int id)
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
|
|
|
{
|
|
|
|
|
Notify($"Aligner Reset Variate ");
|
|
|
|
|
_alignerDevice.Reset();
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
Stop($"Sensor[DI-32] check no tray");
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//电机回原点
|
|
|
|
|
protected void Home(int id, int timeout)
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
|
|
|
{
|
|
|
|
|
Notify($"Aligner Home Msg");
|
2023-05-11 08:49:44 +08:00
|
|
|
|
_alignerDevice.Set("HOM");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
return true;
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
return !_alignerDevice.IsBusy;
|
|
|
|
|
|
|
|
|
|
}, timeout * 1000);
|
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
|
|
|
|
{
|
|
|
|
|
Stop($"Aligner home Timeout, over {timeout} seconds");
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//移动到测量中心
|
|
|
|
|
protected void AlignerMoveToMeasure(int id, int timeout)
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
|
|
|
{
|
|
|
|
|
Notify($"Move to Measure position");
|
2023-05-11 08:49:44 +08:00
|
|
|
|
_alignerDevice.Set("MTM");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
return true;
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
return !_alignerDevice.IsBusy;
|
|
|
|
|
|
|
|
|
|
}, timeout * 1000);
|
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else if (ret.Item2 == Result.TIMEOUT)
|
|
|
|
|
{
|
|
|
|
|
Stop($"Aligner Move to Measure position Timeout, over {timeout} seconds");
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//检查是否有Wafer
|
|
|
|
|
protected void CheckHaveWafer(int id, int timeout)
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
|
|
|
|
{
|
2023-05-17 17:15:14 +08:00
|
|
|
|
Notify($"Check wafer in position");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
2023-05-17 17:15:14 +08:00
|
|
|
|
_alignerDevice.CheckWaferLoad();
|
2023-03-03 15:42:13 +08:00
|
|
|
|
return true;
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
if (!_alignerDevice.IsBusy)
|
|
|
|
|
{
|
|
|
|
|
if (_alignerDevice.HaveWafer)
|
|
|
|
|
{
|
|
|
|
|
if (WaferManager.Instance.CheckNoWafer(Module, 0))
|
|
|
|
|
{
|
|
|
|
|
WaferManager.Instance.CreateWafer(ModuleHelper.Converter(Module), 0,Aitex.Core.Common.WaferStatus.Normal);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (WaferManager.Instance.CheckHasWafer(Module, 0))
|
|
|
|
|
{
|
|
|
|
|
WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Module), 0);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}, timeout * 1000);
|
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else if (ret.Item2 == Result.TIMEOUT)
|
|
|
|
|
{
|
|
|
|
|
Stop($"Aligner Check Wafer Timeout, over {timeout} seconds");
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-17 18:51:45 +08:00
|
|
|
|
protected void AlignerMove(int id, int timeout)
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
2023-05-17 18:51:45 +08:00
|
|
|
|
var ret = ExecuteAndWait(id, () =>
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
2023-05-17 18:51:45 +08:00
|
|
|
|
Notify($"Align");
|
|
|
|
|
_alignerDevice.DoAliger();
|
2023-03-03 15:42:13 +08:00
|
|
|
|
return true;
|
2023-05-17 18:51:45 +08:00
|
|
|
|
}, () => !_alignerDevice.IsBusy, timeout * 1000);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
|
|
|
|
if (ret.Item1)
|
|
|
|
|
{
|
|
|
|
|
if (ret.Item2 == Result.FAIL)
|
|
|
|
|
{
|
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
2023-05-17 18:51:45 +08:00
|
|
|
|
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
2023-03-03 15:42:13 +08:00
|
|
|
|
{
|
2023-05-17 18:51:45 +08:00
|
|
|
|
Stop($"Aligner Align Timeout, over {timeout} seconds");
|
2023-03-03 15:42:13 +08:00
|
|
|
|
throw (new RoutineFaildException());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw (new RoutineBreakException());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|