Sic08/Modules/Mainframe/EFEMs/Routines/EfemSlitValveRoutine.cs

300 lines
11 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.Event;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Equipment;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UnLoad;
2023-04-13 15:35:13 +08:00
using SicModules.EFEMs.Routines.Base;
using SicModules.LLs;
using SicModules.LLs.Routines;
using SicModules.TMs;
using SicModules.UnLoads;
using SicModules.UnLoads.Routines;
2023-03-03 15:42:13 +08:00
2023-04-13 15:35:13 +08:00
namespace SicModules.EFEMs.Routines
2023-03-03 15:42:13 +08:00
{
public class EfemSlitValveRoutine : EfemBaseRoutine
{
enum RoutineStep
{
ServoRoutine,
LiftRoutine,
CheckPressureCondition,
CheckPressure,
SetSlitValve,
CheckPressureCondition2,
TimeDlay1
}
private int _motionTimeout = 30;
private ModuleName _paramTarget; //目标腔体
private ModuleName _robot; //机械手
private bool _paramIsOpen; //是否开门
private bool _bothPressureIsATM; //判断两边压力是否都为ATM
private SicTM _tm;
private LoadLock _loadLock;
private UnLoad _unLoad;
private LoadLockServoToRoutine _llServoToRoutine;
private UnLoadServoToRoutine _unLoadServoToRoutine;
private LoadLockLiftRoutine _llLiftRoutine;
private UnLoadLiftRoutine _unLoadLiftRoutine;
private double _maxPressureDiffOpenSlitValve = SC.GetValue<double>("EFEM.MaxPressureDiffOpenSlitValve");
public void Init(ModuleName targetModule,ModuleName robot, bool isOpen)
{
_paramTarget = targetModule;
_robot = robot;
_paramIsOpen = isOpen;
Name = isOpen ? "Open Slit Valve" : "Close Slit Valve";
2023-03-03 15:42:13 +08:00
}
public EfemSlitValveRoutine()
{
Module = ModuleName.EFEM.ToString();
Name = "EFEMSlitValue";
2023-03-03 15:42:13 +08:00
_tm = DEVICE.GetDevice<SicTM>($"{ ModuleName.System.ToString()}.{ ModuleName.TM.ToString()}");
_loadLock= DEVICE.GetDevice<SicLoadLock>($"{ ModuleName.LoadLock.ToString()}.{ ModuleName.LoadLock.ToString()}");
_unLoad = DEVICE.GetDevice<SicUnLoad>($"{ ModuleName.UnLoad.ToString()}.{ ModuleName.UnLoad.ToString()}");
_llServoToRoutine = new LoadLockServoToRoutine(ModuleName.LoadLock);
_unLoadServoToRoutine = new UnLoadServoToRoutine(ModuleName.UnLoad);
_llLiftRoutine = new LoadLockLiftRoutine();
_unLoadLiftRoutine = new UnLoadLiftRoutine();
}
public override Result Start(params object[] objs)
{
Reset();
//只有LoadLock和UnLoad需要开门
if (_robot == ModuleName.WaferRobot)
{
if (_paramTarget != ModuleName.LoadLock && _paramTarget != ModuleName.Load && _paramTarget != ModuleName.UnLoad)
{
return Result.DONE;
}
}
else if (_robot == ModuleName.TrayRobot)
{
if (_paramTarget != ModuleName.LoadLock)
{
return Result.DONE;
}
}
else
{
return Result.DONE;
}
if (_paramIsOpen)
{
if (EfemDevice.CheckSlitValveOpen(_paramTarget, _robot))
{
return Result.DONE;
}
//判断TM到LoadLock或者UnLoad的门是否关上
if (!_tm.CheckSlitValveClose(_paramTarget))
{
EV.PostWarningLog(Module, $"can not open slit valve {_paramTarget}, {_paramTarget} to TM slit valve not closed, can not open at same time");
return Result.FAIL;
}
if (!EfemDevice.CheckSlitValveClose(ModuleName.LoadLock, ModuleName.WaferRobot)) //此门是必须要关上的
{
EV.PostWarningLog(Module, $"can not open slit valve {_paramTarget}, {ModuleName.LoadLock} to Efem slit valve not closed, can not open at same time");
return Result.FAIL;
}
if (!EfemDevice.CheckSlitValveClose(ModuleName.UnLoad, _robot))
{
EV.PostWarningLog(Module, $"can not open slit valve {_paramTarget}, {ModuleName.UnLoad} to Efem slit valve not closed, can not open at same time");
return Result.FAIL;
}
if (!EfemDevice.CheckSlitValveClose(ModuleName.LoadLock, _robot))
{
EV.PostWarningLog(Module, $"can not open slit valve {_paramTarget}, {ModuleName.LoadLock} to Efem slit valve not closed, can not open at same time");
return Result.FAIL;
}
_motionTimeout = SC.GetValue<int>("EFEM.SlitValveMotionTimeout");
_llServoToRoutine.Init(SC.GetValue<double>("LoadLock.AtmPressureBase"));
_unLoadServoToRoutine.Init(SC.GetValue<double>("UnLoad.AtmPressureBase"));
_llLiftRoutine.Init(false);
_unLoadLiftRoutine.Init(false);
}
else
{
if (EfemDevice.CheckSlitValveClose(_paramTarget, _robot))
{
return Result.DONE;
}
}
Notify("Start");
return Result.RUN;
}
public override Result Monitor()
{
try
{
//开门之前需要对两边腔体进行气压调节,降Lift
if (_paramIsOpen)
{
if (_paramTarget == ModuleName.LoadLock)
{
CheckPressureConditionATM((int)RoutineStep.CheckPressureCondition, _paramTarget);//先判断Load腔是否在大气因为EFEM始终在大气
if (!_bothPressureIsATM)
{
ExecuteRoutine((int)RoutineStep.ServoRoutine, _llServoToRoutine);
ExecuteRoutine((int)RoutineStep.LiftRoutine, _llLiftRoutine);
}
}
else if (_paramTarget == ModuleName.UnLoad)
{
CheckPressureConditionATM((int)RoutineStep.CheckPressureCondition, _paramTarget);//先判断UnLoad腔是否在大气
if (!_bothPressureIsATM)
{
ExecuteRoutine((int)RoutineStep.ServoRoutine, _unLoadServoToRoutine);
ExecuteRoutine((int)RoutineStep.LiftRoutine, _unLoadLiftRoutine);
}
}
CheckPressureCondition((int)RoutineStep.CheckPressureCondition2,_paramTarget);
}
SetSlitValve((int)RoutineStep.SetSlitValve, _paramTarget, _robot, _paramIsOpen, _motionTimeout);
TimeDelay((int)RoutineStep.TimeDlay1, 1);
}
catch (RoutineBreakException)
{
return Result.RUN;
}
catch (RoutineFaildException)
{
return Result.FAIL;
}
Notify("Finished");
return Result.DONE;
}
public void CheckPressureConditionATM(int id, ModuleName target)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
Notify($"check pressure condition to open {target} slit valve");
double targetPressure = 0.0;
if (target == ModuleName.LoadLock)
{
targetPressure = _loadLock.ChamberPressure;
}
else
{
targetPressure = _unLoad.ChamberPressure;
}
_bothPressureIsATM = Math.Abs(EfemDevice.AtmPressureBase - targetPressure) <= _maxPressureDiffOpenSlitValve;
return true;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
public void CheckPressureCondition(int id, ModuleName target)
{
Tuple<bool, Result> ret = Execute(id, () =>
{
Notify($"check {target} pressure is atm");
double targetPressure = 0.0;
if (target == ModuleName.LoadLock)
{
targetPressure = _loadLock.ChamberPressure;
}
else
{
targetPressure = _unLoad.ChamberPressure;
}
if (Math.Abs(EfemDevice.AtmPressureBase - targetPressure) > _maxPressureDiffOpenSlitValve)
{
Stop($"pressure difference {Math.Abs(EfemDevice.AtmPressureBase - targetPressure):F3} between Efem and {target} exceed tolerance {_maxPressureDiffOpenSlitValve}");
return false;
}
return true;
});
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
public void SetSlitValve(int id, ModuleName module,ModuleName _robort, bool isOpen, int timeout)
{
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
{
Notify($"set slit valve {module} " + (isOpen ? "Open" : "Close"));
if (!EfemDevice.SetSlitValve(module, _robort, isOpen, out string reason))
{
Stop(reason);
return false;
}
return true;
}, () =>
{
return isOpen ? EfemDevice.CheckSlitValveOpen(module, _robort) : EfemDevice.CheckSlitValveClose(module, _robort);
}, timeout * 1000);
if (ret.Item1)
{
if (ret.Item2 == Result.FAIL)
{
throw (new RoutineFaildException());
}
else if (ret.Item2 == Result.TIMEOUT) //timeout
{
Stop($"can not complete in {timeout} seconds");
throw (new RoutineFaildException());
}
else
throw (new RoutineBreakException());
}
}
}
}