Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 44 of 56

Modbus TCP: master and slave

An industrial protocol on the socket facade — and a library that deliberately owns none of your data.

The data model, not stored here

Modbus is big-endian on the wire, with four tables: coils (1-bit read/write), discrete inputs, input registers and holding registers.

This library never stores any of them. The application owns its data: the master fills caller-supplied buffers, and the slave is implemented by deriving from Modbus.Slave.Server and overriding the accessors. That is the right split for an embedded device — your registers are usually views onto real state (a sensor reading, a relay's position), not a block of memory that happens to be addressed twice.

Master and slave

Written against the facade

Like DNS and NTP, Modbus is written entirely against GNAT.Sockets, so the same source runs on a desktop and on the board. That is what makes an industrial protocol testable without a PLC on the bench: run the slave on a host, point a standard Modbus client at it, and you have exercised the wire format before any hardware is involved.

On a multi-interface board, a Modbus connection follows the routing table like any other socket, or can be pinned to one interface — which is what you want when the PLC network is deliberately separate from the internet-facing one.