README preview — how these render on GitHub (temp page):front pageble-listenersht30-nodeds18b20-nodesdi12-readermodbus-readeranalog-readercwsi-nodeloadcell-water

OAT DS18B20 Temperature Node

One wire, many probes, every reading landing somewhere you own.

Status Liveflash from the browser, no IDE needed
Interface 1-Wire · DS18B20 (64-bit address per probe, up to ten on one bus)
Chips ESP32 · S3 · C3 · C6
Delivers Webhook (HTTP POST) · MQTT — oat-ods/0.3
License Apache-2.0

A self-configuring ESP32 node that reads one or many DS18B20 temperature probes on a single 1-Wire data line and pushes the readings as oat-ods to an endpoint the grower owns, by webhook or MQTT.

Everything except the sensor read is lifted from the SHT-30 Node, which took it from oat-ble-listener v1.4.8: config + NVS, the shared field registry (one applyField/readField behind both the web form and the serial Console), WiFi/AP/captive portal with connect-then-confirm, mDNS, the push engine (https-preferred with signed-http fallback, HMAC signing, oat-ods batch, monotonic seq), the 60 s health heartbeat, and the two-way USB Console. Set up one OAT node and you have set up all of them.

A grower flashes it from the browser at openagriculturetechnology.com/build/sketches/ds18b20-node/ (ESP Web Tools / Web Serial), then configures it on the device's own page. No IDE, no command line, no code editing.

Wiring

DS18B20 ESP32 wire colour on a sealed probe
VDD 3V3 red
GND GND black
DQ (data) the data pin (default below) yellow, sometimes white or blue

Plus one 4.7 kΩ resistor between DQ and 3V3 — see below. Every probe on the run shares all three wires.

The default data pin, per chip

Board Default Why not the same number everywhere
Classic ESP32 GPIO 4 free; not flash, not strapping, not input-only
ESP32-S3 GPIO 4 free
ESP32-C3 GPIO 4 free
ESP32-C6 GPIO 6 GPIO 4 is a strapping pin on the C6

A 1-Wire bus idles HIGH through its pull-up, which is exactly the nudge that flips a strapping pin into the wrong boot mode — so the C6 gets a different default rather than a shared one that would sometimes break a boot. pinOkForOneWire() refuses flash, strapping, USB-JTAG, UART0 and input-only pins per chip, with the reason, because a bad pin is persisted in NVS and re-applied at every boot: it is not a mistake you get to notice and correct.

Pin lists are from Espressif's per-chip GPIO documentation, not folklore.

The resistor is not optional

1-Wire is an open-drain bus: devices only ever pull the line DOWN, and a pull-up resistor is the only thing that pulls it back UP. With no resistor there is no bus at all, just a floating pin reading noise — which looks exactly like a broken sensor.

How many probes on one wire

The protocol sets no limit. Every DS18B20 carries a unique 64-bit address lasered in at the factory (family code 28h + 48-bit serial + CRC), and the node enumerates whatever is present with the ROM SEARCH command (F0h, the algorithm from Maxim application note 187). Addressing is not the constraint.

The electrical limit is real: every device and every metre of cable adds capacitance, which rounds off the edges of a 60 µs bit until the bus stops being readable. On a short run with the standard 4.7 kΩ pull-up, eight to ten probes is comfortable. This firmware caps its list at MAX_DS (10) for that reason — an honest bound of ours, not a protocol one, and it says so on the console when the list fills.

What it reports

measurement unit fold over the push window
temperature Cel mean

One stream per probe. source.physical_id carries the probe's own 64-bit address (ds18b20:28ff641f8c1a3b02), so a reading is traceable to a chip, not to a position in a list: swap a failed probe and the history of that spot carries on with the change of hardware visible in the record.

Probes are listed in address order, so the numbering on the setup page is stable across reboots even when one is added.

The parts that matter

Resolution

9 to 12 bits, set on the setup page and written to every probe on the wire.

bits step conversion
9 0.5 °C 93.75 ms
10 0.25 °C 187.5 ms
11 0.125 °C 375 ms
12 0.0625 °C 750 ms

Default is 12. The unused low bits at lower resolutions are masked rather than reported as decimal places they do not carry.

Specs above are from the DS18B20 datasheet (Analog Devices / Maxim): ±0.5 °C from −10 °C to +85 °C, ±2 °C over the full −55 °C to +125 °C range.

Files

File What it is
oat_ds18b20_node.ino The firmware source (Arduino / ESP32).
platformio.ini Build config. Four envs: classic ESP32, S3, C3, C6. Pinned libs.
merge_bin.py Post-build hook → one merged factory image per chip at out/firmware-<mcu>.bin, flashable at offset 0.
make_manifest.py Assembles manifest.json + manifest-<mcu>.json from whatever bins exist.
build.sh Builds, then copies bins + manifests + source downloads into the site assets.
docker-build.sh The same compile with no host toolchain (Docker + PlatformIO).

Build

pipx install platformio        # or: pip install --user platformio
./build.sh

No host toolchain?

./docker-build.sh              # compile all four chips in Docker
SKIP_BUILD=1 ./build.sh        # then the asset steps

build.sh produces one merged, flash-at-offset-0 image per chip in out/, plus the manifest and download bundle the OAT site's flash-from-browser page serves.


Code: Apache-2.0 · Docs: CC BY 4.0 · An OAT sketch — an OpenCDC initiative.