Starting to use modbus-tk library

1,939 views
Skip to first unread message

Mike Spath

unread,
Jun 3, 2019, 3:11:49 PM6/3/19
to modbus-tk

'm using modbus_tk library to use as a Modbus RTU slave. I have an off the shelf Modbus RTU master simulator running on another PC through a usb to 485 converter. I cannot see my holding register in the Master.

I have verified that the serial link is good because I can send strings to the slave using a serial program. I have tried setting up the Master for 16 and 32 bit ints the response is always 83 04. I have tried using a few different masters with staring address of 0, this one happens to default to first register 40001. Baud rates and serial port setting match. The slave is being run on a Raspberry Pi board.

Below is the code.

import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
import serial
import time  

modbusServ = modbus_rtu.RtuServer(serial.Serial('/dev/ttyS0'),baudrate= 9600,
                 bytesize=8, parity='N', stopbits=1, xonxoff=0)
print("start")

modbusServ.start()

slave_1 = modbus_tk.modbus.Slave(1)

slave_1.add_block("BlockName", modbus_tk.defines.HOLDING_REGISTERS, 40001, 10)

aa= (1,2,3,4,5,6,7,8,9,10) # data in the register

while True:

    slave_1.set_values ("BlockName", 40001, aa)
    time.sleep(0.5)

Mike Spath

unread,
Jun 3, 2019, 5:00:22 PM6/3/19
to modbus-tk
Hello Group:
Just an FYI I modified the code I posted to get the master to read the values. I have to create a separate handle to a slave to set the values.

My new question is how to set values so they are 32 bit floats? I know you need to create two registers but not sure about the addressing. 

import modbus_tkimport modbus_tk.defines as cst
from modbus_tk import modbus_rtu
import serial
import time  


modbusServ
= modbus_rtu.RtuServer(serial.Serial('/dev/ttyS0'),baudrate= 9600,
                bytesize
=8, parity='N', stopbits=1, xonxoff=0)


print("start")


modbusServ
.start()



slave_1
= modbusServ.add_slave(1)


slave_1
.add_block("BlockName", modbus_tk.defines.HOLDING_REGISTERS, 0, 10)


aa
= (1,2,3,8,5,6,9,8,9,10) # data in the register


# neede to create another handle to set values
slave
= modbusServ.get_slave(1)


slave
.set_values ("BlockName", 0, aa)


while True:
   
print("Modbus Server Waiting for client querires..")


    time
.sleep(0.5)  

Luc JEAN

unread,
Jun 4, 2019, 8:40:52 AM6/4/19
to modb...@googlegroups.com
Hello Mike,

Thanks for using modbus-tk. :)

If you want to write a float as 2 registers in your slave, I think the best option is to use the `struct` python module

something like : 
import struct
four_bytes = struct.pack('f', 3.14)
two_registers = struct.unpack(‘HH', four_bytes)
# Then write these two registers in your slave


The execute function of the master supports float format. It may help you to make sure the data is correct in the slave. see following example:

I hope it helps

Best
luc

Mike Spath

unread,
Jun 4, 2019, 10:17:28 AM6/4/19
to modb...@googlegroups.com
Hi Luc:
Thank you for helping me out, I'm working on a project that has very little time for me to come up to speed on how to communicate through Modbus RTU and programming in Python. I'm using a raspberry pi to communicate to a PLC, passing values back and forth using some proprietary python code.

If I pack and unpack the float 3.14 as you write I get:

packed: b'\xc3\xf5H@'
unpacked: (62915, 16456)

If I just set the slave to write those two unsigned shorts, I do not see the 3.14 in the master. (I'm using SimplyModbus application to simulate the PLC I will eventually have)
slave_1.set_values ("BlockName", 0, two_registers)

I will continue to read up on how to show a 32 bit float in Modbus but any further insight would be great.
Thanks,
Mike

--
You received this message because you are subscribed to the Google Groups "modbus-tk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to modbus-tk+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/modbus-tk/4EBBCB57-50A4-442D-87A5-DA2322112E55%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


--
Thank you,
Mike Spath

Luc JEAN

unread,
Jun 4, 2019, 11:30:32 AM6/4/19
to modb...@googlegroups.com
Hello,

I don’t know SimplyModbus but what you need to know is how the 4 bytes of the float will be read by the master. You may try to play with the struct format for example with a leading > to change the order of bits

four_bytes = struct.pack(‘>f', 3.14)
two_registers = struct.unpack(‘>HH', four_bytes)

Best
luc

Mike Spath

unread,
Jun 4, 2019, 12:19:25 PM6/4/19
to modb...@googlegroups.com
Hi Luc:
Yes, that was the issue, once I used the carets I started to see the value in the 40001 register of the Master. SimplyModbus is a LabView based application I downloaded (free to try $60 to buy) to do my testing. It gives you the flexibility to setup the endian the way you want so I removed the carets from the code and setup the endian for high byte first ON, high word first OFF and that works as well.

Thank you for your help!
Mike


For more options, visit https://groups.google.com/d/optout.

Mike Spath

unread,
Jun 12, 2019, 12:12:57 PM6/12/19
to modb...@googlegroups.com
Hi Luc:
I'm trying to write code to read a 32 bit float (2 registers) written by the master. I'm assuming I would have to reverse the packing? What I have thusfar in psudeo code is:

On the slave add_block("ReadBlock", define HOLDING_REGISTERS, 11, 10)
create a 2 register variable
values = slave.get_values("ReadBlock", 11, 2)
stuff values into the 2 register variable

I'm wondering if this is the right approach and if there are similar python code examples to read float values

thanks,
Mike

Luc JEAN

unread,
Jun 13, 2019, 7:03:49 AM6/13/19
to modb...@googlegroups.com
Hello Mike,

If I understand correctly, you wan to set the values into a slave a and let it read by a master.

I guess you need to know something like:

slave add_block("ReadBlock", define HOLDING_REGISTERS, 11, 10)
create a 2 register variable
values = [reg1, reg2]
slave.set_values("ReadBlock", 11, 2, values)

I hope it helps
Best
luc


Mike Spath

unread,
Jun 13, 2019, 7:52:34 AM6/13/19
to modb...@googlegroups.com
Hi Luc,
I'm trying to understand how to read 32 bit float values that are written by a Modbus master. Below is a screenshot of the master's UI and how it is setup to send. My code does and add_block to the slave 
("ReadBlock", modbus_tk.defines.READ_HOLDING_REGISTERS, 11, 10)
then gets the data
values = slave.get_values("ReadBlock", 12, 2)
It returns values as a Tupelo (16523, 0)
16523 = 408B hex
I don't see the high byte 3405

How do I get the value 4.3501?

Mike

image.png

Mike Spath

unread,
Jun 13, 2019, 8:03:21 AM6/13/19
to modb...@googlegroups.com
Just a quick note, I changed the read address to 11 and now I see both the bytes (3405, 408B).
My main question is how to decipher what that represents in terms of the float value 4.3501

Mike

Mike Spath

unread,
Jun 13, 2019, 8:39:40 AM6/13/19
to modb...@googlegroups.com
I'm able to pack('HH', values[0], values[1])
then unpack that as a float and now I see the float value. ('f', packedVals)

result is 4.350100040435791

I do not know why I'm seeing the 40435791 pat of the value but at least I can see the float written by the master.

Thanks,
Mike
Reply all
Reply to author
Forward
0 new messages