|
|
@@ -31,23 +31,12 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
{
|
|
|
private enum RunRecipeStep
|
|
|
{
|
|
|
- Delay,
|
|
|
- VerticalGotoRinse,
|
|
|
- CheckVerticalGotoRinse,
|
|
|
InterRinse,
|
|
|
CheckInterRinse,
|
|
|
- RotationStartEntry,
|
|
|
- RotationChangeToEntrySpeed,
|
|
|
- AngleTilt,
|
|
|
- VerticalGotoPlate,
|
|
|
- WaitEntryCurrentProtectedFromRinse,
|
|
|
- WaitEntryCurrentProtectedFromHome,
|
|
|
- RunPowerStepWithEntryProtect,
|
|
|
- CheckVerticalGotoPlate,
|
|
|
- AngleVertical,
|
|
|
- WaitPlatingDelay,
|
|
|
- RunPowerStep,
|
|
|
- RunPowerStepWait,
|
|
|
+ Entry,
|
|
|
+ CheckEntry,
|
|
|
+ Deposition,
|
|
|
+ CheckDeposition,
|
|
|
End
|
|
|
}
|
|
|
#region 常量
|
|
|
@@ -94,10 +83,6 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// </summary>
|
|
|
private ReservoirEntity _reservoirEntity;
|
|
|
/// <summary>
|
|
|
- /// interbal rinse routien
|
|
|
- /// </summary>
|
|
|
- private PlatingCellInterRinseRoutine _interRinseRoutine;
|
|
|
- /// <summary>
|
|
|
/// vertical axis entity
|
|
|
/// </summary>
|
|
|
private PlatingCellVerticalEntity _verticalEntity;
|
|
|
@@ -117,27 +102,44 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
|
|
|
#region 电镀通电相关
|
|
|
/// <summary>
|
|
|
- /// PlatingDelay计时
|
|
|
- /// </summary>
|
|
|
- private DateTime _hotPlatingRunTime;
|
|
|
- /// <summary>
|
|
|
/// 不通电
|
|
|
/// </summary>
|
|
|
private bool _isZeroCurrent = false;
|
|
|
/// <summary>
|
|
|
- /// 通电时长
|
|
|
- /// </summary>
|
|
|
- private int _totalMicrosecond = 0;
|
|
|
- /// <summary>
|
|
|
- /// Power 集合
|
|
|
+ /// Power step集合
|
|
|
/// </summary>
|
|
|
List<PowerSupplierStepPeriodData> _powerSupplierStepPeriodDatas = new List<PowerSupplierStepPeriodData>();
|
|
|
/// <summary>
|
|
|
/// 记录dep recipe中出现的最大电流,用于启动电源前切换挡位
|
|
|
/// </summary>
|
|
|
private double _maxCurrent = 0;
|
|
|
+ /// <summary>
|
|
|
+ /// 通电总时长
|
|
|
+ /// </summary>
|
|
|
+ private int _totalMicrosecond = 0;
|
|
|
+ /// <summary>
|
|
|
+ /// Plating启动时间
|
|
|
+ /// </summary>
|
|
|
+ private DateTime _platingStartTime;
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region routine
|
|
|
+ /// <summary>
|
|
|
+ /// interbal rinse routien
|
|
|
+ /// </summary>
|
|
|
+ private PlatingCellInterRinseRoutine _interRinseRoutine;
|
|
|
+ /// <summary>
|
|
|
+ /// entry routien
|
|
|
+ /// </summary>
|
|
|
+ private PlatingCellEntryRoutine _entryRoutine;
|
|
|
+ /// <summary>
|
|
|
+ /// entry routien
|
|
|
+ /// </summary>
|
|
|
+ private PlatingCellDepositionRoutine _depositionRoutine;
|
|
|
#endregion
|
|
|
|
|
|
+ #region 属性
|
|
|
+ #endregion
|
|
|
|
|
|
#endregion
|
|
|
/// <summary>
|
|
|
@@ -147,6 +149,8 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
public PlatingCellRunRecipeRoutine(string module) : base(module)
|
|
|
{
|
|
|
_interRinseRoutine = new PlatingCellInterRinseRoutine(module);
|
|
|
+ _entryRoutine = new PlatingCellEntryRoutine(module);
|
|
|
+ _depositionRoutine = new PlatingCellDepositionRoutine(module);
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 中止
|
|
|
@@ -160,112 +164,25 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public RState Monitor()
|
|
|
- { //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; })
|
|
|
+ { //interval rinse
|
|
|
+ Runner.RunIf(RunRecipeStep.InterRinse, _recipe.RinseBeforeEntryEnable, () => { return _interRinseRoutine.Start(_recipe, _targetPositionList[0]) == RState.Running; })
|
|
|
.WaitWithStopConditionIf(RunRecipeStep.CheckInterRinse, _recipe.RinseBeforeEntryEnable, CheckInterRinseEndStatus,
|
|
|
() => CommonFunction.CheckRoutineStopState(_interRinseRoutine))
|
|
|
- //启动Rotation/Rotation 设置为entry 转速 (没有intercal rinse 在entry开始的时候启动rotation)
|
|
|
- .RunIf(RunRecipeStep.RotationStartEntry, !_recipe.RinseBeforeEntryEnable, RotationStartEntry, _delay_1ms)
|
|
|
- //有intercal rinse 直接变速 (rotation在interval rinse的时候已经启动了)
|
|
|
- .RunIf(RunRecipeStep.RotationChangeToEntrySpeed, _recipe.RinseBeforeEntryEnable, () => { return ChangeSpeed(_recipe.EntrySpinSpeed); }, _delay_1ms)
|
|
|
- //Angle tilt 操作
|
|
|
- .Run(RunRecipeStep.AngleTilt, _device.HeadtTiltAction, () => { return _device.PlatingCellDeviceData.IsHeadTilt; }, _delay_1s)
|
|
|
- //vertical goto plate
|
|
|
- .Run(RunRecipeStep.VerticalGotoPlate, () => { return StartVertical("Plate", _recipe.EntryZoffset); }, _delay_1ms)
|
|
|
- //vertical 到达entry位置前110ms (多10ms)
|
|
|
- .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromRinse, !_recipe.RinseBeforeEntryEnable, CalculateVerticaMoveTime("Rinse", "Entry") - 110 > 0 ? CalculateVerticaMoveTime("Rinse", "Entry") : 0)
|
|
|
- .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromHome, _recipe.RinseBeforeEntryEnable, CalculateVerticaMoveTime("Home", "Entry") - 110 > 0 ? CalculateVerticaMoveTime("Home", "Entry") : 0)
|
|
|
- //有上电保护,此刻给电
|
|
|
- .RunIf(RunRecipeStep.RunPowerStepWithEntryProtect, !_recipe.IsEntryTypeCold,StartPowerStep, _delay_1ms)
|
|
|
- //检查vertical到达plate位置
|
|
|
- .WaitWithStopCondition(RunRecipeStep.CheckVerticalGotoPlate, CheckVerticalEnd, CheckVerticalError)
|
|
|
- //Angle vertical操作
|
|
|
- .Run(RunRecipeStep.AngleVertical, _device.HeadtVerticalAction, () => { return _device.PlatingCellDeviceData.IsHeadVertical; }, _delay_1s)
|
|
|
- //如果不需要上电保护,执行plating delay
|
|
|
- .RunIf(RunRecipeStep.WaitPlatingDelay, _recipe.IsEntryTypeCold, NullFun, _recipe.PlatingDelay)
|
|
|
- //没有上电保护,此刻给电
|
|
|
- .RunIf(RunRecipeStep.RunPowerStep, _recipe.IsEntryTypeCold, StartPowerStep, _delay_1ms)
|
|
|
- .WaitWithStopCondition(RunRecipeStep.RunPowerStepWait, CheckRecipeStepEndStatus, CheckRecipeStepStopStatus, _delay_1ms)
|
|
|
+ //entry
|
|
|
+ .Run(RunRecipeStep.Entry, () => { return _entryRoutine.Start(_recipe, _targetPositionList[0], _powerSupplierStepPeriodDatas,_platingStartTime) == RState.Running; })
|
|
|
+ .WaitWithStopCondition(RunRecipeStep.CheckEntry, CheckInterRinseEndStatus,
|
|
|
+ () => CommonFunction.CheckRoutineStopState(_entryRoutine))
|
|
|
+
|
|
|
+ //Deposition
|
|
|
+ .Run(RunRecipeStep.Deposition, () => { return _depositionRoutine.Start(_recipe, _isZeroCurrent, _isRecipeContainsRevserseRotation,_powerSupplierStepPeriodDatas, _platingStartTime) == RState.Running; })
|
|
|
+ .WaitWithStopCondition(RunRecipeStep.CheckDeposition, CheckInterRinseEndStatus,
|
|
|
+ () => CommonFunction.CheckRoutineStopState(_depositionRoutine))
|
|
|
+
|
|
|
.End(RunRecipeStep.End, NullFun);
|
|
|
return Runner.Status;
|
|
|
}
|
|
|
- /// <summary>
|
|
|
- /// 启动PowerSupplier
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- private bool StartPowerStep()
|
|
|
- {
|
|
|
- bool result = _device.PowerSupplier.StartSetStepPeriodNoWaitEnd(_powerSupplierStepPeriodDatas);
|
|
|
- if (!result)
|
|
|
- {
|
|
|
- _device.PowerSupplier.DisableOperation("", null);
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 检验Powerstep是否启动完成
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- private bool CheckRecipeStepEndStatus()
|
|
|
- {
|
|
|
- if (_isZeroCurrent)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return _device.PowerSupplier.Status == RState.End;
|
|
|
-
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 检验Powerstep是否启动失败
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- private bool CheckRecipeStepStopStatus()
|
|
|
- {
|
|
|
- if (_isZeroCurrent)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return _device.PowerSupplier.Status == RState.Failed || _device.PowerSupplier.Status == RState.Timeout;
|
|
|
- }
|
|
|
- /// <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);
|
|
|
@@ -273,62 +190,6 @@ 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(string positionName,double offset)
|
|
|
- {
|
|
|
- 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 + offset);
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 检验垂直电机是否运动完成
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- private bool CheckVerticalEnd()
|
|
|
- {
|
|
|
- return _verticalEntity.IsIdle;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 检验垂直是否出现错误
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- private bool CheckVerticalError()
|
|
|
- {
|
|
|
- return _verticalEntity.IsError;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
/// 启动
|
|
|
/// </summary>
|
|
|
/// <param name="objs"></param>
|