using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Beckhoff.AxisProvider;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Backends;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.Facilities;
using CyberX8_RT.Devices.Loader;
using CyberX8_RT.Devices.SRD;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Threading;
using Aitex.Core.RT.Routine;
namespace CyberX8_RT.Modules.SRD
{
///
/// RunWafer状态机
///
public class RunWaferRecipeStateMachine : Entity, IEntity
{
#region 常量
private const int MAX_ARM_HOME_RETRIES = 3;
///
/// 旋转增加时长
///
private const int ROTATION_PLUS_TIME = 10;
///
/// ROTATION电机转速比例
///
private const int SPEED_RATIO = 10;
#endregion
#region 内部变量
///
/// 模块名称
///
private string _module;
///
/// Arm Axis
///
private JetAxisBase _armAxis;
///
/// Rotation Axis
///
private JetAxisBase _rotationAxis;
///
/// SRD Common
///
private SrdCommonDevice _srdCommon;
///
/// Total SRD
///
private TotalSRDDevice _totalSRDDevice;
///
/// 另外SRD实例
///
private SRDEntity _otherSrdEntity;
///
/// Loader Common
///
private SystemFacilities _systemFacilities;
///
/// Arm是否Home
///
private bool _armIsHomed;
///
/// Arm重试次数
///
private int _armRetryTimes = 0;
///
/// ARM正在执行Home
///
private bool _armHoming = false;
///
/// 是否正在用水
///
private bool _isUsingWater = false;
///
/// Recipe
///
private SrdRecipe _srdRecipe;
///
/// 记时
///
private int _enterTime;
///
/// Diverting Flow时长
///
private int _divertingFlowCheckTimeSpan;
///
/// Pooling Flow时长
///
private int _poolingFlowCheckTimeSpan;
///
/// Washing Flow时长
///
private int _washingFlowCheckTimeSpan;
///
/// SRD rotation Provider对象
///
private BeckhoffProviderAxis _rotationProviderAxis;
///
/// SRD arm Provider对象
///
private BeckhoffProviderAxis _armProviderAxis;
///
/// 转换增加的时间
///
private int _rotationPlusSecond = ROTATION_PLUS_TIME;
///
/// N2 Enabled
///
private bool _n2Enabled = false;
///
/// Dry速度
///
private int _drySpeed;
///
/// exhaust进入时间
///
private int _exhaustFanTime;
///
/// 旋转停止时间
///
private int _rotationStopTime;
///
/// 是否执行Rotation Stop
///
private bool _isExecuteRotationStop;
///
/// Wafer Presence Accel/Decel比例
///
private int _waferPresenceCheckAccelDecelPercentage;
///
/// Wafer Presence Speed
///
private int _waferPresenceSpeedInRPMs;
///
/// Wafer Presence distance
///
private int _waferPresenceDistance;
///
/// 状态机进入时间
///
private int _startTime;
///
/// Wafer Presence Test功能是否启用
///
private bool _presenceTestEnabled;
///
/// PresenceTest记录次数
///
private int _presenceTestCount;
///
/// 当前次数
///
private int _currentCount;
///
/// Rinse时间=Max(FrontRinseTime, BackRinseTime) 单位s
///
private double _rinseTime;
///
/// Rinse中另一个水阀开关状态
///
private bool _isAnotherWaterOn;
///
/// PresenceTest是否完成
///
private bool _isTestComplete = true;
///
/// Rotation是否执行Position
///
private bool _isRotationExecutePosition = false;
///
/// PresenceTest进入时间
///
private int _presenceTestEnterTime;
#endregion
#region 属性
///
/// 状态
///
public string State { get { return ((RunWaferState)fsm.State).ToString(); } }
#endregion
///
/// 构造函数
///
///
public RunWaferRecipeStateMachine(string module)
{
_module = module;
this.fsm = new StateMachine($"{module}_RunWaferStateMachine", (int)RunWaferState.RunWafer_Complete, 10);
fsm.EnableRepeatedMsg(true);
AnyStateTransition(RunWaferMsg.Init, EnterRunWaferStart, RunWaferState.RunWafer_Start);
AnyStateTransition(RunWaferMsg.Error, EnterError, RunWaferState.Error);
Transition(RunWaferState.RunWafer_Start, RunWaferMsg.RunWafer_Start, RunWaferStartCheckStatus, RunWaferState.RunWafer_CheckFacilities);
Transition(RunWaferState.RunWafer_CheckFacilities, FSM_MSG.TIMER, CheckFacilities, RunWaferState.RunWafer_PreparingExhaustOff);
Transition(RunWaferState.RunWafer_PreparingExhaustOff, FSM_MSG.TIMER, PreparingExhaustOff, RunWaferState.RunWafer_WaitExhaustOff);
Transition(RunWaferState.RunWafer_WaitExhaustOff, FSM_MSG.TIMER, WaitExhaustOff, RunWaferState.RunWafer_EngageChuckVacuum);
Transition(RunWaferState.RunWafer_EngageChuckVacuum, FSM_MSG.TIMER, EngageChuckVacuum, RunWaferState.RunWafer_CheckVacuum);
Transition(RunWaferState.RunWafer_CheckVacuum, FSM_MSG.TIMER, CheckVacuum, RunWaferState.RunWafer_CloseTheDoor);
Transition(RunWaferState.RunWafer_CloseTheDoor, FSM_MSG.TIMER,CloseDoor,RunWaferState.RunWafer_CheckDoorClosed);
Transition(RunWaferState.RunWafer_CheckDoorClosed, FSM_MSG.TIMER, CheckDoorClosed, RunWaferState.RunWafer_ArmToHome);
Transition(RunWaferState.RunWafer_ArmToHome, FSM_MSG.TIMER,ArmToHome, RunWaferState.RunWafer_Diverting_CheckArmHome);
Transition(RunWaferState.RunWafer_Diverting_CheckArmHome, FSM_MSG.TIMER, CheckArmHome, RunWaferState.RunWafer_Diverting_CheckOtherSRD);
Transition(RunWaferState.RunWafer_Diverting_CheckOtherSRD, FSM_MSG.TIMER, CheckOtherSRD, RunWaferState.RunWafer_Diverting_WaterOn);
Transition(RunWaferState.RunWafer_Diverting_WaterOn, FSM_MSG.TIMER, WaterOn, RunWaferState.RunWafer_Diverting_WithFlowCheck);
Transition(RunWaferState.RunWafer_Diverting_WithFlowCheck, FSM_MSG.TIMER, CheckFlow, RunWaferState.RunWafer_Washing_ArmToCenter);
Transition(RunWaferState.RunWafer_Washing_ArmToCenter, FSM_MSG.TIMER, ArmToCenter, RunWaferState.RunWafer_Washing_CheckArmCenter);
Transition(RunWaferState.RunWafer_Washing_CheckArmCenter, FSM_MSG.TIMER, CheckArmToCenter, RunWaferState.RunWafer_Washing_PoolingFrontSide);
Transition(RunWaferState.RunWafer_Washing_PoolingFrontSide, FSM_MSG.TIMER, PoolingFrontSideWaterOn, RunWaferState.RunWafer_Washing_PoolingWithFlowCheck);
Transition(RunWaferState.RunWafer_Washing_PoolingWithFlowCheck, FSM_MSG.TIMER, PoolingCheckFlow, RunWaferState.RunWafer_Washing_StartRotation);
Transition(RunWaferState.RunWafer_Washing_StartRotation, FSM_MSG.TIMER, StartRotation, RunWaferState.RunWafer_Washing_PreFlowCheck);
Transition(RunWaferState.RunWafer_Washing_PreFlowCheck, FSM_MSG.TIMER, WashingPreFlowCheck, RunWaferState.RunWafer_Washing_Finished);
Transition(RunWaferState.RunWafer_Washing_Finished, FSM_MSG.TIMER, WashingFinished, RunWaferState.RunWafer_Drying_PreN2Time);
Transition(RunWaferState.RunWafer_Drying_PreN2Time, FSM_MSG.TIMER, CheckArmMotion, RunWaferState.RunWafer_Drying_ExhaustFanDelay);
Transition(RunWaferState.RunWafer_Drying_ExhaustFanDelay, FSM_MSG.TIMER, ExhaustFanDelay, RunWaferState.RunWafer_Drying_N2On);
Transition(RunWaferState.RunWafer_Drying_N2On, FSM_MSG.TIMER, N2On, RunWaferState.RunWafer_Drying_PreWaferPresenceCheck);
Transition(RunWaferState.RunWafer_Drying_PreWaferPresenceCheck, FSM_MSG.TIMER, PreWaferPresenceCheck, RunWaferState.RunWafer_Drying_WaferPresenceCheck);
Transition(RunWaferState.RunWafer_Drying_WaferPresenceCheck, FSM_MSG.TIMER, WaferPresenceCheck, RunWaferState.RunWafer_Drying_PostN2Time);
Transition(RunWaferState.RunWafer_Drying_PostN2Time, FSM_MSG.TIMER, PostN2Time, RunWaferState.RunWafer_Drying_CheckRotationFinished);
Transition(RunWaferState.RunWafer_Drying_CheckRotationFinished, FSM_MSG.TIMER, CheckRotationFinished, RunWaferState.RunWafer_CheckArmHome);
Transition(RunWaferState.RunWafer_CheckArmHome, FSM_MSG.TIMER, LastCheckArmHomed, RunWaferState.RunWafer_Complete);
//PresenceTest
Transition(RunWaferState.RunWafer_Complete, RunWaferMsg.PreWaferPresenceCheck, RunWaferStartCheckStatus, RunWaferState.RunWafer_Drying_PreWaferPresenceCheck);
EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
}
private bool EnterError(object param)
{
//关闭风扇
if (_srdCommon.CommonData.ExhaustOn)
{
bool result = _srdCommon.ExhaustOffAction("", null);
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "EnterError: Exhaust Off is failed");
}
}
//关闭WaterAbove
if (_srdCommon.CommonData.WaterAbove)
{
bool result = _srdCommon.WaterAboveOff();
if (!result)
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "EnterError: Water Above Off is failed");
}
}
//关闭WaterBelow
if (_srdCommon.CommonData.WaterBelow)
{
bool result = _srdCommon.WaterBelowOff();
if (!result)
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "EnterError: Water Below Off is failed");
}
}
return true;
}
private bool EnterRunWaferStart(object param)
{
_isRotationExecutePosition = false;
return true;
}
#region 状态方法
///
/// 启动
///
///
///
private bool RunWaferStartCheckStatus(object param)
{
_startTime = Environment.TickCount;
if(param!=null)
{
object[] parameters= (object[])param;
_srdRecipe=(SrdRecipe)parameters[0];
}
if(_srdRecipe==null)
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, "srd recipe is null");
return false;
}
_armAxis = DEVICE.GetDevice($"{_module}.Arm");
if(!_armAxis.IsHomed)
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm is not homed");
return false;
}
_rotationAxis = DEVICE.GetDevice($"{_module}.Rotation");
if (!_rotationAxis.IsHomed)
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, "Rotation is not homed");
return false;
}
_srdCommon = DEVICE.GetDevice($"{_module}.Common");
_totalSRDDevice = DEVICE.GetDevice("SRD");
if (_srdCommon.IsWaferPresence)
{
if (_srdCommon.WaferPresence != "WellPlaced")
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, "Wafer Presence is not WellPlaced");
return false;
}
}
else
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "Wafer Presence Test has been ignored");
}
if(SC.ContainsItem("SRD.SRDRotationPlusSecond"))
{
_rotationPlusSecond = SC.GetValue("SRD.SRDRotationPlusSecond");
}
if(SC.ContainsItem("SRD.N2Enabled"))
{
_n2Enabled = SC.GetValue("SRD.N2Enabled");
}
//Wafer Presence Test
if (SC.ContainsItem($"SRD.{_module}EnablePresenceCheckvalue"))
{
_presenceTestEnabled = SC.GetValue($"SRD.{_module}EnablePresenceCheckvalue");
}
_systemFacilities = DEVICE.GetDevice("System.Facilities");
string otherSRD = _module == "SRD1" ? "SRD2" : "SRD1";
_otherSrdEntity = Singleton.Instance.GetModule(otherSRD);
_rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{_module}.Rotation");
if (_rotationProviderAxis == null)
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Rotation Provider is not exist");
return false;
}
_armProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{_module}.Arm");
if (_armProviderAxis == null)
{
PostMsg(RunWaferMsg.Error);
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm Provider is not exist");
return false;
}
_waferPresenceCheckAccelDecelPercentage = SC.GetValue("SRD.WaferPresenceCheckAccelDecelPercentage");
_waferPresenceSpeedInRPMs = SC.GetValue("SRD.WaferPresenceCheckSpeedInRPMs");
_waferPresenceDistance = SC.GetValue("SRD.WaferPresenceCheckDistanceInDegrees");
return true;
}
///
/// 检查Facilities
///
///
///
private bool CheckFacilities(object param)
{
if (_srdCommon.CommonData.FluidContainment)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Fluid Containment sensor is On");
PostMsg(RunWaferMsg.Error);
return false;
}
if(!_systemFacilities.LoaderDiEnable)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Load DI Is Disable");
PostMsg(RunWaferMsg.Error);
return false;
}
return true;
}
///
/// 关闭Exhaust风机
///
///
///
private bool PreparingExhaustOff(object param)
{
bool result = _srdCommon.ExhaustOffAction("", null);
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Preparing Exhaust Off is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return true;
}
///
/// 等待Exhaust风机关闭状态
///
///
///
private bool WaitExhaustOff(object param)
{
if (_srdCommon.Status==RState.Failed||_srdCommon.Status==RState.Timeout)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Waiting Exhaust Off is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ExhaustOn;
}
///
/// Chuck Vacuum
///
///
///
private bool EngageChuckVacuum(object param)
{
if (_srdCommon.IsWaferPresence)
{
bool result = _srdCommon.ChuckVacuumOnAction("", null);
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Chuck Vacuum On Action is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
else
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "EngageChuckVacuum has been ignored");
return true;
}
}
///
/// 检查真空状态
///
///
///
private bool CheckVacuum(object param)
{
if (_srdCommon.IsWaferPresence)
{
if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Vacuum is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return _srdCommon.Status == RState.End && !_srdCommon.CommonData.ChuckVacuum;
}
else
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "CheckVacuum has been ignored");
return true;
}
}
///
/// Close Door
///
///
///
private bool CloseDoor(object param)
{
if (_srdCommon.CommonData.DoorOpened)
{
bool result = _srdCommon.DoorCloseAction("", null);
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Door Close Action is failed");
PostMsg(RunWaferMsg.Error);
return result;
}
}
return true;
}
///
/// 检验DoorClosed
///
///
///
private bool CheckDoorClosed(object param)
{
if (_srdCommon.Status == RState.Failed || _srdCommon.Status == RState.Timeout)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Door Closed is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return _srdCommon.Status == RState.End && _srdCommon.CommonData.DoorClosed;
}
///
/// Arm To Home
///
///
private bool ArmToHome(object param)
{
if (!_armHoming)
{
_armAxis.Home(false);
_armHoming = true;
return false;
}
else
{
if(_armAxis.Status != RState.End)
{
return false;
}
}
_armHoming = false;
_armIsHomed = _armAxis.IsHomed;
return true;
}
///
/// 检验ARM,发现失败,则重试
///
///
///
private bool CheckArmHome(object param)
{
if (_armIsHomed)
{
return true;
}
else
{
if(_armRetryTimes
/// 检验另外一个SRD是否在用水
///
///
///
private bool CheckOtherSRD(object param)
{
if (_otherSrdEntity == null)
{
return true;
}
return !_otherSrdEntity.IsUsingWater;
}
///
/// 打开Above water
///
///
///
private bool WaterOn(object param)
{
if (_srdRecipe.FrontDivertTime>0)
{
if(_srdRecipe.FrontDivertTime>_srdRecipe.DivertPlusPoolDelay)
{
_divertingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
}
else
{
_divertingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime*1000;
}
if (!_srdCommon.CommonData.WaterAbove)
{
bool result = _srdCommon.WaterAboveOn();
if (result)
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
_isUsingWater = true;
_enterTime = Environment.TickCount;
}
else
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
return false;
}
else
{
return true;
}
}
///
/// 检验水压
///
///
///
private bool CheckFlow(object param)
{
if (_srdRecipe.FrontDivertTime==0)
{
return true;
}
else
{
int ticks = Environment.TickCount - _enterTime;
if(ticks<=_divertingFlowCheckTimeSpan)
{
if(_totalSRDDevice.WaterPressure>_srdRecipe.MaxDivertPlusPoolPressure)
{
LOG.WriteLog(eEvent.ERR_SRD, _module,$"Water Pressure {_totalSRDDevice} is over {_srdRecipe.MaxDivertPlusPoolPressure}");
PostMsg(RunWaferMsg.Error);
return false;
}
}
else
{
if (ticks >= _srdRecipe.FrontDivertTime*1000)
{
if (_srdCommon.CommonData.WaterAbove)
{
bool result = _srdCommon.WaterAboveOff();
if (result)
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above off");
}
else
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
}
}
}
return false;
}
///
/// Arm运动至Center
///
///
///
private bool ArmToCenter(object param)
{
bool result= _armAxis.PositionStation("Center");
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm to Center is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
///
/// check Arm是否运动至Center
///
///
///
private bool CheckArmToCenter(object param)
{
if (_armAxis.Status==RState.End)
{
return true;
}
else if(_armAxis.Status==RState.Failed)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Check Arm to Center is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return false;
}
///
/// 打开Above water
///
///
///
private bool PoolingFrontSideWaterOn(object param)
{
if (_srdRecipe.FrontPoolTime > 0)
{
if (_srdRecipe.FrontPoolTime > _srdRecipe.DivertPlusPoolDelay)
{
_poolingFlowCheckTimeSpan = _srdRecipe.DivertPlusPoolDelay * 1000;
}
else
{
_poolingFlowCheckTimeSpan = _srdRecipe.FrontDivertTime * 1000;
}
if (!_srdCommon.CommonData.WaterAbove)
{
bool result = _srdCommon.WaterAboveOn();
if (result)
{
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
_enterTime = Environment.TickCount;
if (_isUsingWater)
{
_isUsingWater = true;
}
}
else
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above On is failed");
PostMsg((int)RunWaferMsg.Error);
}
return result;
}
return true;
}
else
{
return true;
}
}
///
/// 检验水压
///
///
///
private bool PoolingCheckFlow(object param)
{
if (_srdRecipe.FrontPoolTime == 0)
{
return true;
}
else
{
int ticks = Environment.TickCount - _enterTime;
if (ticks <= _poolingFlowCheckTimeSpan)
{
if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}");
PostMsg((int)RunWaferMsg.Error);
return false;
}
if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}");
PostMsg((int)RunWaferMsg.Error);
return false;
}
}
else
{
if (ticks >= _srdRecipe.FrontPoolTime * 1000)
{
return true;
}
}
}
return false;
}
///
/// 开始旋转
///
///
///
private bool StartRotation(object param)
{
if (_srdCommon.CommonData.DoorOpened)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Door is not closed. Can't do rotation");
PostMsg(RunWaferMsg.Error);
return false;
}
double _scale = _rotationProviderAxis.ScaleFactor;
bool above = _srdRecipe.FrontRinseTime > _srdRecipe.BackRinseTime;
int timespan = above ? _srdRecipe.FrontRinseTime : _srdRecipe.BackRinseTime;
//rinse 目标位置
double rinsePosition = timespan * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed);
//dry目标位置
double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _srdRecipe.BackN2DryTime;
//为了让 rotation 不停止,增加了旋转时间(覆盖Arm运动时间)
double plusPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed) * _rotationPlusSecond;
int targetPosition = (int)Math.Round((rinsePosition + dryPosition + plusPosition) * _scale, 0);
int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.RinseSpeed),0);
_drySpeed= (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_srdRecipe.DrySpeed * SPEED_RATIO), 0);
bool result= _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0);
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Start Rotation is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Start Rotation");
//如果BackRinseTime大,则先开WaterBelow后开WaterAbove
if (_srdRecipe.BackRinseTime>_srdRecipe.FrontRinseTime)
{
_rinseTime = _srdRecipe.BackRinseTime;
//关闭WaterAbove
if (_srdCommon.CommonData.WaterAbove)
{
if (!_srdCommon.WaterAboveOff())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above Off");
}
//打开WaterBelow
if (!_srdCommon.CommonData.WaterBelow)
{
if (!_srdCommon.WaterBelowOn())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below On");
}
//Rinse开始时间
_enterTime = Environment.TickCount;
//另一个水阀状态变为未开(即WaterAbove)
_isAnotherWaterOn = false;
//计算水压检测滞后时间
if (_srdRecipe.BackRinseTime > _srdRecipe.FlowCheckDelay)
{
_washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
}
else
{
_washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
}
return true;
}
else
{
_rinseTime = _srdRecipe.FrontRinseTime;
//如果FrontRinseTime大,则先开WaterAbove后开WaterBelow
//打开WaterAbove
if (!_srdCommon.CommonData.WaterAbove)
{
if (!_srdCommon.WaterAboveOn())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
}
//关闭WaterBelow
if (_srdCommon.CommonData.WaterBelow)
{
//打开WaterBelow
if (!_srdCommon.WaterBelowOff())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below Off");
}
//另一个水阀状态变为未开(即WaterBelow)
_isAnotherWaterOn = false;
//Rinse开始时间
_enterTime = Environment.TickCount;
//计算水压检测滞后时间
if (_srdRecipe.FrontRinseTime > _srdRecipe.FlowCheckDelay)
{
_washingFlowCheckTimeSpan = _srdRecipe.FlowCheckDelay * 1000;
}
else
{
_washingFlowCheckTimeSpan = _srdRecipe.BackRinseTime * 1000;
}
return true;
}
}
///
/// 检验水压
///
///
///
private bool WashingPreFlowCheck(object param)
{
int ticks = Environment.TickCount - _enterTime;
//打开另一个未开的水阀
if(!_isAnotherWaterOn)
{
//延迟abs(BackRinseTime - FrontRinseTime)秒打开另一个水阀
if (_srdRecipe.BackRinseTime > _srdRecipe.FrontRinseTime)
{
//若BackRinseTime > FrontRinseTime,则延迟BackRinseTime - FrontRinseTime秒打开Water Above
if (ticks >= _rinseTime*1000 - _srdRecipe.FrontRinseTime*1000 && !_srdCommon.CommonData.WaterAbove)
{
bool result = _srdCommon.WaterAboveOn();
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
_isAnotherWaterOn = true;
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Above On");
}
}
else
{
//若FrontRinseTime > BackRinseTime,则延迟FrontRinseTime - BackRinseTime秒打开Water Below
if (ticks >= _rinseTime * 1000 - _srdRecipe.BackRinseTime * 1000 && !_srdCommon.CommonData.WaterBelow)
{
bool result = _srdCommon.WaterBelowOn();
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below On is failed");
PostMsg((int)RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, "Water Below On");
}
}
}
if (ticks >= _rinseTime * 1000)
{
//达到RinseTime完成Wash
return true;
}
else if (ticks > _washingFlowCheckTimeSpan)
{
if (_totalSRDDevice.WaterPressure > _srdRecipe.MaxWashPressure)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is over {_srdRecipe.MaxWashPressure}");
PostMsg((int)RunWaferMsg.Error);
return false;
}
if (_totalSRDDevice.WaterPressure < _srdRecipe.MinWaterPressure)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"Water Pressure {_totalSRDDevice.WaterPressure} is less {_srdRecipe.MinWaterPressure}");
PostMsg((int)RunWaferMsg.Error);
return false;
}
}
else
{
return false;
}
return false;
}
///
/// Washing结束
///
///
///
private bool WashingFinished(object param)
{
if (_srdCommon.CommonData.WaterAbove)
{
if(!_srdCommon.WaterAboveOff())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Above Off is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
}
if(_srdCommon.CommonData.WaterBelow)
{
if(!_srdCommon.WaterBelowOff())
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Water Below Off is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
}
_isUsingWater = false;
if(_n2Enabled)
{
bool result= _armAxis.PositionStation("Center");
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm to Center is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
else
{
bool result= _armAxis.PositionStation("Home");
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm To Home is failed");
PostMsg(RunWaferMsg.Error);
}
return result;
}
}
///
/// 检验Arm是否运动到位
///
///
private bool CheckArmMotion(object param)
{
//Arm是否运动到位
if (_armAxis.Status==RState.End)
{
//调整速度为 drySpeed
bool result= _rotationAxis.ChangeSpeed(_drySpeed);
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Change Speed to Dry Speed is failed");
return false;
}
if(_n2Enabled)
{
//todo 打开N2 Above和N2 Below
}
_exhaustFanTime = Environment.TickCount;
return true;
}
else if(_armAxis.Status==RState.Failed)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Arm Axis Status is in Failed");
PostMsg(RunWaferMsg.Error);
return false;
}
return false;
}
///
/// Exhaust delay
///
///
///
private bool ExhaustFanDelay(object param)
{
int ticks = Environment.TickCount - _exhaustFanTime;
if (ticks >= _srdRecipe.ExhaustFanDelay * 1000)
{
bool result = _srdCommon.ExhaustOn();
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Exhaust On failed");
PostMsg(RunWaferMsg.Error);
return false;
}
_enterTime = Environment.TickCount;
return true;
}
return false;
}
///
/// N2 On
///
///
///
private bool N2On(object param)
{
if (_n2Enabled)
{
//todo 关闭N2Above和N2 Below
}
int ticks = Environment.TickCount - _enterTime;
if(ticks > _srdRecipe.BackN2DryTime * 1000) return true;
return false;
}
///
/// Pre WaferPresence Check
///
///
private bool PreWaferPresenceCheck(object param)
{
if (!_isExecuteRotationStop)
{
//停止Rotation
bool result= _rotationAxis.StopPositionOperation();
LOG.WriteLog(eEvent.INFO_SRD, _module, "Stop Rotation is done");
_rotationStopTime = Environment.TickCount;
_isExecuteRotationStop = true;
if(!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Stop Rotation is failed");
PostMsg(RunWaferMsg.Error);
}
}
else
{
int ticks=Environment.TickCount-_rotationStopTime;
if(ticks>=5*1000)//固定时间5秒,确认Rotation是否已经停下
{
if(!_rotationAxis.IsRun && _rotationAxis.Status == RState.End)
{
_isExecuteRotationStop = false;
return true;
}
else
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "SRD Rotation Stop time span is over 5 seconds");
PostMsg(RunWaferMsg.Error);
return false;
}
}
}
return false;
}
///
/// Wafer Presence Check
///
///
///
private bool WaferPresenceCheck(object param)
{
double scale = _rotationProviderAxis.ScaleFactor;
int currentRotation = (int)Math.Round(_rotationAxis.MotionData.MotorPosition * scale, 0);
//Presence Test目标位置(单位为°)
int targetPosition = (int)Math.Round(scale * _waferPresenceDistance,0)+currentRotation;
//转速单位转换 RPM(r/min) to degree/s
double degree = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_waferPresenceSpeedInRPMs);
//Presence Test目标转速
int profileVelocity =(int)Math.Round(scale*degree,0);
//加速度
int acceleration = (int)Math.Round(_rotationAxis.ProfileAcceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
//减速度
int deceleration = (int)Math.Round(_rotationAxis.ProfileDeceleration * _waferPresenceCheckAccelDecelPercentage / 100, 0);
if (!_isRotationExecutePosition)
{
if (_srdCommon.CommonData.DoorOpened)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Door is not closed. Can't do rotation");
PostMsg(RunWaferMsg.Error);
return false;
}
bool result = _rotationAxis.ProfilePosition(targetPosition, profileVelocity * SPEED_RATIO, acceleration, deceleration);
if (!result)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Start Rotation is failed");
PostMsg(RunWaferMsg.Error);
}
_isRotationExecutePosition = true;
if (_srdCommon.IsWaferPresence && _presenceTestEnabled)
{
//PresenceTest记录次数=(目标位置/目标转速)*1000ms /500ms
_presenceTestCount = (int)Math.Floor(_waferPresenceDistance / degree * 1000 / 500);
LOG.WriteLog(eEvent.INFO_SRD, _module, $"Presence Test Count is about {_presenceTestCount} times");
//当前test次数归零
_currentCount = 0;
//开始计时
_presenceTestEnterTime = Environment.TickCount;
_isTestComplete = false;
LOG.WriteLog(eEvent.INFO_SRD, _module, "Presence Test Timer is started");
}
return false;
}
else
{
//PresenceTestEnable开启则进行测试
if (!_isTestComplete && _srdCommon.IsWaferPresence && _presenceTestEnabled)
{
int ticks = Environment.TickCount - _presenceTestEnterTime;
//500ms检测一次
if(ticks >= 500)
{
if (_srdCommon.WaferPresence == "WellPlaced")
{
_currentCount++;
LOG.WriteLog(eEvent.INFO_SRD, _module, $"The {_currentCount}th Presence Test is successful");
//更新PresenceTestEnterTime
_presenceTestEnterTime = Environment.TickCount;
if(_currentCount >= _presenceTestCount)
{
//PresenceTest通过
_isTestComplete = true;
LOG.WriteLog(eEvent.INFO_SRD, _module, $"The Presence Test of {_module} is all successful");
}
else
{
return false;
}
}
else
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"The {_currentCount + 1}th Presence Test is failed");
LOG.WriteLog(eEvent.ERR_SRD, _module, $"The Presence Test of {_module} is failed");
PostMsg(RunWaferMsg.Error);
return false;
}
}
else
{
return false;
}
}
if (_rotationAxis.Status!=RState.End)
{
return false;
}
}
return true;
}
///
/// Post N2 Time(Stop rotation ,home rotation)
///
///
///
private bool PostN2Time(object param)
{
bool homeResult = _rotationAxis.Home(false);
if(!homeResult)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not homed");
PostMsg(RunWaferMsg.Error);
return false;
}
return true;
}
///
/// 检验Rotation是否Homed
///
///
///
private bool CheckRotationFinished(object param)
{
//关闭排风扇
if (_srdCommon.CommonData.ExhaustOn && _srdCommon.Status != RState.Running)
{
bool result1 = _srdCommon.ExhaustOffAction("", null);
if (!result1)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, "Preparing Exhaust Off is failed");
PostMsg(RunWaferMsg.Error);
}
}
bool result= _rotationAxis.IsHomed && _rotationAxis.Status == RState.End;
if(_rotationAxis.Status!=RState.Running)
{
if(!_rotationAxis.IsHomed)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.rotation is not homed");
}
return true;
}
return false;
}
///
/// 检验
///
///
///
private bool LastCheckArmHomed(object param)
{
string currentLocation = _armAxis.CurrentStation;
bool armHomed= _armAxis.IsHomed;
if(!armHomed)
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not homed");
PostMsg(RunWaferMsg.Error);
return false;
}
if (!currentLocation.Contains("Home"))
{
LOG.WriteLog(eEvent.ERR_SRD, _module, $"{_module}.Arm is not in home station");
PostMsg(RunWaferMsg.Error);
return false;
}
LOG.WriteLog(eEvent.INFO_SRD, _module, $"Run Wafer State Machine 状态 {RunWaferState.RunWafer_Start}==>{RunWaferState.RunWafer_Complete} Total Time[{Environment.TickCount - _startTime}]");
return true;
}
#endregion
///
/// 停止
///
public void Stop()
{
base.Terminate();
}
public bool Check(int msg, out string reason, params object[] args)
{
reason = "";
return false;
}
#region State Msg枚举
public enum RunWaferState
{
None,
Error,
RunWafer_Start,
RunWafer_CheckFacilities,
RunWafer_PreparingExhaustOff,
RunWafer_WaitExhaustOff,
RunWafer_EngageChuckVacuum,
RunWafer_CheckVacuum,
RunWafer_CloseTheDoor,
RunWafer_CheckDoorClosed,
RunWafer_ArmToHome,
RunWafer_Diverting_CheckArmHome,
RunWafer_Diverting_CheckOtherSRD,
RunWafer_Diverting_WaterOn,
RunWafer_Diverting_WithFlowCheck,
RunWafer_Washing_ArmToCenter,
RunWafer_Washing_CheckArmCenter,
RunWafer_Washing_PoolingFrontSide,
RunWafer_Washing_PoolingWithFlowCheck,
RunWafer_Washing_StartRotation,
RunWafer_Washing_PreFlowCheck,
RunWafer_Washing_Finished,
RunWafer_Drying_PreN2Time,
RunWafer_Drying_ExhaustFanDelay,
RunWafer_Drying_N2On,
RunWafer_Drying_PreWaferPresenceCheck,
RunWafer_Drying_WaferPresenceCheck,
RunWafer_Drying_PostN2Time,
RunWafer_Drying_CheckRotationFinished,
RunWafer_CheckArmHome,
RunWafer_Complete
}
public enum RunWaferMsg
{
Init,
Error,
RunWafer_Start,
CheckFacilities,
PreparingExhaustOff,
WaitExhaustOff,
EngageChuckVacuum,
CloseTheDoor,
ArmToHome,
CheckOtherSRD,
DivertingWaterAboveOn,
ArmToCenter,
PoolingFrontWaterAboveOn,
StartRotation,
Washing_Finished,
N2On,
PreWaferPresenceCheck,
WaferPresenceCheck,
PostN2Time,
CheckArmHome,
Abort
}
#endregion
}
}