SicMultiplate/Modules/Mainframe/EFEMs/Routines/Base/EfemBaseRoutine.cs

809 lines
27 KiB
C#
Raw Normal View History

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.Device.Devices;
using Aitex.Core.RT.Device.Unit;
using Aitex.Core.RT.Event;
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.Aligners.HiWinAligner;
2023-03-03 15:42:13 +08:00
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.EFEM;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
using static MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase.RobotBaseDevice;
2023-04-13 15:35:13 +08:00
using IoInterLock = SicModules.Devices.IoInterLock;
2023-03-03 15:42:13 +08:00
2023-04-13 15:35:13 +08:00
namespace SicModules.EFEMs.Routines.Base
2023-03-03 15:42:13 +08:00
{
public class EfemBaseRoutine : ModuleRoutine, IRoutine
{
private RobotBaseDevice _waferRobot = null;
private RobotBaseDevice _trayRobot = null;
private IEFEM _efemDevice;
public IoSensor _loadTrayHomeSensor; //Tray定位
public IoSensor _loadWaferPlaced; //上下对射检测Wafer有无
public IoSensor _loadTrayPresence; //检测托盘有无
public IoSensor _cassAL6Inch; //6寸检测
public IoSensor _cassAR6Inch; //6寸检测
public IoSensor _cassBL6Inch; //6寸检测
public IoSensor _cassALWaferConvex; //凸片检测
public IoSensor _cassARWaferConvex; //凸片检测
public IoSensor _cassBLWaferConvex; //凸片检测
2023-04-13 15:35:13 +08:00
private IoInterLock _tmIoInterLock;
2023-03-03 15:42:13 +08:00
public IoLift4 _llLift;
public IoClaw _loadWaferClaw;
public IoLift4 _unLoadLift;
public IoClaw _unLoadWaferClaw;
private HwAlignerGuide _alignerDevice = null;
protected RobotBaseDevice WaferRobot
{
get { return _waferRobot; }
}
protected RobotBaseDevice TrayRobot
{
get { return _trayRobot; }
}
protected IEFEM EfemDevice
{
get { return _efemDevice; }
}
2023-03-13 17:37:55 +08:00
public EfemBaseRoutine() : base(ModuleName.EFEM.ToString())
2023-03-03 15:42:13 +08:00
{
_waferRobot = DEVICE.GetDevice<SicWaferRobot>($"WaferRobot.WaferRobot");
_trayRobot = DEVICE.GetDevice<SicTrayRobot>($"TrayRobot.TrayRobot");
_efemDevice = DEVICE.GetDevice<SicEFEM>($"EFEM.EFEM");
_loadTrayHomeSensor = DEVICE.GetDevice<IoSensor>($"TM.LoadTrayHomeSensor");
_alignerDevice = DEVICE.GetDevice<HwAlignerGuide>($"TM.HiWinAligner");
2023-03-03 15:42:13 +08:00
_loadWaferPlaced = DEVICE.GetDevice<IoSensor>($"TM.LLWaferPlaced");
_loadTrayPresence = DEVICE.GetDevice<IoSensor>($"TM.LLTrayPresence");
_cassBLWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassBLWaferConvexSensor");
_cassALWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassALWaferConvexSensor");
_cassARWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassARWaferConvexSensor");
_cassAL6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassALInch6Sensor");
_cassAR6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassARInch6Sensor");
_cassBL6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassBLInch6Sensor");
2023-04-13 15:35:13 +08:00
_tmIoInterLock = DEVICE.GetDevice<IoInterLock>("TM.IoInterLock");
2023-03-03 15:42:13 +08:00
_llLift= DEVICE.GetDevice<IoLift4>($"LoadLock.LLLift");
_unLoadLift= DEVICE.GetDevice<IoLift4>($"UnLoad.UnLoadLift");
_loadWaferClaw = DEVICE.GetDevice<IoClaw>($"LoadLock.LLWaferClaw");
_unLoadWaferClaw = DEVICE.GetDevice<IoClaw>($"UnLoad.UnLoadWaferClaw");
}
2023-03-03 15:42:13 +08:00
protected void CheckTraySensor(int id)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
if (SC.GetValue<bool>($"System.IsSimulatorMode"))
{
return true;
}
return _loadTrayPresence.Value;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Sensor[DI-32] check no tray");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void ClearRobortExtendToDO(int id)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
Notify("Clear RobortExtendTO DO");
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
return true;
});
}
protected void Pick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Pick from {source} {slot + 1} use Blade1 ");
if (!robot.Pick(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Pick failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("pick timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void ExtendForPick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"ExtendForPick from {source} {slot + 1} use Blade1 ");
if (!robot.CheckToPostMessage(RobotMsg.ExtendForPick, RobotArmEnum.Blade1, source.ToString(), slot))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"ExtendForPick failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop(string.Format("ExtendForPick timeout, can not complete in {0} seconds", timeout));
robot.Abort();
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void ExtendForPlace(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"ExtendForPlace to {source} {slot + 1} use Blade1 ");
if (!robot.CheckToPostMessage(RobotMsg.ExtendForPlace, MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"ExtendForPlace failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop(string.Format("ExtendForPlace timeout, can not complete in {0} seconds", timeout));
robot.Abort();
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void RobotActionComplete(int id, RobotBaseDevice robot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Robot Action Complete ");
if (!robot.CheckToPostMessage(RobotMsg.ActionDone))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Robot Action failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop(string.Format("Robot Action timeout, can not complete in {0} seconds", timeout));
robot.Abort();
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void Place(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Place wafer to {source} {slot + 1} use Blade1 ");
if (!robot.Place(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, source.ToString(), slot))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Place failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void CheckWaferStatuBeforePick(int id, RobotBaseDevice robot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Check Wafer Status Before Pick");
if (!robot.ExecuteCommand(new object[] { true }))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
{
if (WaferManager.Instance.CheckHasWafer(robot.Name, 0))
{
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Wafer!");
return null;
}
return true;
}
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Place failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void CheckWaferStatuAfterPlace(int id, RobotBaseDevice robot,int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Check Wafer Status After Place");
if (!robot.ExecuteCommand(new object[] { true}))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
{
if (WaferManager.Instance.CheckHasWafer(robot.Name, 0))
{
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Place Finished and Robot Check Has Wafer!");
return null;
}
return true;
}
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Place failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void CheckTrayStatuBeforePick(int id, RobotBaseDevice robot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Check Tray Status Before Pick");
if (!robot.ExecuteCommand(new object[] { true }))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
{
if (WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Name), 0))
{
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Tray!");
return null;
}
return true;
}
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Place failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void Map(int id, RobotBaseDevice robot, ModuleName source, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Mapping wafer {source}");
if (!robot.WaferMapping(source))
{
robot.IsBusy = false;
return false;
}
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
Stop($"Mapping failed, error {robot.ErrorCode}");
robot.Abort();
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop(string.Format("Mapping timeout, can not complete in {0} seconds", timeout));
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void CheckRobotReady(int id, RobotBaseDevice robot, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"{robot.Name} Check robot ready");
return true;
}, () =>
{
if (robot.IsReady())
return true;
return false;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT)
{
robot.Abort();
Stop($"{robot.Name} timeout, can not complete in {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
public void RobotHomeExcute(int id, RobotBaseDevice robot, int timeout)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
Notify($"{robot.Name} Execute home");
if (!robot.Home(null))
{
EV.PostAlarmLog(Module, $"{robot.Name} Can not home robot");
return false;
}
return true;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
robot.Abort();
Stop($"{robot.Name} home timeout over {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
//关闭Aligner真空
protected void CloseVacuum(int id, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Close Vacuum");
_alignerDevice.CloseVacuum();
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 Close Vacuum Timeout, over {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void AlignerMoveToRobotPutPalce(int id, int timeout)
2023-03-03 15:42:13 +08:00
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"Move to Robot Put Place");
_alignerDevice.MoveToRobotPutPlace();
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
2023-03-03 15:42:13 +08:00
{
Stop($"Aligner Move to Robot Put Place Timeout, over {timeout} seconds");
2023-03-03 15:42:13 +08:00
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
//检查是否有Wafer
protected void CheckHaveWafer(int id, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"check wafer in position");
2023-03-03 15:42:13 +08:00
_alignerDevice.CheckWaferLoad();
2023-03-03 15:42:13 +08:00
return true;
}, () =>
{
if (!_alignerDevice.IsBusy)
{
if (_alignerDevice.HaveWafer)
{
Stop($"Check result : aligner have wafer, can not place to aligner");
2023-03-03 15:42:13 +08:00
return null;
}
else
{
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());
}
}
protected void SetWaferRobortExtendToDO(int id, ModuleName target, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify("Set RobortExtendTO DO");
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
{
if (!_tmIoInterLock.SetWaferRobotExtendLoadEnable(true, out string reasen))
{
Notify(reasen);
return false;
}
}
else if (target == ModuleName.UnLoad)
{
if (!_tmIoInterLock.SetWaferRobotExtendUnLoadEnable(true, out string reasen))
{
Notify(reasen);
return false;
}
}
return true;
}, () =>
{
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
{
return _tmIoInterLock.DiATMRobotExtendLoadLSideEnableFB;
}
else if (target == ModuleName.UnLoad)
{
return _tmIoInterLock.DiATMRobotExtendUnloadEnableFB;
}
return true;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop($"Set Robot extend to Do timeout over {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void SetTrayRobortExtendToDO(int id, ModuleName target, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify("Set RobortExtendTO DO");
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
{
if (!_tmIoInterLock.SetTrayRobotExtendLoadEnable(true, out string reasen))
{
Notify(reasen);
return false;
}
}
return true;
}, () =>
{
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
{
return _tmIoInterLock.DiATMRobotExtendLoadRSideEnableFB;
}
return true;
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop($"Set Robot extend to Do timeout over {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
protected void CheckLoadTrayPresence(int id)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
if (SC.GetValue<bool>("LoadLock.TrayPresenceCheckEnable"))
{
if (!_loadTrayPresence.Value)
{
EV.PostAlarmLog(Module, $"check load Tray Presence sensor false,no Tray in load");
return false;
}
}
return true;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
}
}