使用Minimal Modbus向PLC写入浮点数时的字序交换问题
解决Minimal Modbus写入浮点数字序错误及负数寄存器写入问题
一、浮点数字序交换的正确实现
你预交换字序时报错,是因为直接传递了numpy数组给write_float,但这个方法只接受单个数值类型的输入。要满足PLC的字序要求,我们可以绕开write_float,手动拆分浮点数为寄存器值后交换写入:
- 先把浮点数转换成两个16位寄存器的原始值(模拟
write_float的内部转换逻辑):
import struct import minimalmodbus # 目标浮点数 target_float = 123.456 # 将浮点数打包为大端格式的4字节流,再拆分为两个16位寄存器值 packed_bytes = struct.pack('>f', target_float) reg_val1 = struct.unpack('>H', packed_bytes[0:2])[0] reg_val2 = struct.unpack('>H', packed_bytes[2:4])[0] # 交换两个寄存器的顺序(匹配PLC的字序要求) swapped_registers = [reg_val2, reg_val1]
- 用
write_registers一次性写入交换后的寄存器:
# 初始化设备(根据你的实际端口和站号调整) plc1 = minimalmodbus.Instrument('/dev/ttyUSB0', 1) # 写入到起始寄存器28672 plc1.write_registers(28672, swapped_registers, functioncode=6)
这样就能得到你预期的结果:寄存器28672为十进制-5767(十六进制42F6),寄存器28673为十进制17142(十六进制E979)。
二、解决写入负数寄存器的报错问题
你用write_register写负数时报错,是因为该方法默认使用无符号16位整数格式(>H),负数超出了无符号范围。要写入负数对应的寄存器值,需要先把负数转换为16位有符号整数对应的无符号补码:
比如要写入-5767,转换逻辑如下:
negative_val = -5767 # 转换为16位无符号补码(等效于负数 + 65536) unsigned_val = negative_val & 0xFFFF # 现在可以正常写入寄存器 plc1.write_register(28676, unsigned_val, functioncode=6)
原理是:16位有符号整数的范围是-32768到32767,负数的补码可以通过与0xFFFF按位与得到,这样得到的无符号值就能被write_register正确处理。
额外提示
如果不想每次手动处理,也可以修改Minimal Modbus的write_float方法字节序逻辑,但手动拆分交换的方式更稳妥,避免修改库源码带来的后续维护问题。
内容的提问来源于stack exchange,提问作者user3005949
相关产品推荐
相关产品推荐

