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()
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.