using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Utilities; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.Loader; using CyberX8_RT.Devices.PUF; using CyberX8_RT.Devices.TransPorter; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.RT.SCCore; namespace CyberX8_RT.Modules.PUF { public class PufPickFromLoaderRoutine : RoutineBase,IRoutine { #region 常量 private const string SideA = "SideA"; private const string SideB = "SideB"; private const string CURRENT_STATION_LIST = "CurrentStationList"; private const string WAFER_PRESENT = "WaferPresent"; #endregion private enum PufPickStep { SideConditionRoutine, SideConditionRoutineWait, RotationLoaderPickup, RotationLoaderPickupWait, ChuckOut, CheckChuckOut, VacuumOn, ChuckIn, CheckChuckIn, StickDistanceCheck, RotationHomeStation, RotationHomeStationWait, End } #region 内部变量 private string _loaderSide; private string _pufSide; private JetAxisBase _flipAxis; private JetAxisBase _rotationAxis; private JetAxisBase _gantryAxis; private LoaderSideDevice _loaderSideDevice; private PufVacuum _vacuum; private PufWaferPickSubRoutine _pufWaferPickSubRoutine; private PufChuckRoutine _chuckRoutine; private PufDistanceSensor _distanceSensor; private bool _enableCheckStickDistanceStatus = false; #endregion /// /// 构造函数 /// /// /// public PufPickFromLoaderRoutine(string module) : base(module) { } /// /// 中止 /// public void Abort() { Runner.Stop("Manual Abort"); } public RState Monitor() { Runner.RunConditionSubRoutine(PufPickStep.SideConditionRoutine, SideConditionIndex, new IRoutine[] { _pufWaferPickSubRoutine }, new object[] { _pufSide }) .WaitConditionSubRoutine(PufPickStep.SideConditionRoutineWait) .Run(PufPickStep.RotationLoaderPickup, () => { return _rotationAxis.PositionStation("LoaderPickup"); }, NullFun, 100) .WaitWithStopCondition(PufPickStep.RotationLoaderPickupWait, () => { return _rotationAxis.Status == RState.End; }, () => { return _rotationAxis.Status == RState.Failed; }) .Run(PufPickStep.ChuckOut, () => { return _chuckRoutine.Start(true) == RState.Running; }, NullFun, 100) .WaitWithStopCondition(PufPickStep.CheckChuckOut, () => CommonFunction.CheckRoutineEndState(_chuckRoutine), () => CommonFunction.CheckRoutineStopState(_chuckRoutine)) .Run(PufPickStep.VacuumOn, VacuumOn, CheckWaferPresent, 5000) .Run(PufPickStep.ChuckIn, () => { return _chuckRoutine.Start(false) == RState.Running; }, NullFun, 100) .WaitWithStopCondition(PufPickStep.CheckChuckIn, () => CommonFunction.CheckRoutineEndState(_chuckRoutine), () => CommonFunction.CheckRoutineStopState(_chuckRoutine)) .Wait(PufPickStep.StickDistanceCheck, CheckStickDistanceStatus, 1000) .Run(PufPickStep.RotationHomeStation, () => { return _rotationAxis.PositionStation("Home"); }, NullFun, 100) .WaitWithStopCondition(PufPickStep.RotationHomeStationWait, () => { return _rotationAxis.Status == RState.End; }, () => { return _rotationAxis.Status == RState.Failed; }) .End(PufPickStep.End, NullFun); return Runner.Status; } /// /// Side条件获取SubRoutine索引 /// /// private int SideConditionIndex() { if (_flipAxis.CheckPositionIsInStation(_flipAxis.MotionData.MotorPosition, _pufSide)) { return 1; } else { return 0; } } /// /// 检验VacuumLevel /// /// private bool CheckVacuumLevel() { if (_pufSide == SideA) { return _vacuum.ChuckBVacuumStatus == WAFER_PRESENT; } else if (_pufSide == SideB) { return _vacuum.ChuckAVacuumStatus == WAFER_PRESENT; } else { return false; } } /// /// 检验存在Wafer /// /// private bool CheckWaferPresent() { if (_pufSide == SideA) { return _vacuum.ChuckAVacuumStatus == WAFER_PRESENT; } else if (_pufSide == SideB) { return _vacuum.ChuckBVacuumStatus == WAFER_PRESENT; } else { return false; } } /// /// 打开Vacuum /// /// private bool VacuumOn() { if (_pufSide == SideA) { _vacuum.VacuumAOn(); return true; } else if (_pufSide == SideB) { _vacuum.VacuumBOn(); return true; } return false; } /// /// Stick Distance检验结果 /// /// private bool CheckStickDistanceStatus() { if (_enableCheckStickDistanceStatus) { return _distanceSensor.CheckStickDistanceStatus(); } else { return true; } } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _pufSide = objs[0].ToString(); _flipAxis = DEVICE.GetDevice($"{Module}.Flip"); _rotationAxis = DEVICE.GetDevice($"{Module}.Rotation"); _vacuum = DEVICE.GetDevice($"{Module}.Vacuum"); _gantryAxis = DEVICE.GetDevice($"{ModuleName.Transporter2}.Gantry"); _distanceSensor = DEVICE.GetDevice($"{Module}.DistanceSensor"); _pufWaferPickSubRoutine = new PufWaferPickSubRoutine(Module); _enableCheckStickDistanceStatus = SC.GetValue($"{Module}.EnableCheckStickDistanceStatus"); _chuckRoutine = new PufChuckRoutine(Module); if (CheckCondition()) { return Runner.Start(Module, "PickFrom Loader"); } else { return RState.Failed; } } /// /// 检验条件 /// /// private bool CheckCondition() { //Loader1.Rotation 在LOADA bool isLoaderInstall = ModuleHelper.IsInstalled(ModuleName.Loader1); if (isLoaderInstall) { JetAxisBase loaderRotationAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Rotation"); double loaderRotationPosition = loaderRotationAxis.MotionData.MotorPosition; if (!loaderRotationAxis.CheckPositionInStationIgnoreWaferSize(loaderRotationPosition, "LOAD")) { LOG.WriteLog(eEvent.ERR_PUF, Module, $"Loader Rotation {loaderRotationPosition} is not in LOAD"); return false; } bool isLoadA = loaderRotationAxis.CheckPositionInStationIgnoreWaferSize(loaderRotationPosition, "LOADA"); bool isLoadB = loaderRotationAxis.CheckPositionInStationIgnoreWaferSize(loaderRotationPosition, "LOADB"); string side = isLoadA ? "A" : "B"; _loaderSide = isLoadA ? SideA : SideB; _loaderSideDevice = DEVICE.GetDevice($"{ModuleName.Loader1}.{_loaderSide}"); //Loader1.SwingA 在Open JetAxisBase loaderShuttleAAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Shuttle{side}"); double loaderShuttleAPosition = loaderShuttleAAxis.MotionData.MotorPosition; if (!loaderShuttleAAxis.CheckPositionInStationIgnoreWaferSize(loaderShuttleAPosition, "OUT")) { LOG.WriteLog(eEvent.ERR_PUF, Module, $"Loader ShuttleA {loaderShuttleAPosition} is not in OUT"); return false; } //Loader1.TiltA 在HORI JetAxisBase loaderTiltAAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Tilt{side}"); double loaderTiltAPosition = loaderTiltAAxis.MotionData.MotorPosition; if (!loaderTiltAAxis.CheckPositionIsInStation(loaderTiltAPosition, "HORI")) { LOG.WriteLog(eEvent.ERR_PUF, Module, $"Loader Tilt{side} {loaderTiltAPosition} is not in HORI"); return false; } //Loader Handle Wafer状态确认 // Lip Seal Vacuum "ON" if (!_loaderSideDevice.SideData.CRSVacuum) { LOG.WriteLog(eEvent.ERR_PUF, Module, "Loader1 LS Vacuum is off"); return false; } //Bernoulli Bladder "ON",Retracted Green Light if (!_loaderSideDevice.SideData.BernoulliBladder) { LOG.WriteLog(eEvent.ERR_PUF, Module, "Loader1 Bernoulli Bladder is off"); return false; } //其他SideA/B均为OFF if (_loaderSideDevice.SideData.BernoulliN2) { LOG.WriteLog(eEvent.ERR_PUF, Module, "Loader1 Bernoulli N2 is on"); return false; } if (_loaderSideDevice.SideData.WHBladder) { LOG.WriteLog(eEvent.ERR_PUF, Module, "Loader1 WS Bladder is on"); return false; } } double rotationPosition = _rotationAxis.MotionData.MotorPosition; if(_rotationAxis.CheckPositionIsEmpty(rotationPosition)) { LOG.WriteLog(eEvent.ERR_PUF,Module, $"rotation axis {rotationPosition} is not at Station"); return false; } double flipPosition = _flipAxis.MotionData.MotorPosition; if(_flipAxis.CheckPositionIsEmpty(flipPosition)) { LOG.WriteLog( eEvent.ERR_PUF,Module, $"flip axis {flipPosition} is not at Station"); return false; } return true; } } }