struct.error: 'H' format requires 0 <= number <= 65535

发布时间 2023-10-12 11:26:23作者: x9nu

全部代码如下:

from pymodbus.client import ModbusTcpClient

# 避坑:write_registers和write_register函数差一个s。多一个s的参数用整型列表,没有的只能用整型

def split_float_to_integer_and_fraction_parts(number):
    """
    将浮点数拆分为整数部分和小数部分的函数
    """
    integer_part = int(number)
    fraction_part = int((number - integer_part) * 10000)  # 将小数部分转换为整数
    print(integer_part, "和", fraction_part)
    # 将负值转换为无符号整数
    # 将负值转换为无符号整数
    if number < 0:
        integer_part = 65536 + integer_part
        fraction_part = 65536 + fraction_part
    return integer_part, fraction_part

def send_coordinates_to_robot(coordinates, encoder_value, host_ip='192.168.0.11', host_port=502):
    """
    将坐标发送给机器人的函数
    """
    # 分解编码器值
    result = None
    # print(encoder_value,"encoder_value")
    h4_encoder_integer_part = abs(int(encoder_value / 10000))
    l4_encoder_integer_part = abs(int(encoder_value - h4_encoder_integer_part * 10000))
    encoder_fraction_part = abs(int((encoder_value - int(encoder_value)) * 1000))

    # 创建并连接到Modbus服务器
    client = ModbusTcpClient(host_ip, port=host_port)
    connection = client.connect()
    if connection:
        result = "成功连接到Modbus服务器。"
    else:
        return "无法连接到Modbus服务器。"

    # 准备用于保存 坐标 -> 寄存器值 的列表
    register_coord = []
    # 准备用于保存 传送带编码值 -> 寄存器值 的列表
    register_encoder = []
    # 固定结束位
    end = 1

    # 依次写入坐标寄存器和工件属性寄存器
    # x->(102.103) y->(104.105) z->(106.107) c->(108.109)
    for i, (key, coordinate) in enumerate(coordinates.items()):
        # 跳过"AREA"和"ID"字段
        if key not in ["x", "y", "z", "c", "ATTR"]:
            continue
        # 坐标
        if key in ["x", "y", "z", "c"]:
            coord_integer_part, coord_fraction_part = split_float_to_integer_and_fraction_parts(coordinate)
            register_coord.extend([coord_integer_part, coord_fraction_part])
        # 传送带不在寄存器连续区间
        # 物料属性
        if key == "ATTR":
            register_coord.append(coordinate)

    # 写入编码器值寄存器:整数高4位,整数低4位,小数4位
    register_encoder.extend([h4_encoder_integer_part, l4_encoder_integer_part, encoder_fraction_part])
    print(register_coord)
    print(register_encoder)
    # 从102开始写到109,坐标+工件属性
    response1 = client.write_registers(102, register_coord, slave=1)
    # 从124开始写到126,编码器值
    response2 = client.write_registers(124, register_encoder, slave=1)
    # 在111写入结束位1
    response3 = client.write_register(111, end, slave=1)

    if response1.isError() or response2.isError():
        result += "写入寄存器失败"
    elif response3.isError():
        result += "写入结束位失败"
    else:
        result += "成功写入寄存器,并发送物料信息至机器人"

    # 关闭连接
    client.close()

    # 返回一条消息,表示操作已完成
    return result

send_coordinates_to_robot({
    'x': -2215,
    'y': -5,
    'z': -812.66,
    'c': 23.4038,
    'ATTR': 2,
}, 0)

调试:

输出:

为什么我小数大于零还进入了if分支???
我以为是Python有-0的问题,给我惊呆了,居然有负0。

x = -0
print(x)
if x == 0:
    print("x==0,加1后:", x + 1)
elif x < 0:
    print("x<0,加1后:", x + 1)
elif x > 0:
    print("x>0,加1后:", x + 1)

说明不是负0的问题。
然后我最后才发现,用来判断的数不是我分解后的数。
这是原来的:

    if number < 0:
        integer_part = 65536 + integer_part
        fraction_part = 65536 + fraction_part

修改后,应该分别判断他们是不是小于0

# 将负值转换为无符号整数
    if integer_part < 0:
        print("加之前:", fraction_part)
        integer_part = 65536 + integer_part
    if fraction_part < 0:
        fraction_part = 65536 + fraction_part

这是上一个人给我遗留的代码,真的难找。