contains firmwares and PCB layouts for my own homebrew homebrew setup
  • C 77.3%
  • TypeScript 7.2%
  • JavaScript 6.3%
  • Python 4.3%
  • Shell 2.4%
  • Other 2.5%
Find a file
Bruce 58d1d2d598 HA: pick any available switch as each pump's relay
Add per-pump input_select (brewery_hlt/mlt_pump_relay) listing "none" + every
available switch, seeded from the current set and refreshed every 30 min by a
brewery automation (input_select.set_options). Mirror automations command the
selected switch from each pump's input_boolean; reassigning releases the old
switch and syncs the new one to the current pump state. Dashboard gains a
"Pump relays" card on Setup & Tuning.

Scope: only brewery_* entities/automations are added in the brewery package and
dashboard. Other systems' switches are merely listed as options and commanded —
never reconfigured.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015TZvMeBZ55diAmoDiJRvfg
2026-06-30 13:37:52 +08:00
boil_controller boil_controller: one dynamic output per channel (merge manual duty + output) 2026-06-29 21:19:09 +08:00
brewery_common fwupdate: richer HA update entity (title, release_url, notes, % progress) 2026-06-28 17:11:54 +08:00
homeassistant HA: pick any available switch as each pump's relay 2026-06-30 13:37:52 +08:00
old Brewery monorepo: temp probe + boil controller + shared component 2026-06-28 17:03:03 +08:00
stand_alone_temp_probe stand_alone_temp_probe: reject spurious high-temperature spikes at source 2026-06-30 10:48:28 +08:00
tools deploy.sh: bash 3.2 compatible (no associative arrays) 2026-06-29 08:19:00 +08:00
.gitignore Brewery monorepo: temp probe + boil controller + shared component 2026-06-28 17:03:03 +08:00
CLAUDE.md tools/deploy.sh: one-step build+upload+manifest(+install); document strategy 2026-06-29 08:18:17 +08:00
README.md docs: README layout/diagram tweaks 2026-06-29 08:20:43 +08:00

Brewery control system

Monorepo of firmware and hardware for an automated HERMS brewery, built around a small fleet of networked temperature probes feeding a central heating controller — all coordinated over MQTT (with Home Assistant discovery, so the whole rig shows up in HA automatically).

Layout: stand_alone_temp_probe/ (RTD probe firmware), boil_controller/ (HERMS/boil controller firmware), brewery_common/ (shared ESP-IDF component: OTA, firmware version-check, network log tap — used by both firmwares via a component-manager path dependency), old/ (reference designs + the original KiCad schematic), tools/ (build helper).

            ┌──────────────────────┐
   HLT  ───▶│ temp probe (RTD)     │──┐
   mash ───▶│ temp probe (RTD)     │──┤   mechination/<id>/temperature
   boil ───▶│ temp probe (RTD)     │──┤      (WiFi, retained, >=1 Hz)
   …    ───▶│ temp probe (RTD)     │──┤
            └──────────────────────┘  │
                                      ▼
                             ┌─────────────────┐
                             │   MQTT broker   │  (+ Home Assistant)
                             └─────────────────┘
                                      │ subscribes to the probe temps
                                      ▼
                       ┌────────────────────────────┐
                       │  boil / HERMS controller   │  ESP32-WROVER
                       │  PID ──▶ ULN2003A ──▶ SSRs │
                       └────────────────────────────┘
                               │            │
                           HLT element   Boil-kettle
                          (heats HERMS)    element

The two firmwares we host here

1. stand_alone_temp_probe/ — temperature probe

Seeed XIAO ESP32-C6 + Adafruit MAX31865 RTD amplifier. Reads a PT100/PT1000 RTD, joins WiFi, and publishes its temperature to MQTT (retained, ≥ 1 Hz) with Home Assistant discovery and RTD-fault reporting. One probe per measured point — give each a distinct device id (hlt, herms_out, boil_kettle, …) so they share the MQTT tree without colliding.

Note: the firmware is WiFi + MQTT (see main/temp_probe.h, idf_component.yml). The probe's own README.md still describes an earlier Zigbee revision and is being updated — trust the WiFi/MQTT build.

