|
|
@@ -4,6 +4,7 @@ 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.CommonData.PowerSupplier;
|
|
|
using MECF.Framework.Common.RecipeCenter;
|
|
|
using MECF.Framework.Common.Routine;
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
|
@@ -13,9 +14,12 @@ using PunkHPX8_Core;
|
|
|
using PunkHPX8_RT.Devices.AXIS;
|
|
|
using PunkHPX8_RT.Devices.Facilities;
|
|
|
using PunkHPX8_RT.Devices.PlatingCell;
|
|
|
+using PunkHPX8_RT.Devices.PowerSupplier;
|
|
|
using PunkHPX8_RT.Modules.Reservoir;
|
|
|
+using SecsGem.Core.ItemModel;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
@@ -38,8 +42,12 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
VerticalGotoPlate,
|
|
|
WaitEntryCurrentProtectedFromRinse,
|
|
|
WaitEntryCurrentProtectedFromHome,
|
|
|
- EntryCurrentProtected,
|
|
|
- CheckVertical,
|
|
|
+ RunPowerStepWithEntryProtect,
|
|
|
+ CheckVerticalGotoPlate,
|
|
|
+ AngleVertical,
|
|
|
+ WaitPlatingDelay,
|
|
|
+ RunPowerStep,
|
|
|
+ RunPowerStepWait,
|
|
|
End
|
|
|
}
|
|
|
#region 常量
|
|
|
@@ -101,7 +109,33 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// <summary>
|
|
|
/// run recipe 过程中电机会停的位置(需要根据recipe计算出来)
|
|
|
/// </summary>
|
|
|
- private List<int> _targetPositionList = new List<int>();
|
|
|
+ private List<int> _targetPositionList = new List<int>();
|
|
|
+
|
|
|
+
|
|
|
+ #region 电镀通电相关
|
|
|
+ /// <summary>
|
|
|
+ /// PlatingDelay计时
|
|
|
+ /// </summary>
|
|
|
+ private DateTime _hotPlatingRunTime;
|
|
|
+ /// <summary>
|
|
|
+ /// 不通电
|
|
|
+ /// </summary>
|
|
|
+ private bool _isZeroCurrent = false;
|
|
|
+ /// <summary>
|
|
|
+ /// 通电时长
|
|
|
+ /// </summary>
|
|
|
+ private int _totalMicrosecond = 0;
|
|
|
+ /// <summary>
|
|
|
+ /// Power 集合
|
|
|
+ /// </summary>
|
|
|
+ List<PowerSupplierStepPeriodData> _powerSupplierStepPeriodDatas = new List<PowerSupplierStepPeriodData>();
|
|
|
+ /// <summary>
|
|
|
+ /// 记录dep recipe中出现的最大电流,用于启动电源前切换挡位
|
|
|
+ /// </summary>
|
|
|
+ private double _maxCurrent = 0;
|
|
|
+ #endregion
|
|
|
+
|
|
|
+
|
|
|
#endregion
|
|
|
/// <summary>
|
|
|
/// 构造函数
|
|
|
@@ -124,25 +158,77 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
/// <returns></returns>
|
|
|
public RState Monitor()
|
|
|
{ //vertical去rinse位置
|
|
|
- Runner.RunIf(RunRecipeStep.VerticalGotoRinse, _recipe.RinseBeforeEntryEnable, () => { return StartVertical("Rinse",_recipe.IntervalRinseZoffset); }, _delay_1ms)
|
|
|
+ Runner.RunIf(RunRecipeStep.VerticalGotoRinse, _recipe.RinseBeforeEntryEnable, () => { return StartVertical("Rinse", _recipe.IntervalRinseZoffset); }, _delay_1ms)
|
|
|
.WaitWithStopConditionIf(RunRecipeStep.CheckVerticalGotoRinse, _recipe.RinseBeforeEntryEnable, CheckVerticalEnd, CheckVerticalError)
|
|
|
- //执行interval rinse
|
|
|
+ //执行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))
|
|
|
- //启动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 直接变速
|
|
|
+ //启动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.HeadTilt; }, _delay_1s)
|
|
|
+ .Run(RunRecipeStep.AngleTilt, _device.HeadtTiltAction, () => { return _device.PlatingCellDeviceData.IsHeadTilt; }, _delay_1s)
|
|
|
+ //vertical goto plate
|
|
|
.Run(RunRecipeStep.VerticalGotoPlate, () => { return StartVertical("Plate", _recipe.EntryZoffset); }, _delay_1ms)
|
|
|
- .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromRinse, !_recipe.RinseBeforeEntryEnable,CalculateVerticaMoveTime("Rinse","Entry") - 110 > 0 ? CalculateVerticaMoveTime("Rinse", "Entry"):0) //提前110ms,多10ms
|
|
|
- .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromHome, _recipe.RinseBeforeEntryEnable,CalculateVerticaMoveTime("Home","Entry") - 110 > 0 ? CalculateVerticaMoveTime("Home", "Entry") : 0)
|
|
|
-
|
|
|
+ //vertical 到达entry位置前110ms
|
|
|
+ .DelayIf(RunRecipeStep.WaitEntryCurrentProtectedFromRinse, !_recipe.RinseBeforeEntryEnable, CalculateVerticaMoveTime("Rinse", "Entry") - 110 > 0 ? CalculateVerticaMoveTime("Rinse", "Entry") : 0) //提前110ms,多10ms
|
|
|
+ .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)
|
|
|
.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>
|
|
|
@@ -279,12 +365,63 @@ namespace PunkHPX8_RT.Modules.PlatingCell
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
CalculatVerticalPosition(_recipe);
|
|
|
+ UpdatePowerStepDatas();
|
|
|
_currentCycle = 0;
|
|
|
|
|
|
|
|
|
return Runner.Start(Module, "Run Recipe");
|
|
|
}
|
|
|
/// <summary>
|
|
|
+ /// 初始化Power step步骤
|
|
|
+ /// </summary>
|
|
|
+ private bool UpdatePowerStepDatas()
|
|
|
+ {
|
|
|
+ _isZeroCurrent = false;
|
|
|
+ double current = 0;
|
|
|
+ _totalMicrosecond = 0;
|
|
|
+ _powerSupplierStepPeriodDatas.Clear();
|
|
|
+ if (!_recipe.IsEntryTypeCold)//如果entry带上电保护,那么把上电保护的部分加到步阶电流的第一步
|
|
|
+ {
|
|
|
+ PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData(); //上电保护时间(提前上电时间+延迟时间)
|
|
|
+ step.Hour = 0;
|
|
|
+ step.Minute = (ushort)((_recipe.PlatingDelay) / 60);
|
|
|
+ step.Second = (ushort)(_recipe.PlatingDelay % 60);
|
|
|
+ step.Microsecond = 110; //到达entry位置提前100ms上电,提前一丢丢
|
|
|
+ step.Voltage = _recipe.DepMaxVoltageWarning;
|
|
|
+ _powerSupplierStepPeriodDatas.Add(step);
|
|
|
+
|
|
|
+ }
|
|
|
+ foreach (var item in _recipe.DepSteps)
|
|
|
+ {
|
|
|
+ PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData();
|
|
|
+ step.Current = item.CurrentValue;
|
|
|
+ if(item.CurrentValue > _maxCurrent)
|
|
|
+ {
|
|
|
+ _maxCurrent = item.CurrentValue;
|
|
|
+ }
|
|
|
+ step.Hour = (ushort)(item.DurartionSeconds / 3600);
|
|
|
+ step.Minute = (ushort)((item.DurartionSeconds - step.Hour * 3600) / 60);
|
|
|
+ step.Second = (ushort)(item.DurartionSeconds % 60);
|
|
|
+ step.Microsecond = 0;
|
|
|
+ step.Voltage = _recipe.DepMaxVoltageWarning;
|
|
|
+ _powerSupplierStepPeriodDatas.Add(step);
|
|
|
+ current += step.Current;
|
|
|
+ _totalMicrosecond += item.DurartionSeconds * 1000;
|
|
|
+ }
|
|
|
+ if (current == 0)
|
|
|
+ {
|
|
|
+ _isZeroCurrent = true;
|
|
|
+ }
|
|
|
+ if(_maxCurrent > 0.6) //设置电源挡位,有超过0.6A的电流则用高档,否则用中挡
|
|
|
+ {
|
|
|
+ return _device.PowerSupplier.SetPowerGrade("set power grade high", new object[] { 2 });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return _device.PowerSupplier.SetPowerGrade("set power grade high", new object[] { 1 });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
/// 根据dep recipe计算出整个电镀过程中Rotation profile position可能去到的位置
|
|
|
/// </summary>
|
|
|
private void CalculatVerticalPosition(DepRecipe recipe)
|