using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Beckhoff.Station; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Layout; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Utilities; using MECF.Framework.Common.WaferHolder; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.AXIS.CANOpen; using CyberX8_RT.Devices.Facilities; using CyberX8_RT.Devices.Loader; using CyberX8_RT.Devices.TransPorter; using CyberX8_RT.Modules.Loader; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CyberX8_RT.Devices.Metal; using CyberX8_RT.Devices.Rinse; namespace CyberX8_RT.Modules.Transporter { public class TransporterPickDownToRoutine : RoutineBase, IRoutine { private enum PutDownStep { CheckPreStatus, ElevatorUp, ElevatorUpWait, SafeMoveTo, CheckMoveToStatus, GantryPosition, GantryPositiolWait, CalculatePlaceSpeed, PlaceDelay, ElevatorPositionToCellTop, ElevatorPositionToCellTopWait, Delay, ElevatorPositionToCell, ElevatorPositionToCellWait, DropBlockLockoff, ElevatorGotoUp, ElevatorGotoUpWait, ConfirmWSPresent, UpdateWaferHolder, GantryPositionPark, GantryPositionParkWait, End } #region 内部变量 private string _cellName; private string _otherModule; private JetAxisBase _gantryAxis; private JetAxisBase _elevatorAxis; private JetAxisBase _otherElevatorAxis; private LoaderEntity _loaderEntity; private JetAxisBase _loaderRotationAxis; private SystemFacilities _facilities; private TransporterCommon _transporterCommon; private TransporterConflictRoutine _conflictRoutine; private LoaderCommonDevice _loaderCommonDevice; ProcessLayoutCellItem _cellItem; private int _placeTime; private int _placeDelayTime; private int _velocity; private int _acceleration; private bool _bypassWaferHolderPresent; #endregion /// <summary> /// 构造函数 /// </summary> /// <param name="module"></param> public TransporterPickDownToRoutine(string module) : base(module) { } /// <summary> /// 中止 /// </summary> public void Abort() { Runner.Stop("Manual Abort"); } /// <summary> /// 监控 /// </summary> /// <returns></returns> public RState Monitor() { Runner.Run(PutDownStep.CheckPreStatus,CheckStartPreConfition,_delay_1ms) //1. Elevator 移动至Up .Run(PutDownStep.ElevatorUp, ElevatorGotoUp, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorUpWait, CheckElevatorPositionEndStatus, CheckElevatorPositionStopStatus) //2. other Transporter Safe Move .Run(PutDownStep.SafeMoveTo, SafeMoveTo, _delay_1ms) .WaitWithStopCondition(PutDownStep.CheckMoveToStatus, () => CommonFunction.CheckRoutineEndState(_conflictRoutine), CheckSafeMoveToStopStatus) //3. Gantry 移动 .Run(PutDownStep.GantryPosition, GantryPositionToCell, _delay_1ms) .WaitWithStopCondition(PutDownStep.GantryPositiolWait, CheckGantryPositionStatus, CheckGantryPositionRunStop) //4. 确认Place 速度和加速度 .Run(PutDownStep.CalculatePlaceSpeed, CalculatePownDownSpeed, _delay_1ms) //5. Pickup delay .Delay(PutDownStep.PlaceDelay, _placeDelayTime * 1000) //6. Elevator 移动至cellTop .Run(PutDownStep.ElevatorPositionToCellTop, ElevatorPositionToCellTop, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorPositionToCellTopWait, CheckElevatorPositionEndStatus, CheckElevatorPositionStopStatus) .Delay(PutDownStep.Delay, 500) //7. Elevator 移动至cell .Run(PutDownStep.ElevatorPositionToCell, ElevatorPositionToCell, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorPositionToCellWait, CheckElevatorPositionEndStatus, CheckElevatorPositionStopStatus) //8. DropBlockLock off .Run(PutDownStep.DropBlockLockoff, DropBlockLockoff , _delay_1ms) //9. Elevator移动至Up .Run(PutDownStep.ElevatorGotoUp, ElevatorGotoUp, _delay_1ms) .WaitWithStopCondition(PutDownStep.ElevatorGotoUpWait, CheckElevatorPositionEndStatus, CheckElevatorPositionStopStatus) //10. 确认WSPresent信号 .Wait(PutDownStep.ConfirmWSPresent,ConfirmWSPresentSensorOff,_delay_2s) //11. Wafer Holder location update .Run(PutDownStep.UpdateWaferHolder,WaferHolderTransfer,_delay_1ms) //12. Gantry Position To Park .Run(PutDownStep.GantryPositionPark, GantryBackToPark, _delay_1ms) .WaitWithStopCondition(PutDownStep.GantryPositionParkWait, CheckGantryParkPositionStatus, CheckGantryParkPositionRunStop) .End(PutDownStep.End,NullFun,100); return Runner.Status; } /// <summary> /// Elevator goto Up /// </summary> /// <returns></returns> private bool ElevatorGotoUp() { bool result= _elevatorAxis.PositionStation("UP", false); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto up failed", 0); } return result; } /// <summary> /// 检验前置条件 /// </summary> /// <returns></returns> private bool CheckPreCondition() { if(!_gantryAxis.IsSwitchOn) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not switch on ", -1); return false; } if (!_gantryAxis.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not homed ",-1); return false; } if (!_elevatorAxis.IsSwitchOn) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not switch on ", -1); return false; } if (!_elevatorAxis.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not homed ",-1); return false; } return true; } /// <summary> /// 安全避障移动 /// </summary> /// <returns></returns> private bool SafeMoveTo() { _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); string stationName = _cellName; if (_cellItem != null) { if (_cellName.ToLower() != "loader" && _cellName.ToLower() != "park") { stationName = $"Cell{_cellItem.CellId}"; } } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } var result = _gantryAxis.GetPositionByStation(stationName); if (result.success) { bool isPositive = false; if (_gantryAxis.MotionData.MotorPosition < result.position) { isPositive = true; } return _conflictRoutine.Start(result.position, isPositive) == RState.Running; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in station list",0); return false; } } /// <summary> /// 检验安全避让异常结束状态 /// </summary> /// <returns></returns> private bool CheckSafeMoveToStopStatus() { bool result = CommonFunction.CheckRoutineStopState(_conflictRoutine); if (result) { NotifyError(eEvent.ERR_TRANSPORTER, "Safe Move failed", 0); } return result; } /// <summary> /// Gantry Position To cell /// </summary> /// <returns></returns> private bool GantryPositionToCell() { _cellItem= ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName); bool result = false; if (_cellItem != null) { if (_cellName.ToLower() != "loader"&&_cellName.ToLower()!="park") { result= _gantryAxis.PositionStation($"Cell{_cellItem.CellId}",false); } else { result = _gantryAxis.PositionStation(_cellName,false); } if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry axis motion failed", 0); } return result; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } } /// <summary> /// Elevator Position to cellTop /// </summary> /// <returns></returns> private bool ElevatorPositionToCellTop() { bool result = _elevatorAxis.PositionStation("CELLTOP", false, _velocity, _acceleration, _acceleration); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto CELLTOP failed", 0); } return result; } /// <summary> /// Elevator Position to cell /// </summary> /// <returns></returns> private bool ElevatorPositionToCell() { bool result= false; if( _cellItem != null ) { if (_cellName.ToLower()!="loader") { result= _elevatorAxis.PositionStation($"Cell{_cellItem.CellId}",false,_velocity,_acceleration,_acceleration); } else { result= _elevatorAxis.PositionStation(_cellName,false,_velocity,_acceleration,_acceleration); } if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed", 0); } return result; } else { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0); return false; } } /// <summary> /// 检验Elevator移动状态 /// </summary> /// <returns></returns> private bool CheckElevatorPositionEndStatus() { return _elevatorAxis.Status == RState.End; } /// <summary> /// 检验Vertical是否还在运动 /// </summary> /// <returns></returns> private bool CheckElevatorPositionStopStatus() { bool result= _elevatorAxis.Status == RState.Failed||_elevatorAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed", 0); } return result; } /// <summary> /// 检验Gantry移动状态 /// </summary> /// <returns></returns> private bool CheckGantryPositionStatus() { return _gantryAxis.Status == RState.End; } /// <summary> /// 检验Gantry是否还在运动 /// </summary> /// <returns></returns> private bool CheckGantryPositionRunStop() { bool result= _gantryAxis.Status == RState.Failed||_gantryAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry axis motion failed", 0); } return result; } /// <summary> /// 计算放下速度 /// </summary> /// <returns></returns> private bool CalculatePownDownSpeed() { if(_placeTime==0) { return true; } BeckhoffStationAxis stationAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(Module, "Elevator", 0); Station upStation = stationAxis.Stations.Find(O => O.Name.EndsWith("UP")); Station cellStation = null; if (_cellName == "Loader") { cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith("Loader")); } else { cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith($"Cell{_cellItem.CellId}")); } if (upStation==null) { NotifyError(eEvent.ERR_TRANSPORTER, "UP is not in Station List",0); return false; } if(cellStation==null) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} is not in Station List",0); return false; } if(!double.TryParse(cellStation.Position,out double cellStationPosition)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid",0); return false; } if (!double.TryParse(upStation.Position, out double upStationPosition)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid",0); return false; } int distance =(int)(Math.Round(Math.Abs(cellStationPosition - upStationPosition))); double tmpVelocity = (double) distance/ _placeTime; _velocity = _elevatorAxis.CalculateMultiplySpeedRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpVelocity)); double tmpAccelaration = (double)(2 * distance) / Math.Pow(_placeTime, 2); _acceleration = _elevatorAxis.CalculateMultiplyAccelerationRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpAccelaration)); LOG.WriteBackgroundLog(eEvent.INFO_TRANSPORTER, Module, "adjust profile speed"); return true; } /// <summary> /// 更新WaferHolder移动信息 /// </summary> /// <returns></returns> private bool WaferHolderTransfer() { bool result= WaferHolderManager.Instance.TransferWaferHolder(Module,Module, _cellName); if (!result) { NotifyError(eEvent.ERR_TRANSPORTER, "tranfer waferHolder message failed", 0); } else { if (Singleton<RouteManager>.Instance.IsAutoRunning) { WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(_cellName); if (waferHolderInfo != null) { string strTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); waferHolderInfo.SchedulerModules.Add($"{strTime} {Module} => {_cellName}"); } } } return result; } /// <summary> /// 确认WH Present Sensor off /// </summary> /// <returns></returns> private bool ConfirmWSPresentSensorOff() { if (_bypassWaferHolderPresent) return true; bool result= !_transporterCommon.TransporterData.WSHoldPresent; if(!result) { NotifyError(eEvent.ERR_TRANSPORTER, "confirm WS Present sensor failed",0); } return result; } /// <summary> /// Gabtry是否需要回到 /// </summary> /// <returns></returns> private bool NeedGantryBackToPark() { switch(_cellName) { case "Loader": case "Prewet": return true; default: return false; } } /// <summary> /// Gantry 回至Park /// </summary> /// <returns></returns> private bool GantryBackToPark() { if (NeedGantryBackToPark()) { bool result= _gantryAxis.PositionStation("Park", false); if(!result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry back to park failed",0); } return result; } else { return true; } } /// <summary> /// 检验Gantry Park移动状态 /// </summary> /// <returns></returns> private bool CheckGantryParkPositionStatus() { if (NeedGantryBackToPark()) { return _gantryAxis.Status == RState.End; } else { return true; } } /// <summary> /// 检验Gantry Park是否还在运动 /// </summary> /// <returns></returns> private bool CheckGantryParkPositionRunStop() { if (NeedGantryBackToPark()) { bool result = _gantryAxis.Status == RState.Failed||_gantryAxis.Status==RState.Timeout; if(result) { NotifyError(eEvent.ERR_TRANSPORTER, "gantry motion failed", 0); } return result; } else { return false; } } /// <summary> /// 关闭DropBlockLock /// </summary> /// <returns></returns> private bool DropBlockLockoff() { if (_transporterCommon.TransporterData.Lock) { return _transporterCommon.UnlockOperation("", null); } return true; } /// <summary> /// 启动 /// </summary> /// <param name="objs"></param> /// <returns></returns> public RState Start(params object[] objs) { _cellName = objs[0].ToString(); _velocity = 0; _acceleration = 0; InitializeParameters(); string preConfig = SC.GetConfigPreContent(_cellName); _bypassWaferHolderPresent = SC.GetValue<bool>("Transporter.BypassWaferHolderPresent"); if (SC.ContainsItem($"{preConfig}.PlaceTimeSeconds")) { _placeTime = SC.GetValue<int>($"{preConfig}.PlaceTimeSeconds"); } if (SC.ContainsItem($"{preConfig}.PlaceDelaySeconds")) { _placeDelayTime = SC.GetValue<int>($"{preConfig}.PlaceDelaySeconds"); } return Runner.Start(Module, $"Pun Down To {_cellName}"); } /// <summary> /// 初始化参数 /// </summary> private void InitializeParameters() { _elevatorAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Elevator"); _gantryAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Gantry"); _loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString()); _loaderRotationAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.Rotation"); _facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities"); _conflictRoutine = new TransporterConflictRoutine(Module); _transporterCommon = DEVICE.GetDevice<TransporterCommon>($"{Module}.Common"); _otherModule = Module == "Transporter2" ? "Transporter1" : "Transporter2"; _otherElevatorAxis = DEVICE.GetDevice<JetAxisBase>($"{_otherModule}.Elevator"); _loaderCommonDevice = DEVICE.GetDevice<LoaderCommonDevice>($"{ModuleName.Loader1}.Common"); } /// <summary> /// 启动校验条件 /// </summary> /// <returns></returns> private bool CheckStartPreConfition() { //所有轴上电并Homed bool result = CheckPreCondition(); if(!result) { return false; } //Loader is Home if (!_loaderEntity.IsHomed) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} is not homed", -1); return false; } //若目标Cell为Loader, 则Loader需在TRNA或TRANB位置且WaferShuttlePresent信号on if (_cellName == "Loader") { double loaderRotationPosition = _loaderRotationAxis.MotionData.MotorPosition; if (!_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPA") && !_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPB")) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} rotation axis {loaderRotationPosition} is not int TRNPA or TRNPB station", -1); return false; } if (_loaderCommonDevice.CommonData.WaferHolderPresent) { NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} WaferShuttlePresent is on", -1); return false; } } //Transporter应有WS信息 if (!WaferHolderManager.Instance.HasWaferHolder(Module)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} does not has wafer Shuttle",-1); return false; } //目标Cell没有WS信息 if (WaferHolderManager.Instance.HasWaferHolder(_cellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"Cell {_cellName} already has wafer Shuttle", -1); return false; } //检验Lock if (!_transporterCommon.TransporterData.Lock) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} Drop block lock is off ", -1); return false; } //检验Wafer shuttle hold present if (!_bypassWaferHolderPresent && !_transporterCommon.TransporterData.WSHoldPresent) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} Wafer shuttle hold present sensor is off ",-1); return false; } //检验Facilities //var faciltiesResult = _facilities.CheckCDA(); //if (!faciltiesResult.result) //{ // NotifyError(eEvent.ERR_TRANSPORTER, faciltiesResult.reason, -1); // return false; //} return true; } /// <summary> /// 重试 /// </summary> /// <param name="step"></param> public RState Retry(int step) { InitializeParameters(); List<Enum> preStepIds = new List<Enum>(); return Runner.Retry(PutDownStep.CheckPreStatus, preStepIds, Module, "PickUp Moveto Retry"); } /// <summary> /// 检验前面Unload完成状态 /// </summary> /// <returns></returns> public bool CheckCompleteCondition(int index) { TransporterEntity transporterEntity = Singleton<RouteManager>.Instance.GetModule<TransporterEntity>(Module); if (transporterEntity.WaferHolderInfo != null) { NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} has waferholder", index); return false; } if (!WaferHolderManager.Instance.HasWaferHolder(_cellName)) { NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} does not have waferholder", index); return false; } return true; } } }