Techman read / write values using Modbus

You can read and write Modbus values with Python.

All you need is this Python module:

from pyModbusTCP.client import ModbusClient
c = ModbusClient(host="192.168.0.1", auto_open=True)

while True:
    # read 16 bits at address 0, these are the Digital Outputs for the TechMan
    bits = c.read_coils(0, 16)
    print("bit ad #0 to 9: "+str(bits) if bits else "read error")
    # sleep 2s
    time.sleep(2)

It is also possible to read / write floats, but so far only user defined values can be read:

# how-to add float support to ModbusClient

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='192.168.0.1', port=502, auto_open=True)

c.write_float(9000, [123.0])
# read @0 to 9
float_l = c.read_float(9000)
print(float_l)

c.close()

To read a X,Y,Z coordinate you have to read a input register instead of a holding register. It still is a float so we copied the read_float function and made some adjustments.

Could you post your adjustments? :slight_smile:

We added this function to the class FloatModbusClient:

   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 read_input_registers_float(self, address, number=1):
        reg_1 = self.read_input_registers(address, number * 2)
        if reg_1:
            return [utils.decode_ieee(f) for f in utils.word_list_to_long(reg_1)]
        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)
    
    def write_single_register_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_single_register(address, b16_l)

And call the function in this way:

c_f = FloatModbusClient(host='192.168.0.1', port=502, auto_open=True)
x_pos = c_f.read_input_registers_float(7001,2)
print (x_pos)
1 Like