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;
using static Mono.Security.X509.X520;
namespace CyberX8_RT.Modules.Transporter
{
public class TransporterPickDownToRoutine : RoutineBase, IRoutine
{
private enum PutDownStep
{
CheckPreStatus,
ElevatorUp,
ElevatorUpWait,
SafeMoveTo,
CheckMoveToStatus,
GantryPosition,
GantryPositiolWait,
ElevatorPositionToCellTop,
ElevatorPositionToCellTopWait,
Delay,
CalculatePlaceSpeed,
PlaceDelay,
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
///
/// 构造函数
///
///
public TransporterPickDownToRoutine(string module) : base(module)
{
}
///
/// 中止
///
public void Abort()
{
Runner.Stop("Manual Abort");
}
///
/// 监控
///
///
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)
//6. Elevator 移动至cellTop
.Run(PutDownStep.ElevatorPositionToCellTop, ElevatorPositionToCellTop, _delay_1ms)
.WaitWithStopCondition(PutDownStep.ElevatorPositionToCellTopWait, CheckElevatorPositionEndStatus, CheckElevatorPositionStopStatus)
.Delay(PutDownStep.Delay, 500)
//4. 确认Place 速度和加速度
.Run(PutDownStep.CalculatePlaceSpeed, CalculatePownDownSpeed, _delay_1ms)
//5. Pickup delay
.Delay(PutDownStep.PlaceDelay, _placeDelayTime * 1000)
//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;
}
///
/// Elevator goto Up
///
///
private bool ElevatorGotoUp()
{
bool result= _elevatorAxis.PositionStation("UP", false);
if (!result)
{
NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto up failed", 0);
}
return result;
}
///
/// 检验前置条件
///
///
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;
}
///
/// 安全避障移动
///
///
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;
}
}
///
/// 检验安全避让异常结束状态
///
///
private bool CheckSafeMoveToStopStatus()
{
bool result = CommonFunction.CheckRoutineStopState(_conflictRoutine);
if (result)
{
NotifyError(eEvent.ERR_TRANSPORTER, "Safe Move failed", 0);
}
return result;
}
///
/// Gantry Position To cell
///
///
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;
}
}
///
/// Elevator Position to cellTop
///
///
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;
}
///
/// Elevator Position to cell
///
///
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;
}
}
///
/// 检验Elevator移动状态
///
///
private bool CheckElevatorPositionEndStatus()
{
return _elevatorAxis.Status == RState.End;
}
///
/// 检验Vertical是否还在运动
///
///
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;
}
///
/// 检验Gantry移动状态
///
///
private bool CheckGantryPositionStatus()
{
return _gantryAxis.Status == RState.End;
}
///
/// 检验Gantry是否还在运动
///
///
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;
}
///
/// 计算放下速度
///
///
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("CellTop")); 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, "CellTop 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;
}
///
/// 更新WaferHolder移动信息
///
///
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.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;
}
///
/// 确认WH Present Sensor off
///
///
private bool ConfirmWSPresentSensorOff()
{
if (_bypassWaferHolderPresent) return true;
bool result= !_transporterCommon.TransporterData.WSHoldPresent;
if(!result)
{
LOG.WriteLog(eEvent.INFO_TRANSPORTER, Module, "confirm WS Present sensor failed");
}
return result;
}
///
/// Gabtry是否需要回到
///
///
private bool NeedGantryBackToPark()
{
switch(_cellName)
{
case "Loader":
case "Prewet":
return true;
default:
return false;
}
}
///
/// Gantry 回至Park
///
///
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;
}
}
///
/// 检验Gantry Park移动状态
///
///
private bool CheckGantryParkPositionStatus()
{
if (NeedGantryBackToPark())
{
return _gantryAxis.Status == RState.End;
}
else
{
return true;
}
}
///
/// 检验Gantry Park是否还在运动
///
///
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;
}
}
///
/// 关闭DropBlockLock
///
///
private bool DropBlockLockoff()
{
if (_transporterCommon.TransporterData.Lock)
{
return _transporterCommon.UnlockOperation("", null);
}
return true;
}
///
/// 启动
///
///
///
public RState Start(params object[] objs)
{
_cellName = objs[0].ToString();
_velocity = 0;
_acceleration = 0;
InitializeParameters();
string preConfig = SC.GetConfigPreContent(_cellName);
_bypassWaferHolderPresent = SC.GetValue("Transporter.BypassWaferHolderPresent");
if (SC.ContainsItem($"{preConfig}.PlaceTimeSeconds"))
{
_placeTime = SC.GetValue($"{preConfig}.PlaceTimeSeconds");
}
if (SC.ContainsItem($"{preConfig}.PlaceDelaySeconds"))
{
_placeDelayTime = SC.GetValue($"{preConfig}.PlaceDelaySeconds");
}
return Runner.Start(Module, $"Pun Down To {_cellName}");
}
///
/// 初始化参数
///
private void InitializeParameters()
{
_elevatorAxis = DEVICE.GetDevice($"{Module}.Elevator");
_gantryAxis = DEVICE.GetDevice($"{Module}.Gantry");
_loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString());
_loaderRotationAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Rotation");
_facilities = DEVICE.GetDevice("System.Facilities");
_conflictRoutine = new TransporterConflictRoutine(Module);
_transporterCommon = DEVICE.GetDevice($"{Module}.Common");
_otherModule = Module == "Transporter2" ? "Transporter1" : "Transporter2";
_otherElevatorAxis = DEVICE.GetDevice($"{_otherModule}.Elevator");
_loaderCommonDevice = DEVICE.GetDevice($"{ModuleName.Loader1}.Common");
}
///
/// 启动校验条件
///
///
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;
}
///
/// 重试
///
///
public RState Retry(int step)
{
InitializeParameters();
List preStepIds = new List();
return Runner.Retry(PutDownStep.CheckPreStatus, preStepIds, Module, "PickUp Moveto Retry");
}
///
/// 检验前面Unload完成状态
///
///
public bool CheckCompleteCondition(int index)
{
TransporterEntity transporterEntity = Singleton.Instance.GetModule(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;
}
}
}