424 lines
16 KiB
C#
424 lines
16 KiB
C#
using Aitex.Core.RT.Device;
|
||
using Aitex.Core.RT.Device.Devices;
|
||
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.MFCs;
|
||
using SicModules.PMs.Routines.Base;
|
||
|
||
namespace SicModules.PMs.Routines
|
||
{
|
||
class PMPostTransferRoutine : PMBaseRoutine
|
||
{
|
||
enum RoutineStep
|
||
{
|
||
SetUpLimit,
|
||
SetBlockOn,
|
||
Delay,
|
||
WaitStatusCorrect,
|
||
SetBlockOff,
|
||
EnableRotation,
|
||
EnableHeater,
|
||
SetRotation1,
|
||
WaitRotation1,
|
||
SetTC1Mode,
|
||
SetTC1Ratio,
|
||
SetTC1Ref,
|
||
SetTC2Mode,
|
||
SetTC2Ratio,
|
||
SetTC2Ref,
|
||
SetChamberPressure,
|
||
EnableTC1,
|
||
EnableTC2,
|
||
SetServoUp,
|
||
SetScrReset,
|
||
|
||
TimeDelay1,
|
||
TimeDelay2,
|
||
TimeDelay3,
|
||
TimeDelay4,
|
||
TimeDelay5,
|
||
TimeDelay6,
|
||
TimeDelay7,
|
||
TimeDelay8,
|
||
TimeDelay9,
|
||
TimeDelay10,
|
||
TimeDelay11,
|
||
TimeDelay12,
|
||
TimeDelay13,
|
||
TimeDelay14,
|
||
TimeDelay15,
|
||
|
||
SetV31,
|
||
SetV32,
|
||
SetV35V36,
|
||
SetGroupA,
|
||
SetGroupB,
|
||
SetGroupC,
|
||
SetGroupE,
|
||
SetGroupF,
|
||
SetGroupH,
|
||
SetGroupK,
|
||
SetGroupD,
|
||
SetGroupG,
|
||
SetM1toM17,
|
||
SetPC,
|
||
SetM18toM40,
|
||
SetEPV2,
|
||
SetGroupJ,
|
||
SetV72,
|
||
SetV25,
|
||
SetPressureDown,
|
||
SetTVto300
|
||
}
|
||
|
||
bool hasWafer;
|
||
|
||
private IoThrottleValve2 _IoThrottle;
|
||
private double _throttleFinalPressure = 300;//蝶阀最终调整对的压力
|
||
private double _pmPressureMaxDiff; //蝶阀与目标压力的差值范围(认为调整到位了)
|
||
private int _throttleTimeout; //蝶阀调整到指定压力的超时时间
|
||
|
||
//private int _timeout;
|
||
private int _rotationSpeed = 60;
|
||
|
||
private bool _psuHeatEnable = false; //是否启用PSU 加热
|
||
private int _psuHeatMode = 0;
|
||
//private float _psuPowerRef = 0;
|
||
private float _psuL1Ratio = 0;
|
||
private float _psuL2Ratio = 0;
|
||
private float _psuL3Ratio = 0;
|
||
|
||
private bool _scrHeatEnable = false; //是否启用SCR 加热
|
||
private int _scrHeatMode = 0;
|
||
//private float _scrPowerRef = 0;
|
||
private float _scrL1Ratio = 0;
|
||
private float _scrL2Ratio = 0;
|
||
private float _scrL3Ratio = 0;
|
||
|
||
private int _IoValueOpenCloseTimeout = 10; //开关超时时间
|
||
|
||
private double _targetPressure;
|
||
private PMServoToPressure _pmServoToPressure;
|
||
private bool _needEnableHeat = true;
|
||
|
||
private int _servoUpDelay;
|
||
|
||
//private NAISServo servo;
|
||
|
||
public PMPostTransferRoutine(ModuleName module, PMModule pm1) : base(module, pm1)
|
||
{
|
||
Module = module.ToString();
|
||
Name = "Post Transfer Routine";
|
||
|
||
_pmServoToPressure = new PMServoToPressure(module, pm1);
|
||
}
|
||
|
||
|
||
public void Init(bool needEnableHeat)
|
||
{
|
||
_needEnableHeat = needEnableHeat;
|
||
}
|
||
|
||
public void Init(float basePressure, int ventDelayTime)
|
||
{
|
||
|
||
}
|
||
|
||
|
||
public override Result Start(params object[] objs)
|
||
{
|
||
|
||
_IoThrottle = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV");
|
||
_rotationSpeed = SC.GetValue<int>($"PM.{Module}.ProcessIdle.RotationSpeed");
|
||
|
||
_pmPressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
|
||
_throttleFinalPressure = SC.GetValue<double>($"PM.{Module}.ProcessIdle.FinalPressure");
|
||
_throttleTimeout = SC.GetValue<int>($"PM.{Module}.ThrottlePressureTimeout");
|
||
|
||
_psuHeatEnable = SC.GetValue<bool>($"PM.{Module}.ProcessIdle.PSUHeaterEnable");
|
||
_psuHeatMode = SC.GetValue<int>($"PM.{Module}.ProcessIdle.PSUHeaterMode");
|
||
//_psuPowerRef = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUPowerRef");
|
||
_psuL1Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUInnerRatio");
|
||
_psuL2Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUMiddleRatio");
|
||
_psuL3Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUOuterRatio");
|
||
|
||
_scrHeatEnable = SC.GetValue<bool>($"PM.{Module}.ProcessIdle.SCRHeaterEnable");
|
||
_scrHeatMode = SC.GetValue<int>($"PM.{Module}.ProcessIdle.SCRHeaterMode");
|
||
//_scrPowerRef = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRPowerRef");
|
||
_scrL1Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRUpperRatio");
|
||
_scrL2Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRMiddleRatio");
|
||
_scrL3Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRLowerRatio");
|
||
_targetPressure = SC.GetValue<double>($"PM.{Module}.ProcessIdle.FinalPressure");
|
||
|
||
_servoUpDelay = SC.GetValue<int>($"PM.{Module}.PreProcess.ServoBeforeUpDelay");
|
||
|
||
_pmServoToPressure.Init(_targetPressure);
|
||
|
||
|
||
hasWafer = WaferManager.Instance.CheckHasWafer(Module, 0);
|
||
|
||
Reset();
|
||
|
||
Notify("Start");
|
||
return Result.RUN;
|
||
}
|
||
|
||
|
||
public override Result Monitor()
|
||
{
|
||
try
|
||
{
|
||
//1、 打开 V31(H2.Supply)、 V32(Ar.Supply)。
|
||
SetIoValueByGroup((int)RoutineStep.SetV31, IoGroupName.V31, true, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetV32, IoGroupName.V32, true, _IoValueOpenCloseTimeout);
|
||
//2、 打开 V35(H2N2.Line1)、 V36(H2N2.Line2),关闭 B/ C / E / F / H / KValves,打开 D/ G Valves。
|
||
SetIoValueByGroup((int)RoutineStep.SetV35V36, IoGroupName.V35V36, true, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupB, IoGroupName.B, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupC, IoGroupName.C, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupE, IoGroupName.E, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupF, IoGroupName.F, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupH, IoGroupName.H, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupK, IoGroupName.K, false, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupA, IoGroupName.A, true, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupD, IoGroupName.D, true, _IoValueOpenCloseTimeout);
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupG, IoGroupName.G, true, _IoValueOpenCloseTimeout);
|
||
//3、 M1 - M17 设定为 default 值,所有 PC 设定为 default 值(PC1 - PC9)。
|
||
SetMfcToDefaultByGroup((int)RoutineStep.SetM1toM17, MfcGroupName.M1toM17, 0);
|
||
SetPcToDefault((int)RoutineStep.SetPC, _lstPcList);
|
||
//4、 M18 - M40(除 M30\M34\M39)) MFC 3s ramp 到 default 值。
|
||
SetMfcToDefaultByGroup((int)RoutineStep.SetM18toM40, MfcGroupName.M18toM40No303439, 3);
|
||
//5、 打开 EPV2。
|
||
SetIoValueByGroup((int)RoutineStep.SetEPV2, IoGroupName.EPV2, true, _IoValueOpenCloseTimeout);
|
||
//6、打开 J Valves
|
||
SetIoValueByGroup((int)RoutineStep.SetGroupJ, IoGroupName.J, true, _IoValueOpenCloseTimeout);
|
||
//7、打开 V72(GasBox.Vent.Pump) 关闭 V25(GasBox.Vent.Bypass), 反应腔压力伺服到300mbar(可配置)
|
||
SetIoValueByGroup((int)RoutineStep.SetV72, IoGroupName.VentPump, true, _IoValueOpenCloseTimeout);
|
||
TimeDelay((int)RoutineStep.TimeDelay5, 1);
|
||
SetIoValueByGroup((int)RoutineStep.SetV25, IoGroupName.V25, false, _IoValueOpenCloseTimeout);
|
||
SetThrottleToTargetAndNoWait((int)RoutineStep.SetPressureDown, _IoThrottle, _throttleFinalPressure);
|
||
WaitThrottleToPressureAndSetMfcSpecial((int)RoutineStep.SetTVto300, _IoThrottle, _throttleFinalPressure, _pmPressureMaxDiff, _throttleTimeout);
|
||
//8、设定转速(可配置)
|
||
EnableRotation((int)RoutineStep.EnableRotation, 5);
|
||
SetRotationValveAndNoWait((int)RoutineStep.SetRotation1, _rotationSpeed);
|
||
|
||
//9、加热使能(PSU 和 SCR)(可配置)
|
||
if (_psuHeatEnable && _needEnableHeat)
|
||
{
|
||
SetPSUEnable((int)RoutineStep.EnableTC1, true, 5);
|
||
|
||
SetPSUHeatMode((int)RoutineStep.SetTC1Mode, _psuHeatMode);
|
||
TimeDelay((int)RoutineStep.TimeDelay9, 1);
|
||
SetPSUHeatRatio((int)RoutineStep.SetTC1Ratio, _psuL1Ratio, _psuL2Ratio, _psuL3Ratio);
|
||
}
|
||
if (_scrHeatEnable && _needEnableHeat)
|
||
{
|
||
SetSCRReset((int)RoutineStep.SetScrReset);
|
||
TimeDelay((int)RoutineStep.TimeDelay10, 1);
|
||
|
||
SetSCREnable((int)RoutineStep.EnableTC2, true, 5);
|
||
|
||
SetSCRHeatMode((int)RoutineStep.SetTC2Mode, _scrHeatMode);
|
||
TimeDelay((int)RoutineStep.TimeDelay11, 1);
|
||
SetSCRHeatRatio((int)RoutineStep.SetTC2Ratio, _scrL1Ratio, _scrL2Ratio, _scrL3Ratio);
|
||
}
|
||
|
||
TimeDelay((int)RoutineStep.TimeDelay8, 1);
|
||
WaitRotationValve((int)RoutineStep.WaitRotation1, _rotationSpeed, true, _rotationSpeed / 2);
|
||
}
|
||
catch (RoutineBreakException)
|
||
{
|
||
return Result.RUN;
|
||
}
|
||
catch (RoutineFaildException)
|
||
{
|
||
return Result.FAIL;
|
||
}
|
||
|
||
Notify("Finished");
|
||
|
||
return Result.DONE;
|
||
}
|
||
|
||
//private void ServoUpLimit(int id, PMModuleBase pm, int timeout)
|
||
//{
|
||
// Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
// {
|
||
// Notify($"Run {pm.Name} set Block No High.");
|
||
|
||
// //if (!servo.SetBlockNoHigh())
|
||
// //{
|
||
// // Stop(reason);
|
||
// // return false;
|
||
// //}
|
||
// servo.SetBlockNoHigh();
|
||
// return true;
|
||
// }, () =>
|
||
// {
|
||
// if (servo.AlarmStatus)
|
||
// {
|
||
// Stop($"{pm.Name} Servo in error State.");
|
||
// return null;
|
||
// }
|
||
// if (!servo.IsBusy)
|
||
// return true;
|
||
|
||
// return false;
|
||
|
||
// }, timeout * 1000);
|
||
|
||
// if (ret.Item1)
|
||
// {
|
||
// if (ret.Item2 == Result.FAIL)
|
||
// {
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
// {
|
||
// Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else
|
||
// throw (new RoutineBreakException());
|
||
// }
|
||
//}
|
||
//private void ServoBlockOn(int id, PMModuleBase pm, int timeout)
|
||
//{
|
||
// Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
// {
|
||
// Notify($"Run {pm.Name} set Stb On.");
|
||
|
||
// //if (!servo.SetBlockNoHigh())
|
||
// //{
|
||
// // Stop(reason);
|
||
// // return false;
|
||
// //}
|
||
// servo.SetStbOn();
|
||
// return true;
|
||
// }, () =>
|
||
// {
|
||
// if (servo.AlarmStatus)
|
||
// {
|
||
// Stop($"{pm.Name} Servo in error State.");
|
||
// return null;
|
||
// }
|
||
// if (!servo.IsBusy)
|
||
// {
|
||
// PMDevice.ServoStatus = ServoStatus.Uping;
|
||
// return true;
|
||
// }
|
||
|
||
// return false;
|
||
|
||
// }, timeout * 1000);
|
||
|
||
// if (ret.Item1)
|
||
// {
|
||
// if (ret.Item2 == Result.FAIL)
|
||
// {
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
// {
|
||
// Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else
|
||
// throw (new RoutineBreakException());
|
||
// }
|
||
//}
|
||
//private void ServoBlockOff(int id, PMModuleBase pm, int timeout)
|
||
//{
|
||
// Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
// {
|
||
// Notify($"Run {pm.Name} set Stb Off.");
|
||
|
||
// //if (!servo.SetBlockNoHigh())
|
||
// //{
|
||
// // Stop(reason);
|
||
// // return false;
|
||
// //}
|
||
// servo.SetStbOff();
|
||
// return true;
|
||
// }, () =>
|
||
// {
|
||
// if (servo.AlarmStatus)
|
||
// {
|
||
// Stop($"{pm.Name} Servo in error State.");
|
||
// return null;
|
||
// }
|
||
// if (!servo.IsBusy)
|
||
// return true;
|
||
|
||
// return false;
|
||
|
||
// }, timeout * 1000);
|
||
|
||
// if (ret.Item1)
|
||
// {
|
||
// if (ret.Item2 == Result.FAIL)
|
||
// {
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
// {
|
||
// Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else
|
||
// throw (new RoutineBreakException());
|
||
// }
|
||
//}
|
||
//private void WaitStatusCorrect(int id, PMModule pm, int timeout)
|
||
//{
|
||
// Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
// {
|
||
// Notify($"Run {pm.Name} Wait, Wait Status Correct");
|
||
|
||
// return true;
|
||
// }, () =>
|
||
// {
|
||
// if (servo.AlarmStatus)
|
||
// {
|
||
// Stop($"{pm.Name} Servo in error State error");
|
||
// return null;
|
||
// }
|
||
// if ((!servo.MotorBusy && servo.PositionComplete) && pm.ConfinementRing.IsUp)
|
||
// {
|
||
// PMDevice.ServoStatus = ServoStatus.Up;
|
||
// return true;
|
||
// }
|
||
// return false;
|
||
|
||
// }, timeout * 1000);
|
||
|
||
// if (ret.Item1)
|
||
// {
|
||
// if (ret.Item2 == Result.FAIL)
|
||
// {
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
// {
|
||
// Stop($"{pm.Name} vent timeout, over {timeout} seconds");
|
||
// throw (new RoutineFaildException());
|
||
// }
|
||
// else
|
||
// throw (new RoutineBreakException());
|
||
// }
|
||
//}
|
||
|
||
public override void Abort()
|
||
{
|
||
if (!PmDevice.StopVent(out string reason))
|
||
{
|
||
EV.PostWarningLog(Module, reason);
|
||
}
|
||
|
||
Stop("aborted");
|
||
}
|
||
}
|
||
}
|