2. boil_controller/ — boil / HERMS controller

ESP32-WROVER + ULN2003A + 2× mains SSR. Subscribes to the probes' MQTT temperatures, runs a PID loop per heated vessel, and drives the SSRs with time-proportional output:

  • HERMS channel — modulates the HLT element to hold the mash temperature (wort recirculating out of the HERMS coil), with an HLT over-temp cutout.
  • Boil channel — drives the boil-kettle element to a setpoint.

The first two ULN2003A channels drive the SSRs; the other five are broken out for future use (pumps, alarm, …). It supports OTA updates over MQTT so we can iterate without touching the hardware. See boil_controller/README.md.

Temperature sensors

Each is an independent standalone probe publishing to MQTT. Planned points:

Probe device id Measures Used by the controller for
hlt Hot Liquor Tank HERMS over-temp cutout
herms_out MLT output / mash temp off the HERMS coil HERMS PID process variable
boil_kettle Boil kettle Boil PID process variable
(more) e.g. mash-in, ambient future channels / logging

Topic convention (shared prefix): mechination/<device_id>/temperature, with availability at mechination/<device_id>/status and a per-reading …/temperature/status that goes offline on an RTD fault (so the controller can fail-safe).

old/ — previous designs (reference only)

The earlier brewery was Bluetooth-based and is superseded by the WiFi/MQTT design above. Kept for reference:

  • old/brewery-circuit/the original controller schematic + PCB (Brewery.kicad_pcb, KiCad/2019): ESP32-WROVER + ULN2003A + LTC2986. This is where the boil-controller pinout came from.
  • old/ssr/ — BLE-central SSR firmware (an ESP-IDF BLE example, not the real app)
  • old/hw/SSR/ — single-channel SSR PCB (PN2222A driver + opto) — still useful HW
  • old/hw/Temp_probe/ — temp-probe PCB
  • old/temp_sensor/ — MicroPython MAX31865 driver
  • old/zephyr_temp/ — Zephyr RTOS temperature app
  • old/web/ — the old Web-Bluetooth brewery dashboard

The old boil-controller firmware was not recovered (nothing referencing the LTC2986 exists under ~/dev, and the old system was Bluetooth-based), so boil_controller/ is a clean rebuild. The hardware schematic survives in old/brewery-circuit/, and the controller pinout is taken from it:

Function GPIO
SSR — HERMS/HLT (ULN OUT3) GPIO32
SSR — Boil (ULN OUT4) GPIO33
Spare ULN outputs (OUT57) GPIO25/26/27
LTC2986 SPI (unused) MOSI 23, MISO 19, SCLK 18, CS 5, DRDY 4

⚠️ The board's first two ULN channels (DO1/DO2) land on GPIO34/35, which are input-only — they can't drive outputs, so the SSRs use the first output-capable channels (DO3/DO4 → OUT3/OUT4). The LTC2986 is dropped from the design (temps come over MQTT) but is held quiescent in firmware since it's still populated on the board. Details in boil_controller/README.md.

Building

Both firmwares are independent ESP-IDF projects (ESP-IDF ≥ 5.3; tested with the installed ~/esp/esp-idf). Build each from its own directory:

. ~/esp/esp-idf/export.sh

# Temperature probe (XIAO ESP32-C6)
cd stand_alone_temp_probe
idf.py set-target esp32c6
idf.py menuconfig          # WiFi, MQTT, device id, RTD type/pins
idf.py -p <PORT> flash monitor

# Boil controller (ESP32-WROVER)
cd ../boil_controller
idf.py set-target esp32
idf.py menuconfig          # WiFi, MQTT, sensor topics, ULN GPIOs, PID gains
idf.py -p <PORT> flash monitor

The two boards target different chips (esp32c6 vs esp32), so keep their build trees separate (each has its own sdkconfig). A convenience script is at tools/build.sh:

./tools/build.sh both        # build both
./tools/build.sh probe       # just the temp probe
./tools/build.sh boil flash  # build + flash the controller (auto-detects port)

After the controller's first USB flash, subsequent updates can go over the air — see boil_controller/README.md.