|
|
@@ -3,6 +3,7 @@ using Aitex.Core.RT.Log;
|
|
|
using Aitex.Core.RT.Routine;
|
|
|
using Aitex.Core.Util;
|
|
|
using MECF.Framework.Common.Beckhoff.AxisProvider;
|
|
|
+using MECF.Framework.Common.Beckhoff.Station;
|
|
|
using MECF.Framework.Common.RecipeCenter;
|
|
|
using MECF.Framework.Common.Routine;
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
|
@@ -18,6 +19,7 @@ using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
+using static Mono.Security.X509.X520;
|
|
|
|
|
|
namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
{
|
|
|
@@ -26,14 +28,26 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
private enum RunRecipeStep
|
|
|
{
|
|
|
Delay,
|
|
|
+ VerticalGotoRinse,
|
|
|
+ CheckVerticalGotoRinse,
|
|
|
InterRinse,
|
|
|
CheckInterRinse,
|
|
|
- Vertical,
|
|
|
+ RotationStartEntry,
|
|
|
+ RotationChangeToEntrySpeed,
|
|
|
+ AngleTilt,
|
|
|
+ VerticalGotoEntry,
|
|
|
+ WaitEntryCurrentProtectedFromRinse,
|
|
|
+ WaitEntryCurrentProtectedFromHome,
|
|
|
+ EntryCurrentProtected,
|
|
|
CheckVertical,
|
|
|
End
|
|
|
}
|
|
|
#region 常量
|
|
|
private const int ALL_DAY_MILLOSECONDS = 24 * 60 * 60 * 1000;
|
|
|
+ /// <summary>
|
|
|
+ /// ROTATION电机转速比例
|
|
|
+ /// </summary>
|
|
|
+ private const int SPEED_RATIO = 1;
|
|
|
#endregion
|
|
|
|
|
|
#region 内部变量
|
|
|
@@ -76,6 +90,18 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// vertical axis entity
|
|
|
/// </summary>
|
|
|
private PlatingCellVerticalEntity _verticalEntity;
|
|
|
+ /// <summary>
|
|
|
+ /// vertical 轴的位置数据
|
|
|
+ /// </summary>
|
|
|
+ private BeckhoffStationAxis _verticalBeckhoffStation;
|
|
|
+ /// <summary>
|
|
|
+ /// recipe中是否存在电机反转
|
|
|
+ /// </summary>
|
|
|
+ private bool _isRecipeContainsRevserseRotation;
|
|
|
+ /// <summary>
|
|
|
+ /// run recipe 过程中电机会停的位置(需要根据recipe计算出来)
|
|
|
+ /// </summary>
|
|
|
+ private List<int> _targetPositionList = new List<int>();
|
|
|
#endregion
|
|
|
/// <summary>
|
|
|
/// 构造函数
|
|
|
@@ -97,17 +123,59 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public RState Monitor()
|
|
|
- {
|
|
|
- Runner.Delay(RunRecipeStep.Delay, 5000)
|
|
|
- .RunIf(RunRecipeStep.InterRinse, _recipe.RinseBeforeEntryEnable,() => { return _interRinseRoutine.Start(_recipe,_rotationAxis, _device, _rotationProviderAxis) == RState.Running; })
|
|
|
- .WaitWithStopConditionIf(RunRecipeStep.CheckInterRinse, _recipe.RinseBeforeEntryEnable,CheckInterRinseEndStatus,
|
|
|
+ { //vertical去rinse位置
|
|
|
+ Runner.RunIf(RunRecipeStep.VerticalGotoRinse, _recipe.RinseBeforeEntryEnable, () => { return StartVertical("Rinse",_recipe.IntervalRinseZoffset); }, _delay_1ms)
|
|
|
+ .WaitWithStopConditionIf(RunRecipeStep.CheckVerticalGotoRinse, _recipe.RinseBeforeEntryEnable, CheckVerticalEnd, CheckVerticalError)
|
|
|
+ //执行interval rinse
|
|
|
+ .RunIf(RunRecipeStep.InterRinse, _recipe.RinseBeforeEntryEnable, () => { return _interRinseRoutine.Start(_recipe, _rotationAxis, _device, _rotationProviderAxis, _targetPositionList[0]) == RState.Running; })
|
|
|
+ .WaitWithStopConditionIf(RunRecipeStep.CheckInterRinse, _recipe.RinseBeforeEntryEnable, CheckInterRinseEndStatus,
|
|
|
() => CommonFunction.CheckRoutineStopState(_interRinseRoutine))
|
|
|
- .Run(RunRecipeStep.Vertical, StartVertical)
|
|
|
- .WaitWithStopCondition(RunRecipeStep.CheckVertical, CheckVerticalEnd, CheckVerticalError)
|
|
|
+ //启动Rotation/Rotation 设置为entry 转速
|
|
|
+ .RunIf(RunRecipeStep.RotationStartEntry, !_recipe.RinseBeforeEntryEnable, RotationStartEntry, _delay_1ms) //没有intercal rinse 在entry开始的时候启动rotation
|
|
|
+ .RunIf(RunRecipeStep.RotationChangeToEntrySpeed, _recipe.RinseBeforeEntryEnable, () => { return ChangeSpeed(_recipe.EntrySpinSpeed); }, _delay_1ms) //有intercal rinse 直接变速
|
|
|
+ //Angle tilt 操作
|
|
|
+ .Run(RunRecipeStep.AngleTilt, _device.HeadtTiltAction, () => { return _device.PlatingCellDeviceData.HeadTilt; }, _delay_1s)
|
|
|
+ .Run(RunRecipeStep.VerticalGotoEntry, () => { return StartVertical("Entry", _recipe.EntryZoffset); }, _delay_1ms)
|
|
|
+ .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromRinse, !_recipe.RinseBeforeEntryEnable,CalculateVerticaMoveTime("Rinse","Entry") - 100 > 0 ? CalculateVerticaMoveTime("Rinse", "Entry"):0)
|
|
|
+ .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromHome, _recipe.RinseBeforeEntryEnable,CalculateVerticaMoveTime("Home","Entry") - 100 > 0 ? CalculateVerticaMoveTime("Home", "Entry") : 0)
|
|
|
.End(RunRecipeStep.End, NullFun);
|
|
|
return Runner.Status;
|
|
|
}
|
|
|
-
|
|
|
+ /// <summary>
|
|
|
+ /// 计算vertical 从一个位置移动到另一个位置用时
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="sourceLocation"></param>
|
|
|
+ /// <param name="destinationLocation"></param>
|
|
|
+ /// <returns>返回值单位毫秒</returns>
|
|
|
+ private int CalculateVerticaMoveTime(string sourceLocation,string destinationLocation)
|
|
|
+ {
|
|
|
+ Station sourceStation = _verticalBeckhoffStation.Stations.FirstOrDefault(p => p.Name == $"{_verticalEntity.Module}.{sourceLocation}");
|
|
|
+ Station destinationStation = _verticalBeckhoffStation.Stations.FirstOrDefault(p => p.Name == $"{_verticalEntity.Module}.{destinationLocation}");
|
|
|
+ Double.TryParse(sourceStation.Position, out double sourcePosition);
|
|
|
+ Double.TryParse(destinationStation.Position, out double destinationPosition);
|
|
|
+ double time = Math.Abs(destinationPosition - sourcePosition) / _verticalEntity.MotionData.ProfileVelocity * 10;
|
|
|
+ if (time <= 0)
|
|
|
+ {
|
|
|
+ NotifyError(eEvent.WARN_PLATINGCELL, "Calculate Vertica Move Time is 0", 0);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return (int)time;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// change speed
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ private bool ChangeSpeed(int speed) //参数speed单位是rmp
|
|
|
+ {
|
|
|
+ double realSpeed = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(speed);
|
|
|
+ bool result = _rotationAxis.ChangeSpeed((int)realSpeed);
|
|
|
+ if (!result)
|
|
|
+ {
|
|
|
+ NotifyError(eEvent.ERR_PLATINGCELL, "Change Speed failed", 0);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
private bool CheckInterRinseEndStatus()
|
|
|
{
|
|
|
bool result = CommonFunction.CheckRoutineEndState(_interRinseRoutine);
|
|
|
@@ -115,17 +183,45 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
return result;
|
|
|
}
|
|
|
/// <summary>
|
|
|
- /// 垂直电机运行(仅示例只做参考)
|
|
|
+ /// rotation 从entry步骤开始旋转
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ private bool RotationStartEntry()
|
|
|
+ {
|
|
|
+ bool result = _rotationAxis.ProfilePosition(_targetPositionList[0], _recipe.IntervalRinseSpeed * SPEED_RATIO, 0, 0);
|
|
|
+ if (!result)
|
|
|
+ {
|
|
|
+ NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// vertical 运行
|
|
|
/// </summary>
|
|
|
+ /// <param name="positionName"></param> 目标位置名称
|
|
|
+ /// <param name="offset"></param> 偏移量
|
|
|
/// <returns></returns>
|
|
|
- private bool StartVertical()
|
|
|
+ private bool StartVertical(string positionName,double offset)
|
|
|
{
|
|
|
- double position = 101;
|
|
|
+ double position = 0;
|
|
|
+ Station station = _verticalBeckhoffStation.Stations.FirstOrDefault(p => p.Name == $"{_verticalEntity.Module}.{positionName}");
|
|
|
+ if (station != null)
|
|
|
+ {
|
|
|
+ if(!Double.TryParse(station.Position, out position))
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "vertical station position is error");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, $"vertical station {_verticalEntity.Module}.{positionName} is null");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
return _verticalEntity.CheckToPostMessage<PlatingCellVerticalState, PlatingCellVerticalEntity.VerticalMsg>(Aitex.Core.RT.Log.eEvent.INFO_PLATINGCELL,
|
|
|
- Module, (int)PlatingCellVerticalEntity.VerticalMsg.Position, position);
|
|
|
+ Module, (int)PlatingCellVerticalEntity.VerticalMsg.Position, position + offset);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// 检验垂直电机是否运动完成
|
|
|
/// </summary>
|
|
|
@@ -175,6 +271,8 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
//获取对应reservoir eneity
|
|
|
string reservoir = ReservoirItemManager.Instance.GetReservoirByPlatingCell(Module);
|
|
|
_reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(reservoir);
|
|
|
+ //获取vertical station信息对象
|
|
|
+ _verticalBeckhoffStation = BeckhoffStationLocationManager.Instance.GetStationAxis($"{_verticalEntity.Module}", "Vertical");
|
|
|
if (!CheckPreCondition())
|
|
|
{
|
|
|
return RState.Failed;
|