modbus-cli icon indicating copy to clipboard operation
modbus-cli copied to clipboard

Word register order

Open zmaile opened this issue 5 years ago • 2 comments

It appears that openPLC stores multi-word values differently to how modbus-cli sends/receives them. The bits seem to be the correct edian order, but the words should not always be in the same order.

This page (https://csimn.com/CSI_pages/Modbus101.html under heading "Registers Are 16-bits - How Do I Read Floating Point or 32-bit Data?") has a short section that explains it better than I can. That section also suggests that there are other PLCs that store values in this different way.

Can an option be added to swap the word order for multi-word values?

zmaile avatar Sep 29 '20 13:09 zmaile

We could definitively add a reverse endian mode. What is implemented is what is used in Schneider PLCs so I would think this would be correct in most cases. You are the first to comment this.

The link you send does not really add much to the discussion. Because Modbus internally just supports words and bits.

I would need a way to test this...

tallakt avatar Sep 29 '20 17:09 tallakt

I'm willing to help with testing. Though I'm not a dev so it may take be a few days to fumble through learning how git works (in the context of testing).

Alternatively I could set up a Linux VM with openPLC running on it and open up a firewall rule from an IP of your choosing. That way you can read/write from modbus-cli and confirm the readings on openPLC's monitoring page.

EDIT: A possible workaround for testing: pick an arbitrary value for a float/DWORD, calculate what the value would be when word-reversed and see if that value appears using normal testing methods.

EDIT 2: I tried simply removing the two reverses from the lines in functions read_and_unpack() & pack_and_write() - it worked successfully in reading and writing floats that openPLC recognises correctly. The lines now read as such:

  def read_and_unpack(sl, format)
    # the word ordering is wrong. calling reverse two times effectively swaps every pair
    read_data_words(sl).pack('n*').unpack("#{format}*")
  end

and

  def pack_and_write(sl, format)
    # the word ordering is wrong. calling reverse two times effectively swaps every pair
    sliced_write_registers(sl, addr_offset, values_list.pack("#{format}*").unpack('n*'))
  end

Obviously this doesn't implement a toggle option though.

zmaile avatar Sep 30 '20 00:09 zmaile