Python Forum
Pymodbus Write value to register
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pymodbus Write value to register
#1
Good afternoon. Only on your forum lately I can find answers to my questions. Tell me, send new devices, I can’t extract data from them using Python. I can't figure out how to send the value to the register.
Here's what's in the documentation:
Quote:Example: command 2002
- In the 40053 register set the formula number (No. Formula) for which you want to read the total
set;
- Send the command 2002 to the Command Register (40006);
- Read continuously 40060 register until you find the command echo (in this case 2002) which
indicates “data ready” or 0xFFFF indicates that “error in the command”;
- Read the values present in 40051…40060 registers and use them according to the following table.

I understand how to read from registers, but I can’t manage to write a value to a register.
Reply
#2
As a starting point the example:
https://pymodbus.readthedocs.io/en/lates..._sync.html

Example Code:
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.exceptions import ModbusIOException

# in the Docs the .sync is missing
# https://pymodbus.readthedocs.io/en/latest/source/example/client_sync.html

port = "/dev/ttyUSB1"  # your port is different
unit = 1  # some devices only react, if you explicit use the unit id of the device
# this is also mandatory, if you have more then one modbus client
# the `Server` is the slave and the `Client` is the master
# synchronous client instance
client = ModbusSerialClient(
    port=port, baudrate=9600, bytesize=8, parity="N", stopbits=1
)
# sendng the command 2002 to register 40006
# the unit is may be mandatory, but it's not always the case
# depends of the device you're using
# if this is not required, omit it

# now the strange thing. pymodbus does not raise the
# exceptions, it returns exceptions
# so checking if it's an exception with isinstance function calll
reply = client.write_register(40006, 2002, unit=unit)
if isinstance(reply, ModbusIOException):
    print(reply)

while True:
    values = client.read_input_registers(address=40060, count=1, unit=unit)
    # or client.read_holding_registers(...)
    if isinstance(values, ModbusIOException):
        print(values)
    else:
        # here if values is not an ModbusIOException
        print("Values:", values)
        if values[0] == 0xFFFF:
            print("Error detected")
        elif values[0] == 2002:
            print("Data ready")
            result = client.read_input_registers(address=40051, count=9, unit=unit)
            if isinstance(result, ModbusIOException):
                print("Could not read result")
                print("Maybe client.read_holding_registers?")
            else:
                print("Got a result:", result)
You need to know the baudrate, bytesize, parity, stop_bits and the unid id if you're using a serial connection. If you use the other methods, you'll need the IP, port and unit id.

Then a very annoying habit of pymodbus is, that exceptions do not raise, they are returned. So if you get a rsult back, it can be an Exception, or it can be a list or dict like object AFAIK.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
An error is thrown
Quote:Values: Exception Response(132, 4, IllegalFunction)
Traceback (most recent call last):
File "/home/pokip/winox1.py", line 28, in <module>
if values[0] == 0xFFFF:
TypeError: 'ExceptionResponse' object is not subscriptable
Reply
#4
Oh, then the object is not list-like. Maybe there is more than one possible Exception.

Print more details about the response object:
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.exceptions import ModbusIOException

# in the Docs the .sync is missing
# https://pymodbus.readthedocs.io/en/latest/source/example/client_sync.html

port = "/dev/ttyUSB1"  # your port is different
unit = 1  # some devices only react, if you explicit use the unit id of the device
# this is also mandatory, if you have more then one modbus client
# the `Server` is the slave and the `Client` is the master
# synchronous client instance
client = ModbusSerialClient(
    port=port, baudrate=9600, bytesize=8, parity="N", stopbits=1
)
# sendng the command 2002 to register 40006
# the unit is may be mandatory, but it's not always the case
# depends of the device you're using
# if this is not required, omit it

# now the strange thing. pymodbus does not raise the
# exceptions, it returns exceptions
# so checking if it's an exception with isinstance function calll
reply = client.write_register(40006, 2002, unit=unit)
if isinstance(reply, ModbusIOException):
    print(reply)

while True:
    values = client.read_input_registers(address=40060, count=1, unit=unit)
    # or client.read_holding_registers(...)
    if isinstance(values, ModbusIOException):
        print(values)
    else:
        # here if values is not an ModbusIOException
        print("Values:", values)
        print("Object Type:", type(values))
        print(dir(values))  # <- to see what could be accessed
        break # <- will stop the loop and values could be accessed via REPL
