Reputation: 33
I'm using the python library Minimal Modbus to read an energy meter (RS-485).
I'm trying to use the function to read multiple registers at once
read_registers(registeraddress, numberOfRegisters, functioncode=3)
Here is the code of the python library:
def read_registers(self, registeraddress, numberOfRegisters, functioncode=3):
"""Read integers from 16-bit registers in the slave.
The slave registers can hold integer values in the range 0 to 65535 ("Unsigned INT16").
Args:
* registeraddress (int): The slave register start address (use decimal numbers, not hex).
* numberOfRegisters (int): The number of registers to read.
* functioncode (int): Modbus function code. Can be 3 or 4.
Any scaling of the register data, or converting it to negative number (two's complement)
must be done manually.
Returns:
The register data (a list of int).
Raises:
ValueError, TypeError, IOError
"""
_checkFunctioncode(functioncode, [3, 4])
_checkInt(numberOfRegisters, minvalue=1, description='number of registers')
return self._genericCommand(functioncode, registeraddress, \
numberOfRegisters=numberOfRegisters, payloadformat='registers')
The problem I have got is that the registers hold the data as Long
but this function returns them as a list of int
and looking at the values it doesn't seem correct.
This is my script at the moment:
##!/usr/bin/env python
import minimalmodbus
import time
import glob
import sys
import MySQLdb
instrument = minimalmodbus.Instrument('/dev/ttyUSB1', 7)
#Debug Options
#instrument.debug = True #debug modbus
read = False
def convert(value):
data=chr(value)
return data
def read_registers_ime():
data = instrument.read_registers(4096,20)
return data
while True:
try:
while read == False:
data = read_registers_ime()
print data
time.sleep(0.11)
read = True
break
except KeyboardInterrupt:
print "Stopped"
sys.exit()
except TypeError:
print "TypeError"
except IOError:
print "IOError"
AT the moment it returns the following:
[3, 39192, 3, 44592, 3, 44592, 0, 423, 0, 0, 0, 0, 0, 0, 6, 19884, 6, 24584, 6, 19884]
Everything I have tried so far to convert the data back to the original format has failed. I would really appreciate some help here.
Many thanks,
Bryan
Upvotes: 0
Views: 2603
Reputation: 6219
I already encountered this kind of problem working with modbus using umodbus instead of minimal modbus. I solved it by:
see example below (Python 2.7):
import struct
registers = [3, 39192, 3, 44592, 3, 44592, 0, 423, 0, 0, 0, 0, 0, 0, 6, 19884, 6, 24584, 6, 19884]
def grouped(iterable, group_size):
"""iterates on iterable, yielding groups of group_size elements"""
it = iter(iterable)
while True:
group = [next(it) for _ in range(group_size)]
yield group
for group in grouped(registers, 2):
bytes = b""
for word in group:
word_bytes = struct.pack("H", word)
bytes += word_bytes
bytes_hex = "0x" + "".join(["{:>02X}".format(ord(byte_)) for byte_ in bytes])
print("{} -> {} -> {}".format(group, bytes_hex, struct.unpack("<i", bytes)[0]))
prints:
[3, 39192] -> 0x03001899 -> -1726480381
[3, 44592] -> 0x030030AE -> -1372585981
[3, 44592] -> 0x030030AE -> -1372585981
[0, 423] -> 0x0000A701 -> 27721728
[0, 0] -> 0x00000000 -> 0
[0, 0] -> 0x00000000 -> 0
[0, 0] -> 0x00000000 -> 0
[6, 19884] -> 0x0600AC4D -> 1303117830
[6, 24584] -> 0x06000860 -> 1611137030
[6, 19884] -> 0x0600AC4D -> 1303117830
This example may need some tweaks according to your exact needs, but it may help.
Upvotes: 3