Industrial sensors speak Modbus over RS-485: rugged, multi-drop, good over long noisy cable runs. This node reads their registers and pushes each as oat-ods, the bridge from the factory-floor bus into data you own.
What it does.
Reads Modbus RTU sensors over RS-485 and emits each register as oat-ods: the industrial-bus bridge into data you own, multi-drop and robust over long noisy runs.
That’s the Collect layer for one more kind of sensor: it reads the instrument, shapes each reading into the one oat-ods message every Open Agriculture Technology device speaks, and pushes it to a place you own. The value is what you do with the reading later; this just gets it flowing.
What it reads.
Each reading goes out as its own oat-ods message, filed under the place you name, so swapping the hardware later never breaks the record:
What you need.
Wiring. An RS-485 transceiver on a hardware UART: RX, TX, and (for a MAX485) a DE/RE direction pin (use -1 for an auto-direction module). Match the slave’s baud (default 9600) and 8N1. RS-485 is multi-drop, so many slaves share one A/B pair.
The register map.
Modbus registers are bare numbers, so you describe them on the setup page, one line per slave:
<slave> <stream_id> <reg>:<type>:<measure>:<unit>:<scale>,… 1 gh2-env 0:i:temperature:Cel:0.1,1:i:humidity:%RH:0.1 2 gh2-flow 100:h:flow:l/min:0.1
type: h = holding register, i = input register. value = (signed 16-bit) raw × scale.
What it sends.
It pushes to wherever you point it (Webhook (HTTP POST) or MQTT) as
oat-ods/0.3. One measurement per message; here’s a reading from this node:
{
"schema": "oat-ods/0.3",
"observed_at": "2026-06-25T14:30:00Z",
"stream": { "id": "gh2-env", "name": "…", "location": "…" },
"measurement": "temperature",
"value": 23.4,
"unit": "Cel",
"source": { "tier": "oat-modbus-reader", "gateway_id": "…", "physical_id": "modbus:1:0" }
}
That’s the same envelope the whole library speaks. Point it at your webhook, an Home Assistant broker, or Open Agriculture Technology; the receiver can’t tell which node produced it. The developer reference has the full spec.
Get it & build it.
The project downloads whole: the sketch plus the shared oat_ods library it needs, so it
builds as-is:
Full PlatformIO project (.zip) Just the sketch (.ino)
Two ways to put it on a board, both free:
- PlatformIO (builds all four ESP32 chips): unzip, then
cd oat-modbus-reader && pio run -t upload. The bundledlib/oat_ods/resolves automatically. - Arduino IDE: open the
.ino, install the libraries below from the Library Manager, pick your ESP32 board, and upload.
Compile-verified on our side (it builds clean with the pinned toolchain), but not yet run on the bench with real sensors, so it ships as source rather than a browser image. If you run it, tell the collective how it went; that’s what turns it into a flash-from-browser sketch.
Set it up.
Setup happens on the device’s own page: nothing to install, works with no internet:
- Power the node from any USB charger or your computer.
- Join its Wi-Fi network
OAT-Modbus-XXXX, and the setup page opens (or visithttp://192.168.4.1). - Sign in, set your Wi-Fi, where the readings go, and the sensor details above, then save.
- Point delivery at the test endpoint and watch your first reading arrive, checked against the standard.
Settings persist across reboots; a fresh flash wipes them, on purpose, so a re-used board never carries the last owner’s Wi-Fi or endpoint.
Notes.
- Each register becomes one oat-ods message, with
physical_idrecordingmodbus:<slave>:<reg>for provenance. - RS-485 shines over long, electrically noisy runs where a short I²C or analog wire would fail.
For makers & trainers.
Frequently asked questions.
How do I read a Modbus RTU sensor with an ESP32?
Add an RS-485 transceiver (such as a MAX485) to a hardware UART on the ESP32 and use a Modbus master library to read holding or input registers. Because registers are bare numbers, you map each register to a measurement, unit, and scale factor, so the reading becomes value = raw × scale.
What is RS-485 and why use it for sensors?
RS-485 is a rugged, differential serial bus that works over long, electrically noisy cable runs and supports many devices on one pair of wires (multi-drop). It is the common physical layer for Modbus RTU industrial sensors, which suits spread-out greenhouse or farm installations where short-range buses fail.