7

I have this little device for communication, and I can see the dongle after lsusb, and it is attached to ttyUSB0 (output from dmesg). Since the module has its driver that is installed to Raspberry Pi, I don't need another CPU for handshake. I am using pymodbus, and I wrote the code segment below.

import pymodbus
import serial
from pymodbus.pdu import ModbusRequest
from pymodbus.client.sync import ModbusSerialClient as ModbusClient #initialize a serial RTU client instance
from pymodbus.transaction import ModbusRtuFramer

import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#count= the number of registers to read
#unit= the slave unit this request is targeting
#address= the starting address to read from

client= ModbusClient(method = "rtu", port="/dev/ttyUSB0",stopbits = 1, bytesize = 8, parity = 'E' baudrate= 9600)

#Connect to the serial modbus server
connection = client.connect()
print connection

#Starting add, num of reg to read, slave unit.
result= client.read_holding_registers(0x00,2,unit= 0xff)

print(result)

#Closes the underlying socket connection
client.close()

Output is:

True
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:getting transaction 1
None

It obvious I am doing something wrong, but I don't know what. How can I fix this problem?

1
  • 1
    Why are you setting unit id 0xff. It can be only up to 247 from 1 for slave? I am not sure if you have already solved it.
    – prashant
    May 27, 2018 at 3:21

5 Answers 5

3

I had the same initial problem with pymodbus using a Beaglebone Black to read and write data to a heat recovery ventilator. I had already tried minimalmodbus, so I knew that the hardware side was fine. The documentation, including the recent document (https://media.readthedocs.org/pdf/pymodbus/latest/pymodbus.pdf) is not clear on this. The output seems to be a register, which needs to be accessed to get the actual returned values. This is what worked for me:

temps  = client.read_input_registers(30001, 4, unit=0x0a) # address, count, slave address
print temps.registers
coil  = client.read_coils(10001, 8, unit=0x0a) # address, count, slave address
print coil.bits

Writing seems more straightforward:

rq = client.write_coil(10001, 1, unit=0x0a)
rq = client.write_register(40001, 2, unit=0x0a)

Just for completeness, here are the equivalent commands in minimalmodbus and modbus-tk that mostly worked for me.

Minimalmodbus: I think that the instrument.read_bit command should work, but I get a "ValueError: Could not convert bit response to a value. Input: '\x10'". Coil reads work in pymodbus and Modbus-tk.

temps = instrument.read_registers(30001, 4, 3) # address, count, function code (3 or 4)
print temps
coil = instrument.read_bit(10001, 1) # address, function code (1 or 2), generates error
print coil
instrument.write_bit(10001, 1, 5) # address, value, function code (5 or 15)
instrument.write_register(40001, 2, 0, 6, False) # address, value, number of decimals, function code, signed)

modbus-tk:

temps = master.execute(10, cst.READ_HOLDING_REGISTERS, 30001, 4)
print temps
coil = master.execute(10, cst.READ_COILS, 10001, 8)
print coil
logger.info(master.execute(10, cst.WRITE_SINGLE_COIL, 10001, output_value=0))
logger.info(master.execute(10, cst.WRITE_SINGLE_REGISTER, 40001, output_value=2))
1
  • Thank you for your detailed answer P Mess. I will try what you did and let you know.
    – Cugomastik
    Jan 14, 2015 at 7:59
2

Maybe you should try minimalmodbus library: https://pypi.python.org/pypi/MinimalModbus/0.5. I will check with input register reading and writing soon.

1
  • 2
    To be honest I am using pymodbus because I started with it and read about it a lot. minimalmodbus is my second choice. Seems like I will have to use it eventually. Thank you for your reply.
    – Cugomastik
    Oct 3, 2014 at 21:13
1

The None result could be due to wrong parameters for serial connection. See this line:

client= ModbusClient(method = "rtu", port="/dev/ttyUSB0",stopbits = 1, bytesize = 8, parity = 'E' baudrate= 9600)

In my script, this works: parity = 'N'

Refer to the device documentation if you are not sure about the parameters

0

Try using something like: print('result received is ', ':'.join('{:02x}'.format(x) for x in result.receive(16))). This will read up to 16 characters or everything in the buffer up to 16 chars and show it as hex

0

Start with adding number of registers to read, slave unit.

result= client.read_holding_registers(0x00,2,unit= 0xff)

Try like this

print(result[0])

Not the answer you're looking for? Browse other questions tagged or ask your own question.