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;
}
}
}