2. Mai 2026Touch HMI
Steuerelektronik für Holz-Backöfen: ESP32-S3, Touch-Display und Klon-MAX31855, die ich erst überreden musste
ESP32-S3MAX31855ThermocoupleHolzbackofenTouch-DisplayPlatformIOMQTTHome Assistant

Werbe-Hinweis: Dieser Beitrag enthält Affiliate-Links (mit * markiert). Wenn du darüber kaufst, bekomme ich eine kleine Provision — für dich ändert sich der Preis nicht.
Sicherheitshinweis — Nachbau auf eigene Gefahr
Nachbau auf eigene Gefahr. Die Beschreibung ist eine persönliche Dokumentation, keine geprüfte Bauanleitung — Eignung für deinen Anwendungsfall musst du selbst prüfen.
Warum überhaupt Elektronik in einem Holzofen?
Ein Holz-Backofen kennt eigentlich nur zwei Zustände: zu kalt oder zu heiß. Wer schon mal eine Pizza Napoletana auf 470°C Bodentemperatur gemacht hat, weiß: 30°C zu wenig und der Teig wird gummig, 30°C zu viel und der Boden ist schwarz, bevor der Käse läuft. Mit dem Infrarot-Thermometer rumzulaufen ist Bastelei — vor allem, wenn parallel ausgeschossen, Holz nachgelegt und Teig geformt wird.
Klassische Pizza-Steuerungen für Profis kosten ab 600€ aufwärts und kommen meist als Klemmkasten ohne richtige Anzeige. Was mir bei den fertigen Lösungen fehlt: Kuppel- und Boden-Temperatur gleichzeitig, Live-Verlauf der letzten Minuten (so erkennt man die Abkühlkurve), ein Timer der weiß was eine Pizza Napoletana 90 Sekunden vs. ein Brot 40 Minuten bedeutet — und natürlich Home-Assistant-Integration, damit man beim Anheizen nicht neben dem Ofen stehen muss.
Also: eigene Elektronik. ESP32-S3, 2.8" Touch-Display, zwei K-Typ-Thermoelemente, Web-UI im Browser. Hardware unter 70 Euro, Entwicklungsaufwand ein langes Wochenende plus eine Hand voll Abende für Feinschliff.

