sourceperl / pyModbusTCP

A simple Modbus/TCP library for Python
MIT License
308 stars 106 forks source link

Newbie writing Holding Registers #87

Closed WernerFettke closed 2 months ago

WernerFettke commented 2 months ago

Hi All,

I hope someone can assist, I'm still pretty new to modbus and pyModbusTCP.

I'm trying to write holding register values to the databank using for example:

x = 120889 server.data_bank.set_holding_registers(123, [x])

So in other words writing x (120889) to register number 123

This works, however when I try read the value from the modbus server where this has been written to I get: 55353

I figured out this is 120889 - 65536 = 55353 (the response I'm getting)

I'm assuming I need to convert x or specify the type before doing ? server.data_bank.set_holding_registers(123, [x])

I have checked the documentation to see if I can set the value type (possibly a double or a float ?) when setting the holding_registers but I don't see anything there. The value of x will always be an integer, I'm sure it's something simple, but any assistance would really be appreciated.

Many Thanks !

Werner

sourceperl commented 2 months ago

Hi,

To write a 32-bit value using Modbus, split it into two 16-bit words (native format of modbus address space) and write it as a list of two items. For example, to write 120889 (=0x0001_d839), set [0x0001, 0xd839] at address 123.

# convert 32 bits -> 2 x 16 bits
i = 120_889
high_part = (i>> 16) & 0xFFFF
low_part = i & 0xffff
# this will update words at @123 and @124
server.data_bank.set_holding_registers(123, [high_part , low_part])
# since 32-bit writing is not in modbus standard, some devices may require the reverse order
server.data_bank.set_holding_registers(123, [low_part , high_part])
WernerFettke commented 2 months ago

Hi,

Many thanks for getting back to me, I really appreciate it !!

If I take your code as is, without changing anything (including the value of i), and run the code, on the other end if I read the modbus, I get the attached image: Screen Shot 2024-09-25 at 10 53 18 AM The highlighted row, 55353 and -10183 ? I have also tried hard coding the hex value: 0x0001_d839 for i but this also returns the same as in the screen shot ?

If I swop the low and high parts around, I just get a 1 on the output.

Any other ideas where I'm going wrong ?

Much appreciated.

Regards

Werner

sourceperl commented 2 months ago

Hi,

55353, -10183 and 0xd839 are the same 16-bit value. The first is a decimal representation, the second is a two's complement and the last is a hexadecimal representation.

For the rest, it's difficult to help you based on this image.

WernerFettke commented 2 months ago

Hi,

Something interesting I noticed, instead of using: i = 120_889

If I made it the full number: i = 120889

I get the following, I'm assuming it has something to do with the format of i Screen Shot 2024-09-25 at 12 20 11 PM

WernerFettke commented 2 months ago

Hi,

55353, -10183 and 0xd839 are the same 16-bit value. The first is a decimal representation, the second is a two's complement and the last is a hexadecimal representation.

For the rest, it's difficult to help you based on this image.

Thanks for getting back to me, I just want to confirm, if I used your code: i = 120_889 high_part = (i>> 16) & 0xFFFF low_part = i & 0xffff

this will update words at @123 and @124

server.data_bank.set_holding_registers(123, [high_part , low_part])

I should be getting 120889 when I read the modbus value ?

Regards

Werner

sourceperl commented 2 months ago

Maybe you could try to configure your client to read 2 registers since the "uint32" and "int32" columns are marked as incomplete.

sourceperl commented 2 months ago

To see 120889 you need 2 16-bit registers.

WernerFettke commented 2 months ago

I think I found the problem, I was setting the value for the next register, which was in essence overwriting the value we where calculating, If I don't do that I get: Screen Shot 2024-09-25 at 12 28 44 PM

Thanks so much for your help !!!

sourceperl commented 2 months ago

Glad to read this, have a nice day.