pythonmodbuspymodbusminimalmodbus

Trying to Control a DGH D8500 modbus via python


i have this Two channel Analog Output modbus RTU protocol USB Interface named, DGH D8500. I need to control the voltage of the channels dynamically and automated through python. I connected it i tried it with its own program, but I'm failing to communicate with it using python, i tried using pymodbus and minimalmodbus but i don't seem to receive any type of response:

baudrate=9600, parity = none, bytesize = 8, stopbyte 1

Pymodbus code

from pymodbus.client.sync import ModbusSerialClient
import serial
import logging

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

instrument = ModbusSerialClient(method='rtu', port='COM3', baudrate=9600, parity=serial.PARITY_NONE, stopbits=1, bytesize=8)
print instrument.connect()
print instrument

value = instrument.read_holding_registers(40113, unit=1)
print value

Pymodbus error

DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x1 0x3 0x9c 0xb1 0x0 0x1 0xfa 0x7d
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
True
ModbusSerialClient(rtu baud[9600])
Exception Response(131, 3, IllegalAddress)
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x1 0x83 0x2 0xc0 0xf1
DEBUG:pymodbus.framer.rtu_framer:Getting Frame - 0x83 0x2
DEBUG:pymodbus.factory:Factory Response[131]
DEBUG:pymodbus.framer.rtu_framer:Frame advanced, resetting header!!
DEBUG:pymodbus.transaction:Adding transaction 1
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'

Process finished with exit code 0

Minimalmodbus Code

import minimalmodbus

instrument = minimalmodbus.Instrument('COM3', 1, mode='rtu', debug=True)
instrument.serial.baudrate = 9600
print instrument

value = instrument.read_register(registeraddress=40113, number_of_decimals=3, functioncode=3, signed=False)
print value

Minimalmodbus error

Connected to pydev debugger (build 192.5728.105)
MinimalModbus debug mode. Create serial port COM3
minimalmodbus.Instrument<id=0x39aee88, address=1, mode=rtu, close_port_after_each_call=False, precalculate_read_size=True, clear_buffers_before_each_transaction=True, handle_local_echo=False, debug=True, serial=Serial<id=0x3ae1518, open=True>(port='COM3', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=0.05, xonxoff=False, rtscts=False, dsrdtr=False)>
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x9c\xb1\x00\x01\xfa}' (01 03 9C B1 00 01 FA 7D)
MinimalModbus debug mode. Clearing serial buffers for port COM3
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1574707870601.00 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: '' () (0 bytes), roundtrip time: 63.0 ms. Timeout for reading: 50.0 ms.

Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm 2019.2\helpers\pydev\pydevd.py", line 2060, in <module>
    main()
  File "C:\Program Files\JetBrains\PyCharm 2019.2\helpers\pydev\pydevd.py", line 2054, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files\JetBrains\PyCharm 2019.2\helpers\pydev\pydevd.py", line 1405, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "C:\Program Files\JetBrains\PyCharm 2019.2\helpers\pydev\pydevd.py", line 1412, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:/Users/naxso/PycharmProjects/modbus_virt/minimal_modbus.py", line 8, in <module>
    value = instrument.read_register(registeraddress=40113, number_of_decimals=3, functioncode=3, signed=False)
  File "C:\Users\naxso\PycharmProjects\modbus_virt\venv\lib\site-packages\minimalmodbus.py", line 447, in read_register
    payloadformat=_PAYLOADFORMAT_REGISTER,
  File "C:\Users\naxso\PycharmProjects\modbus_virt\venv\lib\site-packages\minimalmodbus.py", line 1170, in _generic_command
    payload_from_slave = self._perform_command(functioncode, payload_to_slave)
  File "C:\Users\naxso\PycharmProjects\modbus_virt\venv\lib\site-packages\minimalmodbus.py", line 1240, in _perform_command
    response = self._communicate(request, number_of_bytes_to_read)
  File "C:\Users\naxso\PycharmProjects\modbus_virt\venv\lib\site-packages\minimalmodbus.py", line 1406, in _communicate
    raise NoResponseError("No communication with the instrument (no answer)")
minimalmodbus.NoResponseError: No communication with the instrument (no answer)

I really don't understand quite well its my firs time working with this and I'm following the instructions to the steps but maybe its only a little error of me because of my little knowledge.


Solution

  • Very simple solution for a very common problem.

    If you look at the pymodbus log, you'll see this line:

    Exception Response(131, 3, IllegalAddress)
    

    That means the register you are trying to read does not exist.

    This happens because the way you refer to Modbus register addresses is a bit confusing. Most devices use address 40xxx for holding registers, but when you actually read those registers you need to refer to them subtracting 40000. So if you want to read register 40113 you should do:

    value = instrument.read_holding_registers(113, unit=1)
    

    If you want to print the value stored in the register be aware that you have to call it explicitly:

    print value.registers[0]
    

    EDIT: As discussed below sometimes the offset is 40001 instead of 40000. So if you want to read register 40114 you need to query 40114-40001=113.