Modbus#
Description#
We use the library PyModbus for our python programs that need a Modbus connection. This library provides classes for both client and server. Several examples are available directly on their webpage.
Here is a basic server with Holding registers :
from pymodbus.server.sync import StartTcpServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadBuilder # Holding registers start at : START_ADDRESS_READ = 30000 # start server def run_server(): # Initialize the server configuration, we only need a few Holding Registers store = ModbusSlaveContext( hr=ModbusSequentialDataBlock(START_ADDRESS_READ, [0.0] * 100)) context = ModbusServerContext(slaves=store, single=True) # Set one of the holding register builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_32bit_float(27.3) payload = builder.to_registers() context[0].setValues(3, START_ADDRESS_READ, payload) # Initialize the server information identity = ModbusDeviceIdentification() identity.VendorName = 'SPL' identity.ProductCode = '' identity.VendorUrl = '' identity.ProductName = 'Pymodbus Server' identity.ModelName = 'Virtual Server' identity.MajorMinorRevision = '2.3.0' # Run the server StartTcpServer(context, identity=identity, address=("localhost", 1234)) if __name__ == "__main__": print("Launching the server !") run_server()
The client that could read registers from this server :
from pymodbus.client.sync import ModbusTcpClient from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from pymodbus.register_read_message import ReadHoldingRegistersResponse from pymodbus.pdu import ExceptionResponse from pymodbus.exceptions import ModbusIOException START_ADDRESS_READ = 30000 REGISTERS_NUMBER = 2 SLAVE_ID = 1 # from bytes to float def process_data(modbus_response, verbose): decoder = BinaryPayloadDecoder.fromRegisters(modbus_response.registers, endian=Endian.Big) position = decoder.decode_32bit_float() return position if __name__ == "__main__": client = ModbusTcpClient(ip_address_plc, port=modbus_port_plc) is_connected = client.connect() data = client.read_holding_registers(START_ADDRESS_READ, count=REGISTERS_NUMBER, unit=SLAVE_ID) if isinstance(data, ReadHoldingRegistersResponse): position = process_data(data, print_in_terminal)
Ressources#
The documentation of the PyModbus library can be found here.
Examples#
One can find a an example in the DT repo for the odometry.