AdvancedClimateSystems / uModbus

Python implementation of the Modbus protocol.
Mozilla Public License 2.0
211 stars 81 forks source link

tcp.write_multiple_registers command is unable to write more than 3 registers, in modbus TCP #120

Open Abolohit opened 2 years ago

Abolohit commented 2 years ago

I have used your library in my umodbus python program to write to 4 holding registers on my modbus slave. The slave recieved only the first 3 registers successfully. The last register gets a garbage value.

To successfully write the last register, I have to use the tcp.write_single_register command seperately to send the last register after the first 3 registers have been sent over TCP.

Thus, I am able to write 4 holding registers only when I used this workaround. Please fix it to make this library perfect!

OrangeTux commented 2 years ago

Hello @Abolohit, thanks for your comment. I'm not convinced yet that the issues are caused by a bug in this package. Could you provide more info?

1) Are you using Modbus TCP or Modbus RTU? In case of the latter, noise on the serial line could cause the issues you describe.

2) Can you provide a some code that cause issues? And would it be possible to provide logs that show the faulted frames? A pcap file created with Wireshark would be great.

3) Can you verify the behavior with another modbus master? Does the slave receives faulted frames too?

Abolohit commented 2 years ago

I am using Modbus TCP.

The slave recieves the faulted frames. I am actually sending a IP address to the slave by taking a ip address string and breaking it into 4 integers, then writing those 4 integers to holding registers on the slave.

If I use the write multiple registers and send the 4 integers, the last integer(4th) becomes a random number.

If I use write multiple registers and send only the first 3 integers and then send the 4th integer separately using write single register, only then I am able to recieve the complete IP Address accurately on my slave.

My goal is to send an IP Address to the slave using Modbus TCP, which then gets stored in the holding registers of the slave for future use.

Here is a part of my code.

 sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sock2.settimeout(1)

 try:
      sock2.connect((ip_addr.value, 502))

      override_ip = tcp.write_multiple_registers(slave_id=1, starting_address=30, values=[ip1, ip2, ip3, ip4])

      response = tcp.send_message(override_ip, sock2)
      sock2.close()

  except socket.timeout:
      app.error("Timeout", "Check validity of entered IP Address or network connection")

This was my initial attempt at sending the ip address, ip4 fails to be recieved at the slave accurately.


I had to use this work around:

 sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sock2.settimeout(1)

 try:
      sock2.connect((ip_addr.value, 502))

      override_ip = tcp.write_multiple_registers(slave_id=1, starting_address=30, values=[ip1, ip2, ip3])

      response = tcp.send_message(override_ip, sock2)
      sock2.close()

  except socket.timeout:
      app.error("Timeout", "Check validity of entered IP Address or network connection")

 sock3 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sock3.settimeout(1)

 try:
      sock3.connect((ip_addr.value, 502))

      override_ip_last = tcp.write_single_register(slave_id=1, address=33, value=ip4)

      response = tcp.send_message(override_ip_last, sock3)
      sock3.close()

 except socket.timeout:
      app.error("Timeout", "Check validity of entered IP Address or network connection")