You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TwinCAT3中字节数组转LREAL(double)及数组切片索引实现方法咨询

问题1:动态数组区间语法报错的解决

TwinCAT 结构化文本不支持使用变量作为上下限的动态数组切片写法[a..b],切片的上下限必须为编译期常量。不需要对原数组做切片,有两种更高效的实现方式:

  • 直接通过DataReceived[i + 固定偏移量 + 字节序号]的方式逐个访问指定位置的字节
  • 调用系统函数MEMCPY,从原数组的指定偏移地址复制8个字节到临时缓冲区,无需手动逐个取值

问题2:字节数组转LREAL的实现

你之前用BYTEARR_TO_STRING转字符串再转LREAL的方法是完全错误的,这个函数是用来把ASCII编码的字节数组转成字符串,不能处理二进制数值。正确实现方式如下:

  1. 首先定义一个共用体类型,匹配8字节LREAL的内存结构:
TYPE BYTE8_LREAL :
UNION
    byte_buf : ARRAY[0..7] OF BYTE; // 8个字节缓冲区
    lreal_val : LREAL; // 对应解析后的双精度浮点数
END_UNION
END_TYPE
  1. 处理字节序问题:UR机器人返回的报文是大端序(对应Python代码里struct.unpack('>d')的>标识),而TwinCAT运行的x86/x64平台是小端序,所以需要把读取到的8个字节反转顺序后再填入共用体,才能得到正确的数值。

完整修改后的功能块代码

功能块定义部分

FUNCTION_BLOCK DataEncoding
VAR_INPUT
    DataReceived: ARRAY[0..1115] OF BYTE;
END_VAR
VAR_OUTPUT
    moment: ARRAY[0..5] OF LREAL := [6(0.0)];
    joint_pos: ARRAY[0..5] OF LREAL := [6(0.0)];
    joint_vel: ARRAY[0..5] OF LREAL := [6(0.0)];
    tcp_pos: ARRAY[0..5] OF LREAL := [6(0.0)];
    tcp_vel: ARRAY[0..5] OF LREAL := [6(0.0)];
    tcp_force: ARRAY[0..5] OF LREAL := [6(0.0)];
    state: LREAL := 0.0;
    time_new: LREAL := 0.0;
END_VAR
VAR
    i: INT;
    conv_union: BYTE8_LREAL; // 转换用共用体
    j: INT;
END_VAR

功能块主体逻辑部分

// 循环上限设为1112,避免i+3越界访问数组
FOR i := 0 TO 1112 BY 1 DO
    // 匹配报文头0x00 0x00 0x04 0x5C(十进制92)
    IF DataReceived[i] = 0 AND DataReceived[i+1] = 0 AND DataReceived[i+2] = 4 AND DataReceived[i+3] = 92 THEN
        // 解析moment数组,偏移从204开始,每个值占8字节
        FOR j := 0 TO 5 DO
            // 复制8个字节到共用体缓冲区
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 204 + j*8]), 8);
            // 反转字节序适配大端报文
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            moment[j] := conv_union.lreal_val;
        END_FOR;

        // 解析joint_pos数组,偏移从252开始
        FOR j := 0 TO 5 DO
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 252 + j*8]), 8);
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            joint_pos[j] := conv_union.lreal_val;
        END_FOR;

        // 解析joint_vel数组,偏移从300开始
        FOR j := 0 TO 5 DO
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 300 + j*8]), 8);
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            joint_vel[j] := conv_union.lreal_val;
        END_FOR;

        // 解析tcp_pos数组,偏移从444开始
        FOR j := 0 TO 5 DO
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 444 + j*8]), 8);
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            tcp_pos[j] := conv_union.lreal_val;
        END_FOR;

        // 解析tcp_vel数组,偏移从492开始
        FOR j := 0 TO 5 DO
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 492 + j*8]), 8);
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            tcp_vel[j] := conv_union.lreal_val;
        END_FOR;

        // 解析tcp_force数组,偏移从540开始
        FOR j := 0 TO 5 DO
            MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 540 + j*8]), 8);
            conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
            tcp_force[j] := conv_union.lreal_val;
        END_FOR;

        // 解析state,偏移1052
        MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 1052]), 8);
        conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
        state := conv_union.lreal_val;

        // 解析time_new,偏移4
        MEMCPY(ADR(conv_union.byte_buf), ADR(DataReceived[i + 4]), 8);
        conv_union.byte_buf := [conv_union.byte_buf[7], conv_union.byte_buf[6], conv_union.byte_buf[5], conv_union.byte_buf[4], conv_union.byte_buf[3], conv_union.byte_buf[2], conv_union.byte_buf[1], conv_union.byte_buf[0]];
        time_new := conv_union.lreal_val;

        // 找到报文头后退出循环,和Python逻辑一致
        EXIT;
    END_IF;
END_FOR;

如果需要优化性能,也可以提前把字节序反转封装成一个单独的函数,避免重复写反转逻辑。


内容的提问来源于stack exchange,提问作者Harry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:57:00