Build · Sketch · source · v1.0.0

Modbus / RS-485 Reader.

What it does
Reads Modbus RTU registers over RS-485 and pushes each as oat-ods
Interface
RS-485 · Modbus RTU
License
Open: copy it, change it, own it

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:

  1. PlatformIO (builds all four ESP32 chips): unzip, then cd oat-modbus-reader && pio run -t upload. The bundled lib/oat_ods/ resolves automatically.
  2. 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:

  1. Power the node from any USB charger or your computer.
  2. Join its Wi-Fi network OAT-Modbus-XXXX, and the setup page opens (or visit http://192.168.4.1).
  3. Sign in, set your Wi-Fi, where the readings go, and the sensor details above, then save.
  4. 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_id recording modbus:<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.