轴诊断数据采集器AxesDiagPacketRetriever类的设计

internal class AxesDiagPacketRetriever
{
    private readonly Controller controller;

    private short[] itemCodes;

    private short[] axisNumbers;

    private int[] extraCodes;

    private static readonly short[] PerAxisItemCodes;

    private static readonly Dictionary<short, int> NonZeroExtraItemCodes;

    static AxesDiagPacketRetriever()
    {
        PerAxisItemCodes = new short[27]
        {
            10, 11, 28, 29, 36, 37, 38, 39, 49, 48,
            47, 8, 7, 15, 16, 14, 1, 0, 4, 3,
            90, 107, 6, 192, 376, 377, 443
        };
        NonZeroExtraItemCodes = new Dictionary<short, int>();
        NonZeroExtraItemCodes[90] = 0;
        NonZeroExtraItemCodes[107] = 0;
    }

    public AxesDiagPacketRetriever(Controller controller)
    {
        this.controller = controller;
    }

    private void EnsureRequestDataInitialized()
    {
        if (itemCodes == null)
        {
            itemCodes = StatusItemRetrievalHelper.CreateItemArray(PerAxisItemCodes, 32);
        }

        if (axisNumbers == null)
        {
            axisNumbers = StatusItemRetrievalHelper.CreateIndexArray(PerAxisItemCodes, 32);
        }

        if (extraCodes == null)
        {
            extraCodes = StatusItemRetrievalHelper.CreateExtraItemCodesArray(PerAxisItemCodes, 32, NonZeroExtraItemCodes);
        }
    }

    public KeyValuePair<DiagPacket[], double[]> GetAxesDiagnostics(UnitInformation toUnits)
    {
        if (toUnits == null)
        {
            throw new ArgumentNullException("toUnits");
        }

        EnsureRequestDataInitialized();
        int num = PerAxisItemCodes.Length * 32;
        double[] array = new double[num];
        ExceptionResolver.ResolveThrow(controller, Wrapper.AerStatusGetItems(controller.Handle.Value, num, axisNumbers, itemCodes, extraCodes, array));
        return ScaleAxesDiagnostics(array, new UnitInformation(DistanceUnit.Primary, TimeUnit.Seconds), toUnits);
    }

    public KeyValuePair<DiagPacket[], double[]> ScaleAxesDiagnostics(double[] rawData, UnitInformation fromUnits, UnitInformation toUnits)
    {
        EnsureRequestDataInitialized();
        _ = PerAxisItemCodes.Length;
        KeyValuePair<string, double>[] array = UnitUtilities.ConvertData(controller.Parameters, fromUnits, toUnits, itemCodes, axisNumbers, rawData);
        double[] value = Array.ConvertAll(array, (KeyValuePair<string, double> kvp) => kvp.Value);
        DiagPacket[] array2 = new DiagPacket[32];
        for (int i = 0; i < 32; i++)
        {
            array2[i] = interpretDiagnosticData(array, i);
        }

        return new KeyValuePair<DiagPacket[], double[]>(array2, value);
    }

    private DiagPacket interpretDiagnosticData(KeyValuePair<string, double>[] statusData, int axis)
    {
        _ = controller.Parameters.Axes[axis].Units.CountsPerUnit.CachedValue;
        KeyValuePair<string, double>[] dataForIndex = StatusItemRetrievalHelper.GetDataForIndex(statusData, PerAxisItemCodes, axis);
        DiagPacket result = default(DiagPacket);
        result.AnalogInput0 = dataForIndex[0].Value;
        result.AnalogInput1 = dataForIndex[1].Value;
        result.AnalogInput2 = dataForIndex[2].Value;
        result.AnalogInput3 = dataForIndex[3].Value;
        result.AnalogOutput0 = dataForIndex[4].Value;
        result.AnalogOutput1 = dataForIndex[5].Value;
        result.AnalogOutput2 = dataForIndex[6].Value;
        result.AnalogOutput3 = dataForIndex[7].Value;
        result.CurrentCommand = (float)dataForIndex[11].Value;
        result.CurrentFeedback = (float)dataForIndex[12].Value;
        result.DigitalInputs = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[13].Value);
        result.DigitalOutputs = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[14].Value);
        result.AxisFault = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[8].Value);
        result.AxisStatus = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[9].Value);
        result.DriveStatus = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[10].Value);
        result.PositionFeedbackAuxiliary = dataForIndex[15].Value;
        result.PositionCommand = dataForIndex[16].Value;
        result.PositionUnitName = dataForIndex[16].Key;
        result.PositionFeedback = dataForIndex[17].Value;
        result.VelocityCommand = dataForIndex[18].Value;
        result.VelocityUnitName = dataForIndex[18].Key;
        result.VelocityFeedback = dataForIndex[19].Value;
        result.ProgramPositionCommand = dataForIndex[20].Value;
        result.ProgramPositionFeedback = dataForIndex[21].Value;
        result.AccelerationCommand = dataForIndex[22].Value;
        result.AccelerationUnitName = dataForIndex[22].Key;
        result.AccelerationFeedback = dataForIndex[23].Value;
        result.PiezoVoltageCommand = dataForIndex[24].Value;
        result.PiezoVoltageFeedback = dataForIndex[25].Value;
        result.STOStatus = InternalUtilities.DoubleAsIntOrUIntToInt(dataForIndex[26].Value);
        return result;
    }
}

