using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.CommonData.PUF; using MECF.Framework.Common.TwinCat; using PunkHPX8_Core; using PunkHPX8_RT.Modules; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using PunkHPX8_RT.Devices.AXIS.CanOpen; using MECF.Framework.Common.Device; using MECF.Framework.Common.Beckhoff.IOAxis; namespace PunkHPX8_RT.Devices.AXIS.CANOpen { public class CanOpenAxis : JetAxisBase { #region 内部变量 /// /// Home routine /// private CanOpenHomeRoutine _homeRoutine; /// /// 运动Routine /// private CanOpenProfilePositionRoutine _profilePositionRoutine; /// /// Switch On Routine /// private CanOpenSwitchOnRoutine _switchOnRoutine; /// /// Switch off Routine /// private CanOpenSwitchOffRoutine _switchOffRoutine; /// /// Stop Position /// private CanOpenStopPositionRoutine _stopPositionRoutine; /// /// Beckhoff共用对象 /// private BeckhoffCommonAxis _beckhoffCommonAxis; #endregion /// /// 构造函数 /// /// public CanOpenAxis(string module,string name):base(module,name) { } /// /// 初始化参数 /// protected override void InitializeParameter() { _speedRatio = 10; _torqueRatio = 1000; _accelerationRatio = 1; _beckhoffCommonAxis = new BeckhoffCommonAxis(Module, Name, this); } /// /// 初始化Routine /// protected override void InitializeRoutine() { _homeRoutine = new CanOpenHomeRoutine($"{Module}.{Name}",this, _beckhoffCommonAxis); _profilePositionRoutine = new CanOpenProfilePositionRoutine($"{Module}.{Name}", this,_beckhoffCommonAxis); _switchOnRoutine = new CanOpenSwitchOnRoutine($"{Module}.{Name}", this,_beckhoffCommonAxis); _switchOffRoutine = new CanOpenSwitchOffRoutine($"{Module}.{Name}", this,_beckhoffCommonAxis); _stopPositionRoutine = new CanOpenStopPositionRoutine($"{Module}.{Name}", this, _beckhoffCommonAxis); } /// /// 中止操作 /// /// /// /// public override bool StopPositionOperation() { lock (_operationLocker) { if (_currentOperation==MotionOperation.Position&&_profilePositionRoutine.Monitor() == RState.Running) { _profilePositionRoutine.Abort(); } _currentOperation = MotionOperation.StopPosition; _status = _stopPositionRoutine.Start(); } return true; } /// /// 更新StatusWord /// /// public override void UpdateStatusWord(ushort status) { if(status==0) { _commandMotionData.Status = "Status Word is zero"; return; } byte bit0 = (byte)(status & 0b0001); byte bit1= (byte)((status & 0b0010) >> 1); byte bit2 = (byte)((status & 0b0100) >> 2); byte bit3 = (byte)((status & 0b1000) >> 3); byte bit4 = (byte)((status & 0b10000) >> 4); byte bit5 = (byte)((status & 0b100000) >> 5); byte bit6 = (byte)((status & 0b1000000) >> 6); byte bit7 = (byte)((status & 0b10000000) >> 7); byte bit8 = (byte)((status & 0b100000000) >> 8); byte bit9 = (byte)((status & 0b1000000000) >> 9); byte bit10 = (byte)((status & 0b10000000000) >> 10); byte bit11 = (byte)((status & 0b100000000000) >> 11); byte bit12 = (byte)((status & 0b1000000000000) >> 12); byte bit13 = (byte)((status & 0b10000000000000) >> 13); byte bit14 = (byte)((status & 0b100000000000000) >> 14); if (bit0 == 0 && bit1 == 0 && bit2 == 0 && bit3 == 0) { if (bit6 == 0) { _commandMotionData.Status = "Not Ready to switch On"; } else { _commandMotionData.Status = "Switch On Disabled"; } UpdateSwitchOn(false); } else if(bit0 == 1 &&bit2==0&&bit3==0&&bit5==1&&bit6==0) { _commandMotionData.Status = "Ready to Switch On"; UpdateSwitchOn(false); } else if(bit0==1&&bit1==1&&bit2==0&&bit3==0&&bit5==1&&bit6==0) { _commandMotionData.Status = "Switched On"; UpdateSwitchOn(true); } else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 0 && bit5 == 1 && bit6 == 0) { _commandMotionData.Status = "Operation Enabled"; UpdateSwitchOn(true); } else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 0 && bit5 == 0 && bit6 == 0) { _commandMotionData.Status = "Quick Stop Active"; UpdateSwitchOn(true); } else if (bit0 == 1 && bit1 == 1 && bit2 == 1 && bit3 == 1 && bit6 == 0) { _commandMotionData.Status = "Fault reaction active"; UpdateSwitchOn(false); } else if (bit0 == 0 && bit1 == 0 && bit2 == 0 && bit3 == 1 && bit6 == 0) { _commandMotionData.Status = "Fault"; UpdateSwitchOn(false); } if (bit3==1) { _isError = true; } else { _isError = false; } if(bit7==1) { _commandMotionData.Status = "Waring is occured"; } if (bit4 == 0) { _commandMotionData.Status = "No Power"; } if (_modeOfOperation==(byte)AxisModeOfOperation.HomingMode) { if(bit10==1&&bit12==1) { _isHomed = true; } else { _isHomed= false; } } else if(_modeOfOperation==(byte)AxisModeOfOperation.ProfilePositionMode) { if(bit10==1) { _inTargetPosition = true; } } } /// /// 更新上电状态 /// private void UpdateSwitchOn(bool isSwitchOn) { if(!_isSwitchOn&&isSwitchOn) { _commandMotionData.IsSwitchOn = true; ConfirmOperationState(MotionOperation.SwitchOn); } else if(_isSwitchOn&&!isSwitchOn) { _commandMotionData.IsSwitchOn = false; ConfirmOperationState(MotionOperation.SwitchOff); } _isSwitchOn = isSwitchOn; } /// /// Home /// public override bool Home() { bool result = base.Home(); if(!result) { return false; } _homeRoutine.Start(_homeTimeout,_axisConfig.HomingMethod); MotionData.IsHomed = false; IsHomeSwitchedTriggered = false; return true; } /// /// Home /// public override bool Home(bool isLogError) { bool result = base.Home(isLogError); if (!result) { return false; } _homeRoutine.Start(_homeTimeout, _axisConfig.HomingMethod, isLogError); MotionData.IsHomed = false; IsHomeSwitchedTriggered = false; return true; } /// /// 停止 /// public override void Stop() { } /// /// SwitchOff /// public override bool SwitchOff() { if (_status == RState.Running) { EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot switchoff"); return false; } _currentOperation = MotionOperation.SwitchOff; _switchOffRoutine.Start(); _status = RState.Running; return true; } /// /// SwitchOn /// public override bool SwitchOn() { if (_status == RState.Running) { EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot SwitchOn"); return false; } _currentOperation = MotionOperation.SwitchOn; _switchOnRoutine.Start(); _status = RState.Running; return true; } /// /// 首次启动写入COE线程 /// public override void FirstStartUpWriteCOE(string variable) { _beckhoffCommonAxis.FirstStartUpWriteCOE(variable); } /// /// 启动写入COE线程 /// public override void StartUpWriteCoeThread() { _beckhoffCommonAxis.StartUpWriteCoeThread(); } /// /// OnTimer 定时器执行 /// public override bool OnTimer() { lock (_operationLocker) { if (_status == RState.Running) { if (_currentOperation == MotionOperation.Position) { RState state = _profilePositionRoutine.Monitor(); if (state == RState.End) { _inTargetPosition = false; EndOperation(); _status = RState.End; LOG.WriteLog(eEvent.INFO_AXIS, $"{Module}.{Name}", $"Position Complete,Current Position {MotionData.MotorPosition}"); } else if (state == RState.Failed || state == RState.Timeout) { if (_currentOperation == MotionOperation.Position) { _inTargetPosition = false; EndOperation(); _status = RState.Failed; LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", $"Profile Position error {_profilePositionRoutine.ErrorMsg}"); } } } else if (_currentOperation == MotionOperation.Home) { RState state = _homeRoutine.Monitor(); if (state == RState.End) { MotionData.IsHomed = true; IsHomed = true; EndOperation(); _status = RState.End; } else if (state == RState.Failed || state == RState.Timeout) { EndOperation(); _status = RState.Failed; LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Home error"); } } else if (_currentOperation == MotionOperation.SwitchOn) { RState state = _switchOnRoutine.Monitor(); if (state == RState.End) { EndOperation(); _status = RState.End; } else if (state == RState.Failed || state == RState.Timeout) { EndOperation(); _status = RState.Failed; LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Switch On error"); } } else if (_currentOperation == MotionOperation.SwitchOff) { RState state = _switchOffRoutine.Monitor(); if (state == RState.End) { EndOperation(); _status = RState.End; } else if (state == RState.Failed || state == RState.Timeout) { EndOperation(); _status = RState.Failed; LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "Switch Off error"); } } else if (_currentOperation == MotionOperation.StopPosition) { RState state = _stopPositionRoutine.Monitor(); if (state == RState.End) { EndOperation(); _status = RState.End; } else if (state == RState.Failed || state == RState.Timeout) { EndOperation(); _status = RState.Failed; LOG.WriteLog(eEvent.ERR_AXIS, $"{Module}.{Name}", "StopPosition error"); } } } } JudgeRunMonitor(); return true; } /// /// 位置 /// /// public override bool ProfilePosition(int targetPoint, int profileVelocity, int profileAcceleration, int profileDeceleration,bool judgeTorqueLimit=true) { if (_status == RState.Running) { EV.PostAlarmLog($"{Module}.{Name}", eEvent.ERR_AXIS, $"{Module}.{Name} current execute {_currentOperation},cannot profile position"); return false; } if(profileAcceleration==0) { profileAcceleration = _profileAcceleration; } if (profileDeceleration==0) { profileDeceleration = _profileDeceleration; } _status = _profilePositionRoutine.Start(targetPoint,profileVelocity,profileAcceleration,profileDeceleration,judgeTorqueLimit); _currentOperation = MotionOperation.Position; _inTargetPosition = false; return true; } /// /// StopProfilePosition /// /// /// /// 改变速度 /// /// /// public override bool ChangeSpeed(int speed) { bool result = _beckhoffCommonAxis.WriteControlWord(0x2F); if (!result) { return false; } result = BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.ProfileVelocity", speed); if (!result) { return false; } result = _beckhoffCommonAxis.WriteControlWord(0x3F); return result; } /// /// 改变速度加速度 /// /// /// public override bool ChangeSpeedAcceleration(int speed, int acceleration, int deceleration) { bool result =_beckhoffCommonAxis.WriteControlWord(0x2F); if (!result) { return false; } result = _beckhoffCommonAxis.WriteVariable("ProfileVelocity", speed); _beckhoffCommonAxis.WriteVariable(PROFILE_ACCEL, acceleration); _beckhoffCommonAxis.WriteVariable(PROFILE_DECEL, deceleration); if (!result) { return false; } result = _beckhoffCommonAxis.WriteControlWord(0x3F); return result; } /// /// KeyDown事件 /// /// /// protected override void AxisKeyDown(string arg, double value) { switch (arg) { case PROFILE_VELOCITY: _profileVelocity = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileProfileVelocity = value; BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{arg}", _profileVelocity); break; case PROFILE_ACCEL: _profileAcceleration =CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileAcceleration = value; BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{arg}", _profileAcceleration); break; case PROFILE_DECEL: _profileDeceleration =CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileDeceleration = value; BeckhoffAxisManager.Instance.WriteVariableValue($"{Module}.{Name}.{arg}", _profileDeceleration); break; case HOMING_VELOCITY: _profileHomingVelocity = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileHomingVelocity = value; TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingVelocity); break; case HOMING_VELOCITY_SLOW: _profileHomingVelocitySlow = CalculateMultiplySpeedRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileHomingVelocitySlow = value; TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingVelocitySlow); break; case HOMING_ACCEL: _profileHomingAccel = CalculateDivideAccelerationRatio(CalculateValueMultiplyScale(value)); _commandMotionData.FileHomingAccel = value; TwincatCoeManager.Instance.WriteVariableValue($"{Module}.{Name}", arg, _profileHomingAccel); break; } } /// /// 初始化Axis配置 /// /// protected override AxisConfig InitializeAxisConfig() { AxisConfig axisConfig= BeckhoffAxisManager.Instance.GetAxis($"{Module}.{Name}"); if (axisConfig != null) { BeckhoffAxis beckhoffAxis=axisConfig as BeckhoffAxis; _beckhoffCommonAxis.InitializeCoeOutputs(beckhoffAxis); } return axisConfig; } /// /// 订阅变量 /// protected override void SubscriptionVariable() { _beckhoffCommonAxis.SubscriptionVariable(); } } }