Was die Steuerung macht
Der ESP32-S3 liest zwei K-Typ-Mantelthermoelemente (ø 3 mm, bis 1150 °C, Silikonkabel) — eines steckt in der Kuppel, das zweite kurz über dem Backstein. K-Typ ist Standard für hohe Temperaturen, das 1150 °C-Rating gibt massiv Reserve für die 500 °C, die der Ofen bei einer Napoletana macht.
Auf dem 2.8" Touch-Display zeige ich fünf Seiten zum Swipen:
1. Hauptseite — Kuppel- und Bodentemperatur, das aktuelle Programm, ein „Verdict" (AUFHEIZEN / BEREIT / ZU HEISS / ABKÜHLEN), und die Timer-Restlaufzeit
2. Verlauf — Live-Chart der letzten 6 Minuten mit Zielband fürs aktive Programm
3. Timer — Big-Buttons für Start, Stopp, +5 min, mit Statusanzeige
4. Netzwerk — IP, WLAN-Signal, MQTT-Status
5. System — Heap, Uptime, Firmware
Parallel läuft die Web-UI mit WebSocket-Live-Update und Chart.js — egal ob Handy oder Laptop, beide Anzeigen sind synchron. Der Web-Chart hält 30 min Verlauf (900 Samples bei 2-s-Tick), persistiert in `localStorage` — Reload startet nicht von vorn. Fünf Themes (Favorit: „Trattoria" mit Olivgrün und Terrakotta), Sprache auf Knopfdruck DE/EN.
11 Backprogramme sind hinterlegt, geordnet nach der natürlichen Abkühlkurve eines Holzofens — also genau die Reihenfolge, in der man an einem Anfeuer-Tag die Sachen reinschiebt:
| Programm | Kuppel | Boden | Default-Timer |
| --- | --- | --- | --- |
| Pizza Napoletana | 450-520°C | 380-450°C | 90 s |
| Pizza klassisch | 350-420°C | 320-380°C | 4 min |
| Flammkuchen | 300-360°C | 270-320°C | 3 min |
| Brot anbacken | 280-330°C | 250-290°C | 10 min |
| Brot ausbacken | 230-270°C | 210-250°C | 40 min |
| Semmel/Brioche | 210-240°C | 200-230°C | 15 min |
| Kuchen | 170-200°C | 160-190°C | 35 min |
| Schmoren | 150-190°C | 140-180°C | 2 h |
| Pflaumenmus | 100-140°C | 90-120°C | 4 h |
| Dörren | 55-75°C | 50-70°C | 6 h |
Eine Anfeuerung reicht so für Pizza → Flammkuchen → Brot → Kuchen → Schmoren → Pflaumenmus → Dörren. Acht bis zehn Stunden produktiver Hitzenutzung statt einmal Pizza und gut.

Die Hardware
Aufgebaut habe ich folgendes:
- **ESP32-S3 DevKit-C (N16R8)* — 16 MB Flash, 8 MB PSRAM. Rund 10 €. Zwei SPI-Busse parallel, schnell genug für Display-Refresh und TC-Reads ohne Race.
- 2.8" SPI TFT (ILI9341 + XPT2046)* — das chinesische Standard-14-Pin-Modul für rund 10 €. Touch-Controller direkt mit drauf.
- 2× MAX31855 K-Type Breakout* — die Klon-Variante von AliExpress für 3 € pro Stück. Adafruit-Original kostet 30 €. Mehr dazu im nächsten Abschnitt.
- 2× Mantelthermoelement Typ K bis 1150 °C, Silikonkabel von SensorShop24 — ø 3 mm, Einbaulänge 250 mm (MT/S-3-250-3.0) und 200 mm (MT/S-3-200-3.0), 3 m Kabel mit Aderendhülsen. Zusammen rund 60 € brutto. Wichtig: nicht das billige Bügeleisen-TC nehmen — das Mantel-Material muss ofen-tauglich sein.
- SHT31 Breakout* (optional, ~5 €) — I²C-Sensor für Lufttemperatur und Luftfeuchte am Gehäuse. Nicht in den Garraum — SHT3x sind nur bis 125 °C spezifiziert. Was er ermöglicht, gleich im nächsten Abschnitt.
- 5 V / 2 A Netzteil** — solide Versorgung ist Pflicht, dazu gleich mehr.
Zwei getrennte SPI-Busse sind der Schlüssel: Display + Touch laufen auf FSPI (GPIO 11/12/13), die beiden MAX31855 auf HSPI (GPIO 6/7). So stören sich Display-Refresh und TC-Reads nicht gegenseitig — getestet hatte ich auch shared SPI mit LovyanGFX-Bus-Lock, das funktioniert *bedingt*, ist aber spürbar weniger zuverlässig.
Dazu kommt: das Backlight des 2.8"-Displays will eine saubere Stromversorgung. An einer USB-Powerbank flackerte mir der Backlight-Boost — Ursache waren wegbrechende 3,3 V wegen schwacher 5-V-Quelle. Ein Stecker-Netzteil mit echten 2 A am 5-V-Pin und Ruhe ist.

Klon-MAX31855: erst defekt, dann brauchbar
Den unangenehmsten Teil des Projekts hab ich mir nicht ausgesucht — er kam von alleine. Die billigen MAX31855-Klone, die man bei AliExpress für 3 € bekommt, haben zwei Marotten:
1. Das Open-Circuit-Fault-Bit ist dauerhaft gesetzt. Die Adafruit-Library liest dieses Bit und gibt sofort NaN zurück — als wäre kein Thermoelement angeschlossen. Selbst mit ordentlich verbundener TC bekommt man also nur „—" auf dem Display. Bug Nummer eins.
2. ADC-Offset von 20-30°C. Auch wenn man das OC-Bit ignoriert, sind die Rohwerte systematisch verschoben. Manche dieser Module sind sogar gar keine MAX31855, sondern MAX6675-Klone in passendem Gehäuse — gleicher Fußabdruck, anderes Protokoll.
Lösung: eigener Raw-SPI-Read. Der Chip wird per SPI mit 5 MHz angesprochen, die 32 Bit roh eingelesen, und im Code entscheide ich selbst, welche Fault-Bits ich glaube. Das OC-Bit ignoriere ich auf den Klonen einfach — wenn die TC fehlt, wird das Ergebnis ohnehin durch Plausibilitätsprüfung gefiltert (ein Wert von -200°C ist halt offensichtlich keine echte Messung).
Den ADC-Offset löst eine 2-Punkt-Kalibrierung im Web-UI:
1. Eiswasser vorbereiten — Wasser plus reichlich Eiswürfel, das ergibt ziemlich exakt 0°C. TC eintauchen, 30 s warten, in Settings → Sensoren auf „Punkt 1" tippen
2. Kochendes Wasser — bei Meereshöhe 100°C, in der Höhe entsprechend weniger. TC umsetzen, 30 s warten, „Punkt 2 + berechnen" antippen
3. Gain und Offset werden gespeichert, NVS, fertig
Nach der Kalibrierung sind beide Sensoren auf ±15°C bei 500°C — gut genug für einen Holzbackofen, in dem die Temperatur ohnehin innerhalb der Kuppel um 20-30°C variiert. Wer es genauer braucht, kauft das Adafruit-Original; für Pizza und Brot reicht die Klon-plus-Kalibrierung locker.
Zur Verifizierung gibt's einen Diagnose-Endpoint `/api/maxdiag` — der zeigt Roh-32-Bit-Werte und Fault-Flags. Hat mir bei der Bug-Suche enorm geholfen.

Drei Engineering-Details die mehr ausmachen als sie aussehen
3-fach-Burst mit Median-Filter pro Sample. Auch nach der Kalibrierung zappeln die Klon-MAX31855 mit ~0,5–1 °C und werfen sporadisch NaN durch glitchende SPI-Reads. Drei Reads pro Tick, Median nehmen — Kurve wird visuell ruhig, einzelne Aussetzer fallen einfach raus.
Partial-Push am TFT statt Full-Frame. Ein voller Sprite-Push ist 320×240×16 = 153 KB pro Update. Auf billigen ILI9341-Modulen ohne TE-Pin sieht man das als Aufblitzen. Lösung: pro Screen nur die dynamischen Regionen pushen, statische Chrome bleibt einmal stehen. Spart rund 80 % SPI-Daten und das Tearing ist weg.
Optionaler SHT31 als Umgebungs-Referenz. Der I²C-Sensor sitzt am Gehäuse, ~10 cm Abstand zum heißen Mauerwerk, geschützt vor direkter Strahlung. Ist er nicht da, blendet die Firmware die Umgebungs-Anzeige automatisch aus. Was er aufschaltet:
- Newton-Cooling-Vorhersage: Während der Abkühlphase fittet die Firmware live die Zeitkonstante k aus den letzten 5 min — linearisiert über `ln(T − T_amb)`, dann lineare Regression. Display-Chart und Web zeigen dann „Ofen bei 200 °C in 1h45min, bei 100 °C in 5h30min". Sehr praktisch um zu wissen, wann das Brot rein muss.
- Taupunkt via Magnus-Formel (Sonntag-1990, ±0,4 °C). Kompakte Mini-Stat unter dem Web-Chart. Bei Outdoor-Aufstellung ein guter Kondensations-Indikator — wenn die Kuppel nachts unter den Taupunkt fällt, gibt's Schwitzwasser.
- Zwei zusätzliche HA-Sensoren (`amb_t`, `amb_rh`) tauchen automatisch in der Long-Term-Statistik auf.
5 € Sensor, drei sinnvolle Funktionen — keine Pflicht, aber ein deutlicher Mehrwert.
Timer mit Lerneffekt
Default-Backzeiten sind ein guter Startpunkt, aber jeder Ofen ist anders. Schamott speichert anders als ein dünnwandiger Kuppelofen, Buche brennt anders als Eiche, eine 30-cm-Pizza braucht länger als eine 28er. Statt also auf hundert vorgegebenen Standard-Werten festzuhängen, lernt der Timer aus den tatsächlich gefahrenen Bakes.
Wie's funktioniert: Bei jedem Start wird der Programm-Default genommen und an die aktuelle Ofentemperatur angepasst. Heißer Ofen → Vorschlag etwas kürzer, kühler Ofen → länger. Beim Drücken auf „Stopp" merkt sich das System die tatsächliche Backzeit. Ab der dritten Backung im selben Programm wird der Mittelwert dieser drei Bakes zur neuen Basis. Macht der Bediener weiterhin „Stopp" wenn die Pizza fertig ist, schleift sich der Wert immer weiter Richtung Realität ein — pro Ofen, pro Holzart, pro Pizzagröße automatisch passend.
Dazu der Cooling-Alarm: läuft ein Timer, und der Ofen kühlt schneller ab als das Programmfenster zulässt, gibt's eine Warnung. Praktisch beim Brotausbacken — fällt die Bodentemperatur unter 200°C, ist klar: nachfeuern oder das Brot rausnehmen.
Und ein Ready-Gate: Timer-Start nur, wenn der Ofen im Zielfenster ist. Verhindert, dass aus Versehen der 90-Sekunden-Pizzatimer gedrückt wird, während die Kuppel noch bei 250°C steht. Soll der Start trotzdem erzwungen werden, gibt's einen Force-Flag — z.B. für die bewusste Brot-Pizza.

Home Assistant und Session-Logger
Home Assistant zieht die Anlage automatisch ein — MQTT-Auto-Discovery erstellt zwei Sensoren (Kuppel, Boden) mit `state_class: measurement`, einen Programm-Select und einen Bereit-Binary-Sensor. Damit landen die Temperaturen in den Long-Term-Statistics — Aufheiz- und Abkühlkurven sind auch über Wochen hinweg auswertbar.
Der Programm-Select ist beidseitig: aus HA umschalten, und Display und NVS folgen. Praktisch, wenn der Bediener aus der Küche schon mal von „Pizza Napoletana" auf „Brot anbacken" wechseln will, ohne nach draußen zu laufen.
Parallel läuft im ESP der Session-Logger: jede Anfeuerung wird als CSV in LittleFS aufgezeichnet. Start automatisch ab 60°C, Stopp nach 10 min unter 40°C, maximal 12 Sessions im Ringbuffer. Im Web-UI gibt's eine Liste mit Download-Buttons — die CSV landet in Excel oder Grafana. So lässt sich nachvollziehen, wie verschiedene Holzmengen das Aufheizverhalten beeinflussen oder wie schnell der Ofen über Nacht abkühlt. Für die Entwicklung der Backprogramm-Defaults war dieser Logger entscheidend.
Offline-Toleranz war mir wichtig: Fällt das WLAN aus, läuft der Ofen weiter. Display, Sensoren, Timer, alles funktioniert. Nur die HA-Integration wartet auf Reconnect — der Watchdog versucht's alle 30 Sekunden. Captive Portal taucht nur bei Erstkonfiguration oder explizitem Reset auf, sonst nicht — sonst hängt das Ding bei jedem kurzen Router-Ausfall im Konfigmodus, und das war keine Option.
OTA-Updates über mDNS (`backofen.local`) machen das Flash-Kabel überflüssig, sobald das Gerät einmal im Netz ist.
Was hängengeblieben ist
Drei Sachen würde ich beim nächsten Aufbau direkt anders machen — und ein paar Sachen hab ich schon richtig gemacht und würde sie wieder so bauen:
Direkt zwei SPI-Busse statt shared SPI. Spart mir Stunden Debugging an Bus-Locks und Race-Conditions zwischen Display und MAX31855.
5 V Steckernetzteil statt Powerbank. Backlight-Flackern und Touch-Aussetzer waren reine Stromprobleme, nicht Code. Ein klares Signal, wenn das Display zuckt: erst Versorgung prüfen, dann Software.
AsyncMqttClient statt PubSubClient. Das Publishen aus dem Main-Loop hatte Task-Race-Probleme — der Async-Client ist sauberer, kein Watchdog-Reset mehr beim ersten WLAN-Hänger.
Captive Portal nur bei Erstkonfiguration. Erste Version öffnete den Konfigmodus bei jedem WLAN-Drop — beim zweiten Router-Reboot stand der Ofen plötzlich offline da. Heute nur bei explizitem WLAN-Reset (BOOT-Button beim Einschalten gedrückt halten).
Em-Dash und Mid-Dot sind nicht in jedem Adafruit-GFX-Font. Auf dem Display nur ASCII verwenden, sonst Tofu-Rechtecke.
TX-LED blinkt synchron zum Display-Push. Klon-DevKits mit CH343P-USB-Bridge haben ihre TX/RX-LEDs direkt an UART0 (GPIO43/44). Wenn UART0 nicht aktiv getrieben wird, koppelt der SPI-Burst kapazitiv ein, der CH343 sieht das als „UART-Verkehr" und zappelt mit. Sah aus wie Software-Bug, war reines Crosstalk. Fix: GPIO43 nach `Serial0.end()` aktiv auf HIGH (UART-Idle), GPIO44 auf `INPUT_PULLUP`.
Auf der Roadmap steht: ein PCB statt DevKit (60×40 mm, 2-Layer mit TPS63020), Adafruit-Original-MAX31855 als Plan B falls die Klone irgendwann driften, ein Tür-Reed-Sensor für klügere Cooling-Erkennung und vielleicht ein MLX90614 IR-Pyrometer als kontaktloser Boden-Oberflächensensor — der könnte den heißeren Steinboden direkt messen, statt nur die Luft drüber.
Wer einen Holz-Backofen oder einen Steinbacker zu Hause stehen hat und ohnehin Home Assistant fährt, für den ist das eine sehr lohnende Wochenend-Bastelei. Im Testbetrieb läuft die Steuerung stabil — die Temperaturkurve ist sichtbar ruhiger geworden, der Boden brennt nicht mehr an, und jede Session liegt als CSV im Archiv. Die Backprogramm-Defaults haben sich nach den ersten zwei Anfeuerungen schon spürbar in die Realität eingeschliffen.
Mehr technische Details zu diesem Projekt:
Zum Projekt →* Werbung — Die mit Sternchen (*) gekennzeichneten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision — für dich ändert sich der Preis nicht.
Mike Sobczinski
Embedded-Entwickler und Schichtarbeiter in der Halbleiterindustrie. Baut IoT-Lösungen mit ESP32, LoRa und Home Assistant — von der Firmware bis zum Dashboard.
Mehr erfahren →