Lab 1 — homeostasis by diffusion: thermal medium · build sheet

Eight nodes, one insulated box of air. Each node heats the shared bath under load and reads only its own sensor. Goal: ambient settles to setpoint with nobody in charge.

THE ONE RULE: the regulating scalar never becomes a packet. No node broadcasts its reading. Sense the common bath locally, respond locally.

1. Bill of materials

QtyItemNotes
8ESP32-S3 N16R8 (ESP32-S3-DevKitC-1 layout)Lonely Binary / any DevKitC-1-layout S3; internal temp sensor works in a pinch
8DS18B20 temperature sensorsor NTC + ADC divider; one per node, local only
84.7 kΩ pull-up resistorsDS18B20 data line
8power resistors ~10 Ω / 5 W (optional)heat source; CPU busy-loop is the free alternative
1insulated enclosurecooler, foam box, or capped pipe length
USB power for all boardsa powered hub or two; cables exit through one notch

2. Per-node wiring

SignalESP32 pinConnects to
DS18B20 dataGPIO 4sensor data, 4.7 kΩ pull-up to 3V3
DS18B20 VDD / GND3V3 / GNDsensor power
Load PWMGPIO 16gate of small MOSFET switching the 10 Ω resistor across 5 V
(skip entirely if using the busy-loop as the heater)

Board (ESP32-S3-DevKitC-1 layout, N16R8): GPIO 4 and GPIO 16 exist on the S3 and are unchanged from the classic-ESP32 wiring (1-Wire is pin-agnostic; GPIO 16 is a legal LEDC/PWM pin). On octal-PSRAM N16R8 leave GPIO 33–37 (PSRAM) and GPIO 26–32 (SPI flash) alone — touching them crashes the cache; safe GPIOs are 1–18, 21, 38–42, 47.

Nothing is wired between boards for control. The only shared thing is the air. Mount sensors in free air near each board, not touching the heater resistor.

THERMAL DECOUPLING: a sensor must never sit on the node it belongs to. It reads the shared box air, not its own board's heat — mounted on its own node it measures that one board, and the run produces a smooth, plausible, meaningless curve. Give every sensor 10–15 cm of lead out into the box's common air. Full build in §3.

Lab 1 per-node wiring, breadboard view

Per-node wiring, breadboard view — heater block at right is the optional section; MOSFET drawn by pin name (D·S·G), check your package's datasheet before wiring. Pin positions are correct; the USB connector shown is cosmetic (micro-USB in the drawing vs the lab boards' dual USB-C). Editable sketch: lab1_thermal_wiring.fzz

3. Sensor mounting — the pigtail assembly

Screw terminals, not breadboards. The wiring diagram above shows a breadboard because that is what Fritzing draws; the reference build does not use one. Each ESP32-S3 is seated in a screw-terminal breakout base, and each sensor is a small soldered assembly — a pigtail — that screws into three terminals. Nine breadboards would be nine more things to knock loose in a box you open, poke, and reseal repeatedly. The wiring is identical either way — DS18B20 data to GPIO 4, a 4.7 kΩ pull-up between data and 3V3, power and ground to 3V3 and GND — only the mechanical mounting differs. Building on breadboards? Follow the diagram literally and keep the sensor on leads.

Build a pigtail — nine of them (eight nodes and the gauge), roughly an hour sitting down. Per assembly: one DS18B20 (TO-92), three wires 10–15 cm long, three short lengths of heatshrink for the legs, one larger piece to sleeve the bundle.

  1. Cut and strip everything first. Twenty-seven wires — all the cutting, then all the stripping, then all the soldering is markedly faster than nine complete assemblies one at a time.
  2. Slide the heatshrink on before you solder. The universal lesson, relearned by everyone exactly once.
  3. Solder by colour, and get the pinout right (see the pinout rule below): red → VDD, yellow → DQ (data), black → GND.
  4. Shrink the individual legs, then sleeve the bundle. The individual sleeves are what stop the bare legs shorting against each other.
  5. Terminate at the board: red into 3V3, yellow into GPIO 4 (IO4), black into GND.
  6. The 4.7 kΩ pull-up goes in at the board end, bridging the 3V3 and IO4 terminals — two conductors in each of those two screws, which the terminal blocks handle without complaint. Putting it at the board rather than the sensor is deliberate: to try a different value or chase an unreliable 1-Wire line, it is a screwdriver away instead of buried under heatshrink.
TO-92 PINOUT: hold the sensor with the flat face toward you and the legs pointing down. Left to right: GND, DQ (data), VDD. Reversed power and ground makes the part warm and the reading absent — the most common DS18B20 mistake.

Before you seal the box: measure the spread. The sub-dollar sensors are not laboratory instruments and do not agree with each other perfectly. Before mounting them, pile all nine in one spot, let them sit ten minutes, and log them together; record how far apart they read and publish that number alongside your results — a stated uncertainty makes a result credible, an unstated one makes it suspicious.

Do not correct the node sensors. Nine nodes with slightly different ideas of the setpoint is not contamination of the experiment — it is the experiment: heterogeneous participants sharing one medium, regulating anyway. Correcting them would also require per-node configuration, and every node running byte-identical firmware is the point. Correct the gauge if you like — it is an instrument, not a participant, and its correction happens on the logging machine.

Sensor pigtail wired into an ESP32-S3 terminal base

Sensor on a soldered pigtail into the terminal base: the 4.7 kΩ pull-up bridges 3V3 and IO4 at the board, and the TO-92 sits 10–15 cm out in the box air. Inset shows the TO-92 pin order, flat face toward you.

4. Node loop (firmware logic — identical on all 8)

SETPOINT = 30.0        # °C, the collective target
GAIN     = 0.15        # droop slope — how hard to back off per degree over

every 2 s:
    t = read_own_DS18B20()
    duty = clamp(1.0 - GAIN * (t - SETPOINT), 0.0, 1.0)
    set_load_pwm(duty)          # or: busy-loop for duty fraction of the window
    # tell no one. write nothing to the network.

5. Read-only gauge (watch but never touch)

One extra sensor in the box center on a WIRED serial line out to a laptop — not on any node, not on WiFi it doesn't need. Log timestamp + °C. The gauge observes the bath; it is never in the control path. (Telemetry radio here would only add a small constant heat term, but wired keeps the demo pure.)

6. Bring-up procedure

7. Perturbation runs (the graphs that argue for you)

Keep every gauge log. Disturbance → recovery → nobody in charge is the thesis in one plot.