Sorry for my bad english. I try to write and read float in a plc register in python via Modbus using pyModbusTCP lib. This is my code that unfortunatly didn't go...
from pyModbusTCP.client import ModbusClient
from pyModbusTCP import utils
class FloatModbusClient(ModbusClient):
def read_float(self, address, number=1):
reg_l = self.read_holding_registers(address, number * 2)
if reg_l:
return [utils.decode_ieee(f) for f in utils.word_list_to_long(reg_l)]
else:
return None
def write_float(self, address, floats_list):
b32_l = [utils.encode_ieee(f) for f in floats_list]
b16_l = utils.long_list_to_word(b32_l)
return self.write_multiple_registers(address, b16_l)
c = FloatModbusClient(host=ip, port=porta, auto_open=True)
# write 10.0 at @0
c.write_float(registrow, [var])
print("write ok")
# read @0 to 9
float_l = c.read_float(registror)
print(float_l)
c.close()
Can someone help me?
This is little bit tricky because all Modbus registers are only 16-bit unsigned data
(those who are intended for sending numbers
):
Object type | Access | Size | Address Space
Coil | Read-write | 1 bit | 00001 - 09999
Discrete input | Read-only | 1 bit | 10001 - 19999
Input register | Read-only | 16 bits | 30001 - 39999
Holding register | Read-write | 16 bits | 40001 - 49999
Int
).Float
to Int
and from Int
to Float
both on Server side and Client side.Client
.Float
data via Modbus you need to transform them via simple multiplication or division.This is code that will allow you as a Client
send positive Float
numbers from Python to Modbus server:
from pyModbusTCP.client import ModbusClient
def send_single_float(client, reg_addr, reg_value, setting, by):
if setting == "multiply":
client.write_single_register(reg_addr = reg_addr, reg_value = int(reg_value*by))
elif setting == "divide":
if reg_value == 0:
client.write_single_register(reg_addr = reg_addr, reg_value = int(reg_value))
else:
client.write_single_register(reg_addr = reg_addr, reg_value = int(reg_value/by))
else:
raise TypeError("Only string with following values can be set for 'Setting' attribute: ('multiply', 'divide')")
c = ModbusClient("localhost")
c.open()
my_float = 10.05
while True:
send_single_float(c, 0, my_float, "multiply", 100)
You can use also this function to read Float
numbers from Modbus:
def read_single_float(client, reg_addr, setting, by):
if setting == "multiply":
return client.read_holding_registers(reg_addr = reg_addr, reg_nb = 1)[0] * by
elif setting == "divide":
data = client.read_holding_registers(reg_addr = reg_addr, reg_nb = 1)[0]
if data == 0:
return data
else:
return data / by
else:
raise TypeError("Only string with following values can be set for 'Setting' attribute: ('multiply', 'divide')")