Lab 3 — homeostasis by diffusion: shared light field · build sheet

Eight nodes in one space. Each emits light into the shared field and senses the total field at its own spot, dimming where it's bright. A spatial gradient emerges — diffusion you can see and map. (Light variant; the RSSI variant exists but the light version is the visible, clean one.)

THE ONE RULE: the regulating scalar never becomes a packet. Each node just senses the common field and dims itself.
COROLLARY (this lab only): the gauge must not report through the medium being regulated. Light field + WiFi telemetry = already out-of-band, fine. RSSI variant + WiFi telemetry = the report perturbs the field — use wire, or characterize the gauge's emission as a known constant term.

1. Bill of materials

QtyItemNotes
8ESP32-S3 N16R8 (ESP32-S3-DevKitC-1 layout)Lonely Binary / any DevKitC-1-layout S3
8photodiodes or LDRsLDR + 10 kΩ divider is the cheap path; face UP into the field
8diffuse white LEDs + ~220 Ω resistorsemitters; diffuse beats clear (spreads into the bath)
1shared enclosureclosed box with light walls, or a dim room; ambient light is a confounder — control it
USB power for all boards

2. Per-node wiring

SignalESP32 pinConnects to
Field senseGPIO 5 (ADC1)LDR/photodiode divider midpoint (LDR to 3V3, 10 kΩ to GND)
LED PWMGPIO 16220 Ω → LED → GND; LED aimed up/out into shared space

Board (ESP32-S3-DevKitC-1 layout, N16R8): sense is GPIO 5 (S3 ADC1 = GPIO 1–10, WiFi-safe); the classic-ESP32 GPIO 34 is not an ADC pin on the S3. 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. The onboard RGB LED (GPIO 48) is not the field emitter — use the external diffuse white LED above.

Sensor must see the FIELD, not its own LED directly — small baffle (a washer of tape) between a node's LED and its own sensor keeps self-glare from dominating the common-bath reading. Spacing matters: spread the 8 nodes so gradients have room.

Lab 3 per-node wiring, breadboard view

Per-node wiring, breadboard view — LED drawn red by the stock part; use a diffuse white LED on the bench. Pin positions are correct; the USB connector shown is cosmetic (micro-USB in the drawing vs the lab boards' dual USB-C). Editable sketch: lab3_field_wiring.fzz

3. Node loop (identical on all 8)

F_SET = calibrated mid-scale reading    # the collective field target
GAIN  = tune on the bench (start 0.002 per ADC count)

every 100 ms:
    f = read_field_adc()
    duty = clamp(1.0 - GAIN * (f - F_SET), 0.0, 1.0)
    set_led_pwm(duty)
    # bright neighborhood → this node dims. no messages. ever.

4. Read-only gauge

One roaming sensor (phone lux meter, or a spare ESP32 + LDR on a WIRED serial lead) sampled at marked grid positions maps the spatial gradient. WiFi telemetry is acceptable in the light variant per the corollary — but the wired lead costs nothing and keeps the demo unarguable.

5. Bring-up procedure

6. Perturbation runs