using System; using XP.Hardware.MotionControl.Abstractions; using XP.Hardware.MotionControl.Abstractions.Enums; using XP.Hardware.Plc.Abstractions; namespace XP.Hardware.MotionControl.Implementations { /// /// 基于 PLC 的直线轴实现 | PLC-based Linear Axis Implementation /// 通过 ISignalDataService 与 PLC 通信,信号名称硬编码在 MotionSignalNames 中 /// Communicates with PLC via ISignalDataService, signal names hardcoded in MotionSignalNames /// public class PlcLinearAxis : LinearAxisBase { private readonly ISignalDataService _signalService; private readonly string _readSignal; private readonly string _writeSignal; private readonly string _speedSignal; private readonly string _jogPosSignal; private readonly string _jogNegSignal; private readonly string _homeSignal; private readonly string _stopSignal; private readonly string _limitPosSignal; private readonly string _limitNegSignal; /// /// 构造函数 | Constructor /// public PlcLinearAxis( AxisId axisId, double min, double max, double origin, ISignalDataService signalService, string readSignal, string writeSignal, string speedSignal, string jogPosSignal, string jogNegSignal, string homeSignal, string stopSignal) : base(axisId, min, max, origin) { _signalService = signalService ?? throw new ArgumentNullException(nameof(signalService)); _readSignal = readSignal; _writeSignal = writeSignal; _speedSignal = speedSignal; _jogPosSignal = jogPosSignal; _jogNegSignal = jogNegSignal; _homeSignal = homeSignal; _stopSignal = stopSignal; _limitPosSignal = $"MC_{axisId}_LimitPos"; _limitNegSignal = $"MC_{axisId}_LimitNeg"; } /// public override MotionResult MoveToTarget(double target, double? speed = null) { if (!ValidateTarget(target)) return MotionResult.Fail($"目标位置 {target} 超出范围 [{_min}, {_max}]"); if (Status == AxisStatus.Moving) return MotionResult.Fail($"轴 {_axisId} 正在运动中,拒绝重复命令"); if (speed.HasValue) _signalService.EnqueueWrite(_speedSignal, (float)speed.Value); _signalService.EnqueueWrite(_writeSignal, (float)target); Status = AxisStatus.Moving; return MotionResult.Ok(); } /// public override MotionResult JogStart(bool positive) { if (Status == AxisStatus.Homing) return MotionResult.Fail($"轴 {_axisId} 正在回零,拒绝 Jog 命令"); var signal = positive ? _jogPosSignal : _jogNegSignal; _signalService.EnqueueWrite(signal, true); return MotionResult.Ok(); } /// public override MotionResult JogStop() { _signalService.EnqueueWrite(_jogPosSignal, false); _signalService.EnqueueWrite(_jogNegSignal, false); return MotionResult.Ok(); } /// public override MotionResult Home() { _signalService.EnqueueWrite(_homeSignal, true); Status = AxisStatus.Homing; return MotionResult.Ok(); } /// public override MotionResult Stop() { _signalService.EnqueueWrite(_stopSignal, true); return MotionResult.Ok(); } /// public override void UpdateStatus() { ActualPosition = _signalService.GetValueByName(_readSignal); try { PositiveLimitHit = _signalService.GetValueByName(_limitPosSignal); } catch { } try { NegativeLimitHit = _signalService.GetValueByName(_limitNegSignal); } catch { } if (PositiveLimitHit || NegativeLimitHit) Status = AxisStatus.Alarm; } } }