using System; using Aitex.Core.Common; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using JetVirgoPM.Devices; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using Aitex.Sorter.Common; namespace JetVirgoPM.PMs.Routines { class PMPrepareTransferRoutine : PMRoutineBase, IStepRoutine { enum RoutineStep { LiftUpDown, Vent, VentDelay, SetGuidePin, CheckCoolantTemp1, CheckCoolantTemp2, CheckTemp1, CheckTemp2, CheckLETemp, SetSlitDoor, SlitDoorDelay, PrepareTransferPlace, PrepareTransferPick, kEnd } private EnumTransferType _TransferType; private EnumDualPM _pos; private int _timeout; private readonly VentRoutine _ventRoutine; private WaferSize _ws; private double _temp; private double _tolerance; private double _Chiller1OffsetTemp = 0.0f; private double _Chiller2OffsetTemp = 0.0f; private double _TargetTemp1 = 0.0f; private double _TargetTemp2 = 0.0f; private bool _enableCheckTemp = false; private int _checkChamberTempTimeout = 60; private bool _isATMMode; public bool _Chamber1Disabled; public bool _Chamber2Disabled; private bool _enableChiller1; private bool _enableChiller2; private bool _enableLE1; private bool _enableLE2; private bool _isVented = false; public bool GuidePinInstalled; public PMPrepareTransferRoutine(JetDualPM chamber, VentRoutine _vRoutine) : base(chamber) { Name = "PrepareTransfer"; _ventRoutine = _vRoutine; } public RState Init(EnumTransferType type, EnumDualPM pos, WaferSize size, double temp1, double temp2, bool EnableCheckTemp) { if (type == EnumTransferType.Place) { Name = $"Prepare Place {_ws}"; } else if (type == EnumTransferType.Pick) { size = WaferManager.Instance.GetWafer(_chamber.Module, pos == EnumDualPM.Left ? 0 : 1).Size; Name = $"Prepare Pick {_ws}"; } _TargetTemp1 = temp1; _TargetTemp2 = temp2; _enableCheckTemp = EnableCheckTemp; _pos = pos; _TransferType = type; _ws = size; return RState.End; } public RState Init(EnumTransferType type, int[] slot, double temp1, double temp2, bool EnableCheckTemp, int handSlot = -1, EnumDualPM autoPos= EnumDualPM.None) { EnumDualPM pos = (slot.Length > 1) ? EnumDualPM.Both : (slot[0] == 0) ? EnumDualPM.Left : EnumDualPM.Right; if(autoPos != EnumDualPM.None) { pos = autoPos; } if (SC.IsDoubleFork) pos = EnumDualPM.Both; WaferSize ws = WaferSize.WS0; if(handSlot != -1 && type == EnumTransferType.Place) { Hand hand = (Hand)handSlot; if (hand == Hand.Both) { ws = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)Hand.Blade1).Size; } else { ws = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)hand).Size; } } else if (type == EnumTransferType.Pick) { if(pos == EnumDualPM.Left || pos == EnumDualPM.Both) { ws = WaferManager.Instance.GetWafer(_chamber.Module, (int)EnumDualPM.Left - 1).Size; } else if(pos == EnumDualPM.Right) { ws = WaferManager.Instance.GetWafer(_chamber.Module, (int)EnumDualPM.Right - 1).Size; } } _TargetTemp1 = temp1; _TargetTemp2 = temp2; _enableCheckTemp = EnableCheckTemp; return Init(type, pos, ws, temp1, temp2, EnableCheckTemp); } public RState Start(params object[] objs) { Reset(); _timeout = SC.GetValue($"{Module}.PrepareTransferTimeout"); _Chamber1Disabled = SC.GetValue($"System.SetUp.{Module}Chamber1Disabled.IsInstalled"); _Chamber2Disabled = SC.GetValue($"System.SetUp.{Module}Chamber2Disabled.IsInstalled"); _enableChiller1 = SC.GetValue($"{Module}.Chiller1.EnableChiller"); _enableChiller2 = SC.GetValue($"{Module}.Chiller2.EnableChiller"); GuidePinInstalled = SC.GetValue($"{Module}.GuidePin.IsInstalled"); if(GuidePinInstalled && _ws == WaferSize.WS0) { Stop($"GuidePin 开启后,检查到Wafer size is {_ws.ToString()}"); return RState.Failed; } _checkChamberTempTimeout = SC.GetValue($"{Module}.CheckChamberTempTimeout"); _temp = SC.GetValue($"{Module}.ChamberBaseTemperatureThreshold"); _tolerance = SC.GetValue($"System.MaxTemperatureToleranceToTarget"); _Chiller1OffsetTemp = SC.GetValue($"{Module}.Chiller1.ChillerTemperatureOffset"); _Chiller2OffsetTemp = SC.GetValue($"{Module}.Chiller2.ChillerTemperatureOffset"); if (CheckAlreadyReadyForTransfer()) { return RState.End; } _isATMMode = SC.IsATMMode; if (_isATMMode && !_chamber.CheckAtm()) { Stop($"Running in ATMmode,{_chamber.DeviceID} not in atmos now!"); return RState.Failed; } Notify($"开始, 准备 {(_TransferType == EnumTransferType.Place ? "放" : _TransferType == EnumTransferType.Pick ? "取" : "动作未知")}{_ws} 寸片, "); _enableLE1 = true; _enableLE2 = true; return Runner.Start(_chamber.Module.ToString(), Name); } public RState Monitor() { Runner.Run(RoutineStep.Vent, Vent, CheckVent) .Run(RoutineStep.CheckCoolantTemp1, SetCoolant1Temp, CheckCoolant1Temp, _checkChamberTempTimeout * 1000) .Run(RoutineStep.CheckCoolantTemp2, SetCoolant2Temp, CheckCoolant2Temp, _checkChamberTempTimeout * 1000) .Run(RoutineStep.CheckLETemp, SetLETemp, CheckLETemp, _checkChamberTempTimeout * 1000) .Run(RoutineStep.CheckTemp1, SetLETemp1, CheckLETemp1, _checkChamberTempTimeout * 1000) .Run(RoutineStep.CheckTemp2, SetLETemp2, CheckLETemp2, _checkChamberTempTimeout * 1000) .Run(RoutineStep.PrepareTransferPlace, PMPreparePlace, CheckPMPreparePlace, _timeout * 1000) .Run(RoutineStep.PrepareTransferPick, PMPreparePick, CheckPMPreparePick, _timeout * 1000) .End(RoutineStep.kEnd, EndFunc, _delay_0s); return Runner.Status; } public override void Abort() { } bool Vent() { _isVented = SC.IsATMMode || _chamber.CheckSlitDoor1Open() || _chamber.CheckSlitDoor2Open(); if (!_isVented) { var status = _ventRoutine.Start(); _isVented = status == RState.End; if (!_isVented) return status == RState.Running; } return _isVented; } bool CheckVent() { if (_isVented) return true; var status = _ventRoutine.Monitor(); if (status == RState.End) return true; else if (status == RState.Failed || status == RState.Timeout) { Runner.Stop($"Vent failed."); return true; } return false; } bool SetCoolant1Temp() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableCheckTemp && !_Chamber1Disabled && _TargetTemp1 > 0 && _enableChiller1) { _enableLE1 = false; return SetCoolant1Temp(_TargetTemp1, _Chiller1OffsetTemp, _tolerance); } return true; } bool CheckCoolant1Temp() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableCheckTemp && !_Chamber1Disabled && _TargetTemp1 > 0 && _enableChiller1) { return CheckCoolant1Temp(_TargetTemp1, _Chiller1OffsetTemp, _tolerance); } return true; } bool SetCoolant2Temp() { if(_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableCheckTemp && !_Chamber2Disabled && _TargetTemp2 > 0 && _enableChiller2) { _enableLE2 = false; return SetCoolant2Temp(_TargetTemp2, _Chiller2OffsetTemp, _tolerance); } return true; } bool CheckCoolant2Temp() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableCheckTemp && !_Chamber2Disabled && _TargetTemp2 > 0 && _enableChiller2) { return CheckCoolant2Temp(_TargetTemp2, _Chiller2OffsetTemp, _tolerance); } return true; } bool SetLETemp() { if(_TransferType == EnumTransferType.Place && !SC.IsATMMode && (_enableLE1 && !_Chamber1Disabled && _TargetTemp1 > 0) && (_enableLE2 && !_Chamber2Disabled && _TargetTemp2 > 0)) { return SetLETemp(_TargetTemp1, _TargetTemp2, _tolerance, _enableLE1, _enableLE2); } return true; } bool CheckLETemp() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && (_enableLE1 && !_Chamber1Disabled && _TargetTemp1 > 0) && (_enableLE2 && !_Chamber2Disabled && _TargetTemp2 > 0)) { return CheckLETemp(_TargetTemp1, _TargetTemp2, _tolerance, _enableLE1, _enableLE2); } return true; } bool SetLETemp1() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableLE1 && !_Chamber1Disabled && _TargetTemp1 > 0) { return SetLETemp(_TargetTemp1, 0, _tolerance, _enableLE1, false); } return true; } bool CheckLETemp1() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableLE1 && !_Chamber1Disabled && _TargetTemp1 > 0) { return CheckLETemp(_TargetTemp1, 0, _tolerance, _enableLE1, false); } return true; } bool SetLETemp2() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableLE2 && !_Chamber2Disabled && _TargetTemp2 > 0) { return SetLETemp(0, _TargetTemp2, _tolerance, false, _enableLE2); } return true; } bool CheckLETemp2() { if (_TransferType == EnumTransferType.Place && !SC.IsATMMode && _enableLE2 && !_Chamber2Disabled && _TargetTemp2 > 0) { return CheckLETemp(0, _TargetTemp2, _tolerance, false, _enableLE2); } return true; } bool CheckAlreadyReadyForTransfer() { if (_pos == EnumDualPM.Left) { if (_TransferType == EnumTransferType.Pick) { if (!_chamber.CheckSlitDoor1Open()) { return false; } if (!_chamber.CheckLift1Up()) { return false; } return _chamber.CheckSlitDoor1Open() && _chamber.CheckLift1Up(); } else if (_TransferType == EnumTransferType.Place) { if (!_chamber.CheckSlitDoor1Open()) { return false; } if (!_chamber.CheckLift1Down()) { return false; } return _chamber.CheckSlitDoor1Open() && _chamber.CheckLift1Down(); } } if (_pos == EnumDualPM.Right) { if (_TransferType == EnumTransferType.Pick) { if (!_chamber.CheckSlitDoor2Open()) { return false; } if (!_chamber.CheckLift2Up()) { return false; } return _chamber.CheckSlitDoor2Open() && _chamber.CheckLift2Up(); } else if (_TransferType == EnumTransferType.Place) { if (!_chamber.CheckSlitDoor2Open()) { return false; } if (!_chamber.CheckLift2Down()) { return false; } return _chamber.CheckSlitDoor2Open() && _chamber.CheckLift2Down(); } } if (_pos == EnumDualPM.Both) { bool checkSlitDoorBothResult = _chamber.CheckSlitDoor1Open() && _chamber.CheckSlitDoor2Open(); if (!checkSlitDoorBothResult) { return checkSlitDoorBothResult; } if (_TransferType == EnumTransferType.Pick) { return _chamber.CheckLift1Up() && _chamber.CheckLift2Up(); } else if (_TransferType == EnumTransferType.Place) { return _chamber.CheckLift1Down() && _chamber.CheckLift2Down(); } } return false; } bool PMPreparePlace() { if(_TransferType == EnumTransferType.Place) { return SetLiftPinAndSlitDoorAndGuidePin(false, _ws, true, GuidePinInstalled); } return true; } bool CheckPMPreparePlace() { if (_TransferType == EnumTransferType.Place) { return CheckLiftPinAndSlitDoorAndGuidePin(false, _ws, true, GuidePinInstalled); } return true; } bool SetLiftPinAndSlitDoorAndGuidePin(bool isUp, WaferSize ws, bool isOpen, bool _guidePinInstalled) { Notify($"设置 {_chamber.Name}{_pos} liftPin {(isUp ? "升" : "降")}, 设置 {ws} Pin 升, 设置 {_chamber.Name}{_pos} SlitDoor {(isOpen ? "开" : "关")}"); if (_pos == EnumDualPM.Left || _pos == EnumDualPM.Both) { if (!_chamber.SetLiftPin1(isUp ? MovementPosition.Up : MovementPosition.Down, out string reason)) { Stop(reason); return false; } if (GuidePinInstalled) { _chamber.PrepareGuidePinForPlaceLeft(ws); } _chamber.SetSlitDoor1(isOpen, out string reason1); } if (_pos == EnumDualPM.Right || _pos == EnumDualPM.Both) { if (!_chamber.SetLiftPin2(isUp ? MovementPosition.Up : MovementPosition.Down, out string reason)) { Stop(reason); return false; } if (GuidePinInstalled) { _chamber.PrepareGuidePinForPlaceRight(ws); } _chamber.SetSlitDoor2(isOpen, out string reason2); } return true; } bool CheckLiftPinAndSlitDoorAndGuidePin(bool isUp, WaferSize ws, bool isOpen, bool _guidePinInstalled) { bool Check1() { bool res1 = isUp ? _chamber.CheckLift1Up() : _chamber.CheckLift1Down(); bool res2 = isOpen ? _chamber.CheckSlitDoor1Open() : _chamber.CheckSlitDoor1Close(); bool res3 = _guidePinInstalled ? _chamber.CheckGuidePinIsReadyForTransferLeft(ws) : true; return res1 && res2 && res3; } bool Check2() { bool res1 = isUp ? _chamber.CheckLift2Up() : _chamber.CheckLift2Down(); bool res2 = isOpen ? _chamber.CheckSlitDoor2Open() : _chamber.CheckSlitDoor2Close(); bool res3 = _guidePinInstalled ? _chamber.CheckGuidePinIsReadyForTransferRight(ws) : true; return res1 && res2 && res3; } return ((_pos != EnumDualPM.Left && _pos != EnumDualPM.Both) || Check1()) && ((_pos != EnumDualPM.Right && _pos != EnumDualPM.Both) || Check2()); } bool PMPreparePick() { if (_TransferType == EnumTransferType.Pick) { return SetLiftPinAndSlitDoorAndGuidePin(true, _ws, true, false); } return true; } bool CheckPMPreparePick() { if (_TransferType == EnumTransferType.Pick) { return CheckLiftPinAndSlitDoorAndGuidePin(true, _ws, true, false); } return true; } } }