Run this for example with (don't forget to change port and baudrate):
python -i script.py
After the break, you're inside the REPL, and you can access the object.
This is the benefit of dynamic languages, you can introspect objects easily.

If you're using an IDE, the IDE can do this for you.

PS: you're not the first and last one who struggles with pymodbus. This package is complicated for beginners.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
Here's what happens. continuously
Quote:Values: Exception Response(132, 4, IllegalFunction)
Object Type: <class 'pymodbus.pdu.ExceptionResponse'>
['ExceptionOffset', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_rtu_frame_size', 'calculateRtuFrameSize', 'check', 'decode', 'encode', 'exception_code', 'function_code', 'isError', 'original_code', 'protocol_id', 'should_respond', 'skip_encode', 'transaction_id', 'unit_id']
Reply
#6
From the device description

Attached Files

Thumbnail(s)
   
Reply
#7
Maybe you have to use the holding_register:

Change
values = client.read_input_registers(address=40060, count=1, unit=unit)
to
values = client.read_holding_registers(address=40060, count=1, unit=unit)
Another difference, I saw too late, is the Framer. There are 3 different modes:
  • ascii
  • binary
  • rtu
Look in your device description for connections parameters. The mode must be known as well the unit id.
Check also, if the hardware itself is connected right.

AFIK the RTU framer is used for TCP/UDP Connections automatically. If you use ModbusSerialClient, the default mode is ascii.

Try also this 3 different modes:
# client with RTU framer
client = ModbusSerialClient(port=port, baudrate=9600, method="rtu")

# client with binary framer
client = ModbusSerialClient(port=port, baudrate=9600, method="binary")

# client with ascii framer
client = ModbusSerialClient(port=port, baudrate=9600, method="ascii")
And again with read_input_registers and read_holding_registers.
Try it with and without unit.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#8
I tried everything. In the documentation, I found a method for connecting RTU. the registers are still shifted by 1, i.e. instead of 40006 it will be 40005. But the error still pops up:

Quote:Values: ReadHoldingRegistersResponse (1)
Traceback (most recent call last):
File "winox1.py", line 32, in <module>
if values[0] == 0xFFFF:
TypeError: 'ReadHoldingRegistersResponse' object is not subscriptable

My code:
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.exceptions import ModbusIOException
 
# in the Docs the .sync is missing
# https://pymodbus.readthedocs.io/en/latest/source/example/client_sync.html
 
unit = 1 # some devices only react, if you explicit use the unit id of the device
# this is also mandatory, if you have more then one modbus client
# the `Server` is the slave and the `Client` is the master
# synchronous client instance
client = ModbusSerialClient(method='rtu', port='COM3', parity='N', baudrate=9600, bytesize=8, stopbits=1, timeout=1, strict=False)
# sendng the command 2002 to register 40006
# the unit is may be mandatory, but it's not always the case
# depends of the device you're using
# if this is not required, omit it
 
# now the strange thing. pymodbus does not raise the
# exceptions, it returns exceptions
# so checking if it's an exception with isinstance function calll
reply = client.write_register(5, 2002, unit=unit)
if isinstance(reply, ModbusIOException):
    print(reply)
 
while True:
    values = client.read_holding_registers(address=59, count=1, unit=unit)
    # or client.read_holding_registers(...)
    if isinstance(values, ModbusIOException):
        print(values)
    else:
        # here if values is not an ModbusIOException
        print("Values:", values)
        if values[0] == 0xFFFF:
            print("Error detected")
        elif values[0] == 2002:
            print("Data ready")
            values = client.read_holding_registers(address=50, count=1, unit=unit)
            if isinstance(result, ModbusIOException):
                print("Could not read result")
                print("Maybe client.read_holding_registers?")
            else:
                print("Got a result:", result)
I found this in the documentation, but did not understand anything.

Attached Files

Thumbnail(s)
   
Reply
#9
Can't even write the value to the register.
 from pymodbus.client.sync import ModbusSerialClient
from pymodbus.exceptions import ModbusIOException
 
unit = 1
client = ModbusSerialClient(method='rtu', port='COM3', parity='N', baudrate=9600, bytesize=8, stopbits=1, timeout=1, strict=False)
client.connect()
reply = client.write_register(5, 2002, unit=unit)
print (reply)

request = client.read_holding_registers(59, 1, unit=unit)
result = request.registers
print(result) 
answer:
Quote:Exception Response(134, 6, IllegalFunction)
[2020]

2020 should have corrected for 2002. I really need help Blush
Reply
#10
Thanks a lot, got it. :-) I forgot to write one more parameter to another register
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Problem with pymodbus - ModuleNotFoundError: No module named 'pymodbus.client.sync' stsxbel 2 23,763 Nov-02-2023, 08:20 AM
Last Post: South_east
  Pymodbus read and save to database stewietopg 3 1,874 Mar-02-2023, 09:32 AM
Last Post: stewietopg
  Simple syntax to asynchronously get access to MODBUS register orion67 1 2,855 Jan-22-2022, 12:40 PM
Last Post: orion67
  Login and Register system finndude 1 2,403 Apr-24-2020, 10:05 PM
Last Post: deanhystad
  AttributeError: 'Register' object has no attribute 'bit_7' colt 1 2,001 Dec-12-2019, 09:39 PM
Last Post: micseydel
  Pymodbus for Dummies hairem 1 3,165 Mar-12-2019, 01:42 PM
Last Post: hairem
  How to implement class register? AlekseyPython 0 1,995 Feb-14-2019, 06:19 AM
Last Post: AlekseyPython
  simple register code aocii 2 2,637 Dec-22-2018, 11:15 AM
Last Post: aocii
  Python script runs on startup but does not register keystrokes. mericanpi 3 3,463 Sep-07-2018, 02:58 PM
Last Post: mericanpi
  Why does pyinstaller register success with py to exe, but? Pleiades 1 4,296 May-09-2018, 11:02 AM
Last Post: Pleiades

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020