using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Beckhoff.AxisProvider; using MECF.Framework.Common.Persistent.Reservoirs; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.Routine; using MECF.Framework.Common.ToolLayout; using MECF.Framework.Common.Utilities; using PunkHPX8_Core; using PunkHPX8_RT.Devices.AXIS; using PunkHPX8_RT.Devices.PlatingCell; using PunkHPX8_RT.Devices.Reservoir; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PunkHPX8_RT.Modules.PlatingCell { public class PlatingCellCCRRoutine : RoutineBase, IRoutine { private enum CCRStep { CSRStart, CSRClamshellClose, CSROpenRinseValve, CSRStartRotation, CSRRinseMonitor, CSRCloseRinseValve, CSRSetDryRotationSpeed, CSRCheckRotationStoped, CCR1Start, CCR1ClamshellOpen, OpenCCR1Valve, CCR1StartRotation, CCR1CCRMonitor, CCR1CloseCCRValve, CCR1SetDryRotationSpeed, CCR1CheckRotationStoped, CCR2Start, CCR2ClamshellOpen, OpenCCR2Valve, CCR2StartRotation, CCR2CCRMonitor, CCR2CloseCCRValve, CCR2SetDryRotationSpeed, CCR2CheckRotationStoped, End } #region 常量 /// /// ROTATION电机转速比例 /// private const int SPEED_RATIO = 1; #endregion #region 内部变量 /// /// 设备对象 /// private PlatingCellDevice _platingCellDevice; /// /// Rotation axis /// private JetAxisBase _rotationAxis; /// /// SRD rotation Provider对象 /// private BeckhoffProviderAxis _rotationProviderAxis; /// /// startRotationTime,用于控制速度改变 /// private int _startRotationTime; /// /// 当前执行到哪一步的显示 /// private string _currentStep; /// /// 当前执行到哪一步的剩余时间 /// private double _timeRemain; private bool _cSREnable; private bool _cCR1Enable; private bool _cCR2Enable; private int _cSRRinseSpeed; private int _cSRDrySpeed; private double _cSRRinseTime; private double _cSRDryTime; private int _cCR1RinseSpeed; private int _cCR1DrySpeed; private double _cCR1RinseTime; private double _cCR1DryTime; private int _cCR2RinseSpeed; private int _cCR2DrySpeed; private double _cCR2RinseTime; private double _cCR2DryTime; /// /// CCR小步骤的启动时间 /// private DateTime _cSRStartTime; private DateTime _cCR1StartTime; private DateTime _cCR2StartTime; #endregion /// /// 构造函数 /// /// public PlatingCellCCRRoutine(string module) : base(module) { } /// /// 中止 /// public void Abort() { Runner.Stop("CCR Manual Abort"); } /// /// 监控 /// /// public RState Monitor() { CheckCurrentStepAndTimeRemain(); _platingCellDevice.UpdateStatus(_currentStep); Runner.RunIf(CCRStep.CSRStart, _cSREnable , () => RecordCCRStepStartTime(out _cSRStartTime), _delay_1ms) .RunIf(CCRStep.CSRClamshellClose, _cSREnable , () => _platingCellDevice.ClamShellClose(), CheckClamShellClosed, _delay_1ms) .RunIf(CCRStep.CSROpenRinseValve, _cSREnable, OpenRinseValve, _delay_1ms) .RunIf(CCRStep.CSRStartRotation, _cSREnable, () => CSRStartRotation(), _delay_1ms) .WaitIf(CCRStep.CSRRinseMonitor, _cSREnable, MonitorCSRRinseRotationEndStatus) .RunIf(CCRStep.CSRCloseRinseValve, _cSREnable, CloseRinseValve, _delay_1ms) .RunIf(CCRStep.CSRSetDryRotationSpeed, _cSREnable, () => ChangeRotationSpeed(_cSRDrySpeed), _delay_1ms) .WaitWithStopConditionIf(CCRStep.CSRCheckRotationStoped, _cSREnable, CheckRotationEndStatus, CheckRotationStopStatus) .RunIf(CCRStep.CCR1Start, _cCR1Enable, () => RecordCCRStepStartTime(out _cCR1StartTime), _delay_1ms) .RunIf(CCRStep.CCR1ClamshellOpen, _cCR1Enable, () => _platingCellDevice.ClamShellOpen(), CheckClamShellOpen, _delay_1ms) .RunIf(CCRStep.OpenCCR1Valve, _cCR1Enable, OpenCCRValve, _delay_1ms) .RunIf(CCRStep.CCR1StartRotation, _cCR1Enable, () => CCR1StartRotation(), _delay_1ms) .WaitIf(CCRStep.CCR1CCRMonitor, _cCR1Enable, MonitorCCR1RotationEndStatus) .RunIf(CCRStep.CCR1CloseCCRValve, _cCR1Enable, CloseCCRValve, _delay_1ms) .RunIf(CCRStep.CCR1SetDryRotationSpeed, _cCR1Enable, () => ChangeRotationSpeed(_cCR1DrySpeed), _delay_1ms) .WaitWithStopConditionIf(CCRStep.CCR1CheckRotationStoped, _cCR1Enable, CheckRotationEndStatus, CheckRotationStopStatus) .RunIf(CCRStep.CCR2Start, _cCR2Enable, () => RecordCCRStepStartTime(out _cCR2StartTime), _delay_1ms) .RunIf(CCRStep.CCR2ClamshellOpen, _cCR2Enable, () => _platingCellDevice.ClamShellOpen(), CheckClamShellOpen, _delay_1ms) .RunIf(CCRStep.OpenCCR2Valve, _cCR2Enable, OpenCCRValve, _delay_1ms) .RunIf(CCRStep.CCR2StartRotation, _cCR2Enable, () => CCR2StartRotation(), _delay_1ms) .WaitIf(CCRStep.CCR2CCRMonitor, _cCR2Enable, MonitorCCR2RotationEndStatus) .RunIf(CCRStep.CCR2CloseCCRValve, _cCR2Enable, CloseCCRValve, _delay_1ms) .RunIf(CCRStep.CCR2SetDryRotationSpeed, _cCR2Enable, () => ChangeRotationSpeed(_cCR2DrySpeed), _delay_1ms) .WaitWithStopConditionIf(CCRStep.CCR2CheckRotationStoped, _cCR2Enable, CheckRotationEndStatus, CheckRotationStopStatus) .End(CCRStep.End, NullFun, _delay_1ms); return Runner.Status; } /// /// 记录ccr step 起始时间 /// /// /// private bool RecordCCRStepStartTime(out DateTime dateTime) { dateTime = DateTime.Now; return true; } /// /// 判断当前处于ccr的哪一步 /// private void CheckCurrentStepAndTimeRemain() { string currentStep = Runner.CurrentStep.ToString(); if (currentStep.Contains("CSR")) { _currentStep ="CSR Rinse/Dry"; _timeRemain = _cSRRinseTime + _cSRDryTime - (DateTime.Now - _cSRStartTime).TotalSeconds > 0 ? _cSRRinseTime + _cSRDryTime - (DateTime.Now - _cSRStartTime).TotalSeconds : 0; } else if (currentStep.Contains("CCR1")) { _currentStep = "CCR Cycle1 Rinse/Dry"; _timeRemain = _cCR1RinseTime + _cCR1DryTime - (DateTime.Now - _cCR1StartTime).TotalSeconds > 0 ? _cCR1RinseTime + _cCR1DryTime - (DateTime.Now - _cCR1StartTime).TotalSeconds : 0; } else if (currentStep.Contains("CCR2")) { _currentStep = "CCR Cycle2 Rinse/Dry"; _timeRemain = _cCR2RinseTime + _cCR2DryTime - (DateTime.Now - _cCR2StartTime).TotalSeconds > 0 ? _cCR2RinseTime + _cCR2DryTime - (DateTime.Now - _cCR2StartTime).TotalSeconds : 0; } else { _currentStep = "End"; _timeRemain = 0; } _platingCellDevice.UpdateCCRTimeRemain(_timeRemain); } /// /// 打开CCR valve /// /// private bool OpenCCRValve() { return _platingCellDevice.CCREnableAction(); } /// /// 关闭CCR valve /// /// private bool CloseCCRValve() { return _platingCellDevice.CCRDisableAction(); } /// /// 打开Rinse valve /// /// private bool OpenRinseValve() { return _platingCellDevice.RinseEnableAction(); } /// /// 关闭Rinse valve /// /// private bool CloseRinseValve() { return _platingCellDevice.RinseDisableAction(); } /// /// 检查ClamShell是否closed /// /// private bool CheckClamShellClosed() { return _platingCellDevice.PlatingCellDeviceData.ClamShellClose; } /// /// 检查ClamShell是否Open /// /// private bool CheckClamShellOpen() { return !_platingCellDevice.PlatingCellDeviceData.ClamShellClose; } /// /// 检验Rotation是否停止 /// /// private bool CheckRotationEndStatus() { if (!_rotationAxis.IsRun && _rotationAxis.Status == RState.End) { return true; } return false; } /// /// 检验Rotation停止状态 /// /// private bool CheckRotationStopStatus() { if (_rotationAxis.Status == RState.Failed || _rotationAxis.Status == RState.Timeout) { NotifyError(eEvent.ERR_PLATINGCELL, $"{Module}.Rotation is failed", 0); return true; } return false; } /// /// CSR阶段rotation开始旋转 /// /// /// private bool CSRStartRotation() { double _scale = _rotationProviderAxis.ScaleFactor; //rinse 目标位置 double rinsePosition = _cSRRinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRRinseSpeed); //dry目标位置 double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRDrySpeed) * _cSRDryTime; int targetPosition = (int)Math.Round((rinsePosition + dryPosition ) * _scale, 0); int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cSRRinseSpeed), 0); //启动先用rinse的speed,时间到了转成用dry的speed bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0); if (!result) { NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0); return false; } LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CSR Step Rinse Rotation"); //Rinse开始时间 _startRotationTime = Environment.TickCount; return true; } /// /// WaterFlow End Monitor /// /// private bool MonitorCSRRinseRotationEndStatus() { int ticks = Environment.TickCount - _startRotationTime; if (ticks >= _cSRRinseTime * 1000) { return true; } return false; } /// /// CCR1阶段rotation开始旋转 /// /// /// private bool CCR1StartRotation() { double _scale = _rotationProviderAxis.ScaleFactor; //rinse 目标位置 double rinsePosition = _cCR1RinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1RinseSpeed); //dry目标位置 double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1DrySpeed) * _cCR1DryTime; int targetPosition = (int)Math.Round((rinsePosition + dryPosition) * _scale, 0); int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR1RinseSpeed), 0); //启动先用rinse的speed,时间到了转成用dry的speed bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0); if (!result) { NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0); return false; } LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CCR1 Step Rinse Rotation"); //Rinse开始时间 _startRotationTime = Environment.TickCount; return true; } /// /// CCR1 WaterFlow End Monitor /// /// private bool MonitorCCR1RotationEndStatus() { int ticks = Environment.TickCount - _startRotationTime; if (ticks >= _cCR1RinseTime * 1000) { return true; } return false; } /// /// CCR2阶段rotation开始旋转 /// /// /// private bool CCR2StartRotation() { double _scale = _rotationProviderAxis.ScaleFactor; //rinse 目标位置 double rinsePosition = _cCR2RinseTime * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2RinseSpeed); //dry目标位置 double dryPosition = BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2DrySpeed) * _cCR2DryTime; int targetPosition = (int)Math.Round((rinsePosition + dryPosition) * _scale, 0); int rotationSpeed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(_cCR2RinseSpeed), 0); //启动先用rinse的speed,时间到了转成用dry的speed bool result = _rotationAxis.ProfilePosition(targetPosition, rotationSpeed * SPEED_RATIO, 0, 0); if (!result) { NotifyError(eEvent.ERR_PLATINGCELL, "Start Rotation is failed", 0); return false; } LOG.WriteLog(eEvent.INFO_PLATINGCELL, Module, "Start CCR2 Step Rinse Rotation"); //Rinse开始时间 _startRotationTime = Environment.TickCount; return true; } /// /// CCR2 WaterFlow End Monitor /// /// private bool MonitorCCR2RotationEndStatus() { int ticks = Environment.TickCount - _startRotationTime; if (ticks >= _cCR2RinseTime * 1000) { return true; } return false; } /// /// 改变速度 /// /// /// private bool ChangeRotationSpeed(int speed) { double _scale = _rotationProviderAxis.ScaleFactor; speed = (int)Math.Round(_scale * BeckhoffVelocityUtil.ConvertVelocityToDegPerSecondByRPM(speed), 0); return _rotationAxis.ChangeSpeed(speed); } /// /// 启动 /// /// /// public RState Start(params object[] objs) { _platingCellDevice = DEVICE.GetDevice(Module); _cSREnable = SC.GetValue("PlatingCell.CSR.CSREnable"); _cCR1Enable = SC.GetValue("PlatingCell.CCR1.CCR1Enable"); _cCR2Enable = SC.GetValue("PlatingCell.CCR2.CCR2Enable"); _cSRRinseSpeed = SC.GetValue("PlatingCell.CSR.RinseSpeed"); _cSRDrySpeed = SC.GetValue("PlatingCell.CSR.DrySpeed"); _cSRRinseTime = SC.GetValue("PlatingCell.CSR.RinseTime"); _cSRDryTime = SC.GetValue("PlatingCell.CSR.DryTime"); _cCR1RinseSpeed = SC.GetValue("PlatingCell.CCR1.RinseSpeed"); _cCR1DrySpeed = SC.GetValue("PlatingCell.CCR1.DrySpeed"); _cCR1RinseTime = SC.GetValue("PlatingCell.CCR1.RinseTime"); _cCR1DryTime = SC.GetValue("PlatingCell.CCR1.DryTime"); _cCR2RinseSpeed = SC.GetValue("PlatingCell.CCR2.RinseSpeed"); _cCR2DrySpeed = SC.GetValue("PlatingCell.CCR2.DrySpeed"); _cCR2RinseTime = SC.GetValue("PlatingCell.CCR2.RinseTime"); _cCR2DryTime = SC.GetValue("PlatingCell.CCR2.DryTime"); _rotationAxis = DEVICE.GetDevice($"{Module}.Rotation"); _rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.Rotation"); if (_rotationProviderAxis == null) { NotifyError(eEvent.ERR_SRD, $"{Module}.Rotation Provider is not exist", 0); return RState.Failed; } return Runner.Start(Module, "Start Reservoir Initialize"); } } }