以下是针对 AxesDiagPacketRetriever 类的深度解析,从架构设计到实现细节的全面分析:


1. 核心职责

作为 轴诊断数据采集器,主要功能包括:

  • 多轴状态采集:同时获取32个轴的实时诊断数据

  • 数据标准化处理:原始值→工程单位转换

  • 高效数据重组:扁平数组→结构化对象转换

  • 硬件交互抽象:封装底层 AerStatusGetItems 调用


2. 关键设计模式

(1)工厂方法模式

  • 数据预加工:通过辅助类构建硬件请求所需的数据结构

(2)策略模式
private static readonly Dictionary<short, int> NonZeroExtraItemCodes; 
// 特殊项的特殊处理规则

 (3)缓存模式

private short[] itemCodes; // 缓存初始化后的请求参数
private void EnsureRequestDataInitialized() {
    if (itemCodes == null) {
        itemCodes = StatusItemRetrievalHelper.CreateItemArray(...);
    }
}

3. 核心数据结构

字段类型用途
PerAxisItemCodesshort[27]每个轴需要采集的27种数据项ID
NonZeroExtraItemCodesDictionary<short,int>需要额外参数的项配置
itemCodesshort[]硬件API所需的项ID数组(32轴×27项)
axisNumbersshort[]对应的轴编号数组
extraCodesint[]特殊项的额外参数

4. 关键流程分析

(1)数据采集流程

(2)数据结构转换

 

// 原始扁平数组→结构化对象
double[] rawData = new double[32*27]; // 硬件返回
DiagPacket[] packets = new DiagPacket[32]; 

for (int i = 0; i < 32; i++) {
    packets[i] = new DiagPacket {
        AnalogInput0 = rawData[i*27 + 0],
        AnalogInput1 = rawData[i*27 + 1],
        // ...其他字段
    };
}

5. 性能优化点

  1. 请求数据缓存

private short[] itemCodes; // 避免每次请求重新构建数组
  1. 批量读取

Wrapper.AerStatusGetItems(..., count: 864, ...); // 单次调用读取所有数据

并行处理(潜在优化)

Parallel.For(0, 32, i => {
    packets[i] = interpretDiagnosticData(..., i);
});

6. 典型使用场景

(1)实时监控
var retriever = new AxesDiagPacketRetriever(controller);
var data = retriever.GetAxesDiagnostics(new UnitInformation(mm, sec));

// 显示X轴状态
var xAxisData = data.Key[0]; 
Console.WriteLine($"X轴位置: {xAxisData.PositionFeedback} mm");
(2)故障诊断
if ((data.Key[2].AxisStatus & 0x01) != 0) {
    Alert("Y轴超限位!");
}

 

7. 异常处理增强

错误类型当前处理改进建议
硬件超时通过ExceptionResolver增加重试机制
单位转换错误未明确处理添加详细日志
轴号越界可能数组越界添加范围检查

总结

该类的设计优势:

  • 高效批量采集:单次调用获取所有轴数据

  • 类型安全输出:强类型DiagPacket结构

  • 单位抽象:支持灵活的单位转换

  • 资源优化:缓存请求参数减少GC压力

适用于:

  1. 多轴运动控制系统的实时监控

  2. 设备健康状态诊断

  3. 高频率数据采集场景

通过增加异步流式接口和动态配置能力,可进一步提升其在现代工业系统中的适用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值