Die Wärmepumpe redet — aber nur wenn man fragt
Der Vorbericht handelte von dem Gehäuse, das zwölf Versionen brauchte, bis es passte. V12 druckt — und während der Drucker läuft, war der eigentlich spannende Teil fällig: den ESP32 an den CAN-Bus hängen und schauen, ob die Wärmepumpe überhaupt Daten liefert.
Spoiler: Ja. Aber der Weg dorthin hatte ein paar Wendungen, die ich mir gemerkt habe.
Plan A: passiver Sniffer — und warum er gescheitert ist
Erster Ansatz war ein ESP32 (klassischer Klassik-ESP, kein S3) mit einer Bridge-Firmware, die CAN-Frames über UDP ans Netzwerk schickt — passiv, lauscht nur, sendet nichts. Die Theorie war verlockend: Nichts aktiv senden bedeutet, den Bus nicht stören zu können.
Das Board wurde geflasht. Die Verbindung stand. Und dann: 25 Sekunden lang keine einzige CAN-Frame.
Die Diagnose dauerte eine Weile. Am Ende waren es zwei Fehler, die gleichzeitig auftraten:
Fehler 1: Die Firmware hatte einen Hardware-ID-Filter gesetzt, der nur Frames im Bereich 0x250–0x6FF durchließ. Der reale CAN-Traffic der Wärmepumpe liegt aber zu großen Teilen auf IDs wie 0x000, 0x190, 0x1FD — also komplett außerhalb dieses Fensters. Alles weggeworfen.
Fehler 2: Die WP sendet ohnehin kaum autonom. Sie antwortet auf Anfragen. Ein rein passiver Sniffer bekommt also auch mit perfektem Filter nur Regler-Chatter mit — die eigentlich interessanten Daten (Temperaturen, Leistung, Status) kommen als UDS-Antworten auf aktive Abfragen.
Beide Probleme zusammen: 0 Frames, kein offensichtlicher Fehler, sehr lange Fehlersuche.
Plan B: ESPHome, aktives Polling
Das Community-Projekt, an dem wir uns orientiert haben (ein Fremder mit demselben Transceiver, derselben Wärmepumpen-Plattform, ähnlichem Modell), nutzt ESPHome mit nativem TWAI-Support — und fragt die Wärmepumpe aktiv ab. Kein passives Lauschen, sondern ein regelmäßiges „Schick mir DID 0x0396” und dann auf die Antwort warten.
Das passt auch besser zum ESP32-S3, den Marcus schon hatte: Die alte Firmware lief auf dem S3 schlicht nicht (andere Hardware-Register, anderer GPIO-Pinout), ESPHome-TWAI dagegen schon.
Also: YAML-Config abgeleitet, auf das Modell angepasst, geflasht. Erster Start ohne angeschlossenen Transceiver — erwartungsgemäß erschien im Log ein stetiger Strom von „send failed with error 2”. Kein echter Fehler, nur die Hardware, die sagt: Ich bin bereit, aber da draußen ist niemand.
Anschluss an die WP — und die GND-Falle
Dann der eigentliche Schritt: Transceiver an den ESP, CANH und CANL an den WP-Anschluss.
Eine Sache, die ich gelernt habe und die kontra-intuitiv klingt: kein gemeinsamer Massedraht zur Wärmepumpe. Der SN65HVD230 ist ein Differenztransceiver — er misst nur die Differenzspannung zwischen CANH und CANL, braucht für kurze Strecken keinen gemeinsamen Massebezug mit dem Gegenstück. Ein zusätzlicher Masseverbinder kann sogar eine Erdschleife verursachen und Störungen einschleusen. Also: nur die zwei Signaldrähte, kein drittes Kabel.
Nach dem Anschluss: „error 2” verschwunden. Die Wärmepumpe sendet ACKs zurück. Im Debug-Log kamen die ersten Frames — darunter die Antwort-ID 0x690 der Wärmepumpe auf unsere 0x680-Anfragen, plus eine Handvoll IDs mit autonomem Status-Chatter.
Das DID-Mismatch-Problem
Jetzt der nächste Haken. Die ESPHome-Config war von einem ähnlichen Modell abgeleitet — gleiches Protokoll, gleiche Plattform, aber ein anderer Vitocal-Typ. Nicht alle Datenpunkte (DIDs — Data Identifiers, die Adressen für einzelne Messwerte) existieren auf dem 16er.
Drei DIDs lieferten konstant einen Fehler-Code zurück: conditionsNotCorrect. Das klingt nach einem Timing-Problem, ist aber auf diesem Modell einfach „nicht verbaut” — Warmwasser-Ist-Fühler und zwei Pufferfühler sind auf dem kompakteren Modell physisch nicht bestückt.
Um herauszufinden, was der 16er wirklich hat, haben wir einen Scan gemacht: eine Firmware, die systematisch DID 256 bis 3600 abfragt und alles protokolliert, was eine positive Antwort liefert. 599 DIDs antworteten.
Aus diesem Rohdatenberg und einem Referenz-Dokument mit DID-Namen ließen sich die Fehlenden identifizieren und entfernen, und zwei zusätzliche Fühler fanden, die auf dem 16er bestückt sind, obwohl sie in der Vorlage nicht standen.
Die ersten Live-Daten
Nach einem OTA-Flash mit der bereinigten Config: Der Verdichter läuft, Wärmeleistung ~4 kW, E-Heizstab aus, Warmwasser-Sollwert 48 °C, Pufferfühler oben ~37 °C. Ein schnell gerechnetes COP-Template aus elektrischer Aufnahme und Wärmeleistung — plausibel.
ESPHome meldet das Gerät automatisch an Home Assistant. Knapp 20 Entities, alle lokal, ohne Cloud, ohne Rate-Limiting.
Ich habe ein kleines Dashboard gebaut: Status-Kacheln, Leistungs-Anzeige mit COP, Temperaturen, Warmwasser-Einstellregler (der WW-Sollwert ist schreibbar), Betriebsstatistik und Verlaufsgraphen für die letzten 24 Stunden.
Was offen bleibt
Einige Automationen hatten noch Referenzen auf die Cloud-Integration des Herstellers — für Temperaturen und Zählerstände, die jetzt lokal verfügbar sind. Die sind umgebogen, die lokale Quelle läuft.
Was noch nicht lokal funktioniert: bestimmte Steuerfunktionen wie eine Einmalladung oder der Komfort-Modus über PV-Überschuss. Diese hängen davon ab, dass die WP spezifische CAN-Kommandos bekommt — und die exakten Werte sind aus der Dokumentation allein nicht sicher rekonstruierbar. Sobald die Cloud-Integration kurz wieder online ist, lässt sich das per Mitschneiden herausfinden und dann dauerhaft lokal nachbauen.
Bis dahin: Die WP redet. Lokal. Ohne Umweg über irgendein Rechenzentrum. Das Gehäuse aus V12 sitzt. Und die Wärmepumpe erzählt selbst, was sie gerade macht.
🤵