我的AB Micro820可编程控制器中有modbus映射设置。我有一个40001的数组用于写入,42001个数组用于读取。两者都是200个元素和实数类型(32位浮点型)。我现在可以写和读,所以我知道代码可以工作,只是不正确。这些值被读/写为非常小的值(即4.58577478E-19)。有谁能给我指个方向吗?
#!/usr/bin/env python
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.client.sync import ModbusTcpClient
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.INFO)
ip_address = "192.168.2.101"
client = ModbusTcpClient(ip_address)
if client.connect(): # connection is OK
# write float
builder = BinaryPayloadBuilder(endian=Endian.Little)
builder.add_32bit_float(77.77)
payload = builder.build()
result = client.write_registers(1, payload, skip_encode=True)
# read floats
result = client.read_holding_registers(2001, 4)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Little)
print "read_holding_registers: " + str(decoder.decode_32bit_float())
client.close()发布于 2018-02-14 16:11:12
TLDR:
使用:
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, Endian.Big, wordorder=Endian.Little)而不是:
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Little)解释尝试:
文档中描述了此包的BinaryPayloadDecoder.fromRegisters参数。
在这种情况下,我们应该注意:
字节顺序-每个字的字节顺序
wordorder -单词的字节顺序(当wordcount为>= 2时)
我相信适合modbus寄存器(2字节)的值字节顺序必须始终是Endian.Big
wordorder类似于byteorder,但用于modbus寄存器。
For Modbus TCP always必须为that is byteorder=Endian.Big,wordorder=Endian.Little,因为值的字节顺序(由2个以上的字节组成)是在协议规范OPEN MODBUS/TCP SPECIFICATION(Appendix B. Data Encoding for non-word data)中指定的。
For Modbus RTU字节顺序的值,由2个以上的字节组成的值在协议规范Somehow described here中没有精确指定。
大多数实现采用Modbus TCP方法,并以2、1、4、3字节的形式传输浮点数。
然而,还有其他的可能性:
wordorder=Endian.Big
发布于 2015-06-13 03:28:16
我让它在C++中与libmodbus一起工作:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <vector>
#include <iostream>
using namespace std;
extern "C" // needed to integrate C code into C++
{
#include "libmodbus/modbus.h"
}
int main (void)
{
modbus_t *ctx;
uint16_t read_reg[64];
uint16_t write_float_holder[2];
uint16_t read_float_holder[2];
vector <float> write_reg = {77.77, 15.69, 42.78, 50153.33, -56.23};
int rc, start_element = 0, j = 0;
float rc_f[10];
ctx = modbus_new_tcp("192.168.2.101", 502); // PLC IP address and default Modbus Port (502)
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
///// Reading 402000
/// REAL array in PLC
// array fills up right to left with hex: 0x[1][0] >> 0x4174 0x28f6 >> read_from_plc[0] = 15.26
if (1)
{
rc = modbus_read_registers(ctx, 2000, 8, read_reg); // (connection, start position, how many to read, what read values go into)
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (int i = 0; i < rc; i++) {
printf("read_reg[%d]=%d (0x%x)\n", i, read_reg[i], read_reg[i]);
}
for (int i = 0; i < rc; i += 2)
{
read_float_holder[0] = read_reg[i];
read_float_holder[1] = read_reg[i + 1];
rc_f[j] = modbus_get_float(read_float_holder);
printf("rc_f[%d]: %f\n", j, rc_f[j]);
j++;
}
}
///// Writing 40000
/// REAL array in PLC
if (1)
{
for (size_t i = 0; i < write_reg.size(); i++) // write two registers (32-bit float) at a time
{
modbus_set_float(write_reg[i], write_float_holder); // set float to hexadecimal
rc = modbus_write_registers(ctx, start_element, 2, write_float_holder);
start_element += 2;
cout << "modbus_set_float: writing write_reg[" << i << "] = " << write_reg[i] << "\trc: " << rc << endl;
}
}
// close connection and free memory
modbus_close(ctx);
modbus_free(ctx);
return 0;
}https://stackoverflow.com/questions/30784965
复制相似问题