No more dealing with cloud services or crappy proprietary apps for your home sauna - this is an open-source sauna controller allowing you to control your sauna from anywhere but without any commercial/cloud dependenceies via ESPHome + Home Assistant.
The design offers robust controls of both the heater and lights, along with safeties similar to a commercial unit, including:
- Contol of a heater via a 24 VDC coil contactor
- Dual highly accuracy temp sensors (primary high on the wall + one closer to the sitting bench)
- RGBW under-bench lighting (24 V, PWM via MOSFETs)
Safeties include
- Hardware manual-reset high-limit in series with the coil (failsafe)
- Door safety (instant off + timeout fault)
- Strong fault model (latching) + optional contactor auxiliary feedback + high-limit status sensing
While the ESP handles the actual control of the sauna, currently all input is done via Home Assistant - in the future I'll add a physical hardware controller based on a second ESP Board + TFT Display + rotary encoder that can be installed at the door of the sauna.
⚠️ Electrical safety: This project switches lethal voltages. Get a licensed electrician/PE to review & install. Use appropriately rated components and follow local code.
The total cost for the hardware should be a bit <$500 + whatever lighting you choose to use
The single largest cost is the contactor ($100-$150 USD, depending on size) - while there are cheaper options out there, this is the heart of the system and handles a lot of power flowing through it
The other big cost is that various DIN rail parts - I chose to use DIN rail components in order to keep things very clean, but if that's not a priority, you can skip many of those and save $50-$100.
- 24 VDC single rail (Mean Well HDR-150-24) feeds:
- Contactor coil (through DIN fuse → manual-reset high-limit → coil)
- RGBW LED strip branch (separate DIN fuse)
- DDR-15G-5 → 5 V for ESP32 + MAX31865 boards
- Low-side MOSFET drivers (Adafruit PID 5648) for:
- Coil (1× board)
- RGBW (4× boards: R/G/B/W channels)
- Separation: HV (feeder → contactor → heater) and LV (24 V, logic) kept segregated
- Hardware: Manual-reset high-limit (e.g., SUPCO SRL250, ~250 °F) in series with coil kills heat independent of software.
- Software:
- Software high-temp limit (default 210 °F)
- ΔT stratification fault (ceiling vs bench)
- Door open timeout fault
- Session auto-off
- Sensor NaN faults + bench fallback (optional, with offset)
- WDT (30 s): any hang → reboot → coil defaults OFF
- Diagnostics:
- Contactor aux feedback (detects welded or failed-to-close)
- Optional SRL250 status input (shows “High-Limit Tripped”)
last_trip_reasontext + HA notifications (see automations)
- ESP32 DevKitC-32E (1×)
- Contactor ≥65 A, 24 VDC coil — Schneider Easy TeSys DPE65BD (1×)
- Auxiliary contact block compatible with DPE65BD (1× NO or 1NO/1NC)
- 24 V DIN PSU 150 W — Mean Well HDR-150-24 (1×)
- 24→5 V DIN DC-DC — Mean Well DDR-15G-5 (1×)
- DB18B20 probes (2×)
- MOSFET driver boards — Adafruit PID 5648 (5× total: 1× coil, 4× RGBW)
- LEDYi 24 V RGBW sauna strip ~5 m (1×), aluminum channel + frosted lens (~5 m)
- Manual-reset high-limit — SUPCO SRL250 (~250 °F, NC) (1×)
- DIN fuse holders (10×38 mm) + fuses:
- 1–2 A (coil branch)
- 7.5 A time-delay (LED branch; size per LED power)
- Phoenix Contact DIN terminals (HV/LV), ground terminal, jumper bars
- 5-core high-temp silicone cable (18 AWG) for LED, shielded twisted pair for DS18B20s
- High-temp cable glands for wires
- Enclosure (recommended): 500×400×200 mm polycarbonate with backplate
- Feeder 240 V → contactor (power poles) → heater. Ground/bond per code. Keep HV/LV physically separated.
- HDR-150-24 → 24 V bus (+24 V/0 V).
- DDR-15G-5 from 24 V → 5 V to ESP32 VIN. 0 V common for all LV.
- +24 V → DIN fuse (1–2 A) → SRL250 (NC, manual-reset) → contactor coil (+)
- Contactor coil (−) → MOSFET driver OUT− / OUT+ → OPEN (coil channel)
- Driver VIN 24V; GPIO13 → SIG; GND → GND
Optional inputs (recommended):
- SRL250 status (tripped/open = TRUE): 24 V across SRL250 → opto input → GPIOXX.
- Contactor aux feedback (aux closed = TRUE): 24 V → aux → opto input → GPIOXX.
- Reed: one lead to GND, other to GPIO22 (INPUT_PULLUP). Firmware: immediate OFF + timeout fault.
- BUS1=GPIO26 (Bench)
- BUS2=GPIO27 (Ceiling)
- 3.3V to VIN; 0 V common
- +24 V → DIN fuse (LED) ~7.5 A TD → strip V+
- R−/G−/B−/W− → each to its MOSFET driver OUT−; all OUT+ → OPEN
- PWM pins:
- GPIO16 → Red SIG
- GPIO17 → Green SIG
- GPIO18 → Blue SIG
- GPIO19 → White SIG
- 5-core 18 AWG silicone cable through high-temp gland; mount strip under benches in aluminum channel with screws. Power-inject V+ at both ends if needed.
- Single 0 V star (ESP32, drivers, DC-DC, PSU, etc).
- Label terminals: 24V+, 0V, COIL+, COIL−, LED_V+, LED_R−/G−/B−/W−, RTD1, RTD2, DOOR, AUX_FB, HLIMIT_FB.
Power
- VIN (5 V) ← DDR-15G-5
- GND ← 0 V common
- 3V3 → DS18B20 VCC (both)
DS18B20 Temp Sensors
- GPIO26 Bench
- GPIO27 Ceiling
Inputs
- GPIO22 Door (INPUT_PULLUP)
- GPIO32 Contactor Aux Closed (via opto) — TRUE = aux closed
- GPIO33 High-Limit Tripped (via opto) — TRUE = SRL250 open
Outputs
- GPIO13 Coil MOSFET SIG
- GPIO16/17/18/19 RGBW MOSFET SIG (R/G/B/W)
Reserved
- GPIO25/26 reserved for future RS-485
- GPIO0/2/12/15 NC (boot straps)
- GPIO1/3 UART (leave free)
The actual control software runs entirely on the ESP32, the UI is via Home Assistant - in the future I'm likely to build a physical controller for it as well
