Mein SmartHome-Projekt EMS-Bus
EMS steht für "Energie-Management-System" und ist eine Bus-Kommunikation für Heizungssysteme. Mein Buderus-Gas-Brennwertgerät Logamax plus verfügt über eine EMSplus-Schnittstelle (zweite Generation EMS-Bus) und kommuniziert darüber mit der Bedieneinheit Logamatic RC300. Ich wollte die Daten, die in der RC300 dargestellt sind, in mein SmartHome-Projekt einbinden.
Der EMS-Bus ist auf vielen Seiten ganz gut beschrieben, manchmal aber auch etwas verwirrend. Vor allem habe ich kein (einfaches) Python-Script gefunden, um die Informationen vom EMS-Bus beispielhaft auslesen zu können. Daher beschreibe ich hier kurz meinen Aufbau mit einem Raspberry Pi.
Der EMS-Bus ist ein serieller Zwei-Leiter-Bus und versorgt die daran angeschlossenen Geräte auch mit Spannung. Die Spannungspegel liegen bei mir zwischen ca. 10,5 (low) und ca. 15,8 VDC (high). Zum Anschluss an einen Raspi benötigt man also einen Pegelwandler. Hierfür findet man viele Anleitungen, die mir teilweise relativ kompliziert erschienen. Ich habe für meinen ersten Prototyp einen sehr einfachen Aufbau nach folgenden Anleitung gewählt: Junkers HT-Bus Heatronic 3 Schnittstelle. Im Beitrag von IngoF von 14.01.2011 ist ein Schaltplan mit Komperator LM393N dargestellt. Ich verwende lediglich den oberen Teil (RX) zum Auslesen der EMS-Botschaften, da ich vom EMS-Bus lediglich lesen möchte, und (noch) nicht darauf schreiben (TX).
Die vier Dioden D1 bis D4 entsprechen einer Brückengleichrichterschaltung. Dieser Gleichrichter sorgt dafür, dass der EMS-Pegel immer positiv ist. Es ist damit also egal, wie der EMS-Bus an den Pegelwandler angeschlossen wird.
Die beiden Widerstände R1 und R2 ziehen das (positiv) gleichgerichtete EMS-Signal auf einen Pegel zwischen ca. 2,1 (low) und 3,3 V (high) nach unten. Dieses Signal geht dann auf positiven Eingang (IN+, Pin 3 beim LM393) des Komperators. Die beiden Widerstände R3 und R4 legen die Referenzspannung für den Komperator auf ca. 2,3 V und geht an den nagativen Eingang (IN- oder auch Referenzspannung Vref, Pin 2 beim LM393).
Der Ausgang des Komperators (OUT1 oder Pin 1 beim LM393) wird auf LOW (Masse) gezogen, wenn IN+ < IN-. Wenn IN+ > IN-, dann ist der Ausgang nicht beschaltet, und wird durch den Pull-Up-Widerstand R5 auf +3.3VDC gezogen. Mehr dazu im Datenblatt des LM393. Wenn IN+ und IN- vertauscht sind, ist das Ausgangssignal zum EMS-Eingangssignal invertiert, und das funktioniert dann nicht!
Dieser Pegelwandler wandelt so das Signal vom EMS-Bus (im folgenden Oszi-Screenshot Kanal 1, oben, orange) in ein sauberes 3,3-Volt-Pegelsignal um (im Oszi-Screenshot Kanal 2, unten, blau). Wenn man direkt auf den RX-Eingang des Raspberry Pi geht ist es wichtig, dass HIGH und LOW des EMS-Pegels auf HIGH und LOW nach dem Komperator gewandelt werden. Daher Referenzspannung unbedingt an IN- und nicht auf IN+! Die beiden EMS-Bus-Signalleitungen werden parallel zu den anderen EMS-Geräten (in meinem Fall lediglich Logamatic RC300) direkt am Brennwertgerät angeschlossen.
Mit diesem auf 3,3-Volt-Pegel gewandelten Signal gehe ich dann direkt auf den RXD-Pin (GPIO 15, PIN 10) des Raspi. Mein erster Prototyp an einem Raspberry Pi B+ sah dann so aus:
Version 2 auf einer kleinen Platine sah dann so aus und war an einen Raspberry Pi A+ (mit WLAN) angeschlossen:
Diese Platine werkelte auf einem Raspberry Pi Zero W einige Jahre erfolgreich vor sich hin. Vorteil des Raspi Zero W: Klein, geringer Stromverbrauch, WLAN integriert. Achtung: In diesem Foto fehlt noch die 3,3VDC-Verbindung zum Pullup-Widerstand (vor der dreipoligen Klemme)!
Im November 2019 hab ich die Platine mit einem LM393P neu aufgebaut. Der EMS-Pegelwandler sah dann so aus:
Die vier Leitungen rechts gehen zum Raspi Zero W. Rot auf +5VDC, orange auf +3.3VDC, violett auf RXD-Pin, und schwarz auf Masse. Die beiden gelben Leitungen links sind der EMS-Bus.
Nach kurzer Einarbeitungszeit in das geniale Programm TARGET 3001! hab ich damit den Schaltplan nachgezeichnet und auch gleich ein Platinenlayout entworfen. Hier das Ergebnis:
Und so sieht die Platine nun in Echt aus, und funktioniert sogar:
Auf Anfrage stelle ich auch gerne die Target-Datei und/oder (X-)Gerber-Dateien zur Verfügung.
Die Version 5 meines EMS-Pegelwandlers sieht mit fertig bestückter Platine aktuell so aus:
Die vier Leitungen rechts gehen zum Raspi Zero W. Rot auf +5VDC, orange auf +3.3VDC, gelb auf RXD-Pin, und schwarz auf Masse. Die beiden Leitungen links sind der EMS-Bus.
Mit diesem simplen Aufbau des EMS-Bus-Pegelwandlers kann nun der EMS-Bus ausgelesen werden. Das EMS-Telegramm ist auf dieser Seite gut beschrieben: EMS-Telegramm
Basierend auf dieser EMS-Telegramm-Beschreibung habe ich den Python-Code readEMS.py zum Auslesen des EMS-Bus erstellt:
Damit erhält man dann zum Beispiel folgende Ausgabe (eine Zahl ist ein hex-Byte OHNE 0x, weil das aus meiner Sicht besser lesbar ist):
Das Python-Script wertet (die mir bekannten) Botschaften (Telegramme) aus. Die (mir bekannten) Parameter innerhalb der bekannten Botschaften werden unterhalb der Botschaft dargestellt
(wenn longoutput = True
). Zu jeder Botschaft werden im Verzeichnis /var/www/html/
XML-Dateien erstellt, die dann von einem beliebigen Rechner in Netzwerk ausgewertet
werden können. Aktuell sind das folgende Dateien:
UBA steht angeblich für Universal-Brennerautomat, bei mir das Buderus-Gas-Brennwertgerät Logamax plus.
Eine wichtige Ergänzung, die ich nachträglich hinzugefügt hatte, ist die Überprüfung des CRC-Codes. Jedes Telegramm endet mit einen 0x00-Byte, davor steht der CRC-Code. Den Code hat ein aufmerksamer Leser dieser Seite von C nach Python übersetzt, und zwar nach dieser Quelle. Die einzelnen XML-Dateien werden erst nach bestandener CRC-Überprüfung erstellt. Auf diese Weise werden fehlerhafte Übertragungen ausgefiltert. Ein Probelauf über Nacht ergab bei mir knapp 3% fehlerhafte Botschaften, die in den Diagrammen zu unschönen Ausreißern geführt hatten. Das ist seit der Überprüfung der EMS-Botschaften mit CRC-Code nun beseitigt.
Die EMS-Botschaft UBAMonitorFast kommt alle 10 sec, beginnt mit dem Header 0x08 00 18 00
und ist damit ein Telegramm vom UBA (Quelle 0x08) an den EMS-Gateway (Ziel 0x00).
Dieses Telegram liefert zum Beispiel folgende Informationen in UBAMonitorFast.xml:
<EMSRaspi>
<UBAMonitorFast>
<data name="timestamp" value="2019-03-12 20:41:36" valueunit="YYYY-MM-DD hh:mm:ss"/>
<data name="T_feed_set" value="85" valueunit="degC"/>
<data name="T_feed_act" value="49.0" valueunit="degC"/>
<data name="P_heater_max" value="108" valueunit="%"/>
<data name="P_heater_act" value="108" valueunit="%"/>
<data info="Gasarmatur EIN/AUS" name="Valve_gas" value="1" valueunit="on/off"/>
<data info="Geblaese EIN/AUS" name="Blower" value="1" valueunit="on/off"/>
<data info="Zuendung EIN/AUS" name="Ignition" value="0" valueunit="on/off"/>
<data info="Kesselkreispumpe EIN/AUS" name="Pump_heater" value="1" valueunit="on/off"/>
<data info="3-Wege-Ventil auf Warmwasser" name="Valve_WW" value="1" valueunit="on/off"/>
<data info="Zirkulation EIN/AUS" name="Circulation" value="0" valueunit="on/off"/>
<data info="Flammenstrom" name="I_flame" value="27.2" valueunit="10-6 Amp"/>
<data info="Systemdruck" name="p_system" value="25.5" valueunit="mbar"/>
<data info="Betriebs-Code" name="ServiceCode" value="=H" valueunit=""/>
<data info="Stoerungs-Code" name="Errorcode" value="201" valueunit=""/>
<data name="T_intake_air" value="20.0" valueunit="degC"/>
</UBAMonitorFast>
</EMSRaspi>
Die EMS-Botschaft UBAMonitorSlow kommt alle 60 sec, beginnt mit dem Header 0x08 00 19 00
und liefert zum Beispiel folgende Informationen in UBAMonitorSlow.xml:
<EMSRaspi>
<UBAMonitorSlow>
<data name="timestamp" value="2019-03-12 20:31:56" valueunit="YYYY-MM-DD hh:mm:ss"/>
<data name="T_amb" value="5.9" valueunit="degC"/>
<data name="Pump_modulation" value="41" valueunit="%"/>
<data info="Brennerstarts" name="Heater_Starts" value="33774" valueunit="counts"/>
<data info="Betriebstunden" name="OpHrsTotal" value="976.8" valueunit="hours"/>
<data name="OpHrs2" value="0.0" valueunit="hours"/>
<data name="OpHrs_heat" value="355.7" valueunit="hours"/>
<data name="MoreOpHrs" value="464.2" valueunit="hours"/>
</UBAMonitorSlow>
</EMSRaspi>
Die EMS-Botschaft UBAMonitorWWMessage kommt alle 10 sec, beginnt mit dem Header 0x08 00 34 00
und liefert zum Beispiel folgende Informationen in UBAMonitorWWMessage.xml:
<EMSRaspi>
<UBAMonitorWWMessage>
<data name="timestamp" value="2019-03-12 20:48:33" valueunit="YYYY-MM-DD hh:mm:ss"/>
<data name="T_WW_set" value="60" valueunit="degC"/>
<data name="T_WW_act" value="27.4" valueunit="degC"/>
<data info="Warmwasserbereitungszeit" name="WWtime" value="1713.5" valueunit="hours"/>
<data info="Warmwasserbereitungen" name="WWcounter" value="5925" valueunit=""/>
<data info="Tagbetrieb" name="DayOp" value="1" valueunit="0/1"/>
<data info="Einmalladung" name="OneTimeLoad" value="0" valueunit="0/1"/>
<data info="Thermische Desinfektion" name="Desinfect" value="0" valueunit="0/1"/>
<data info="Warmwasserbereitung" name="WWProduction" value="1" valueunit="0/1"/>
<data info="Warmwassernachladung" name="WWReload" value="0" valueunit="0/1"/>
<data info="Warmwasser-Temperatur OK" name="WWTempOK" value="0" valueunit="0/1"/>
<data info="Fuehler 1 defekt" name="Sensor1defect" value="0" valueunit="0/1"/>
<data info="Fuehler 2 defekt" name="Sensor2defect" value="0" valueunit="0/1"/>
<data info="Stoerung WW" name="FailureWW" value="0" valueunit="0/1"/>
<data info="Stoerung Desinfektion" name="FailureDesinfect" value="0" valueunit="0/1"/>
<data info="Zirkulation Tagbetrieb" name="WWCircDayOp" value="0" valueunit="0/1"/>
<data info="Zirkulation manuell gestartet" name="WWCircManStart" value="0" valueunit="0/1"/>
<data info="Zirkulation laeuft" name="WWCircOn" value="0" valueunit="0/1"/>
<data info="Ladevorgang Warmwasser laeuft" name="WWLoadOn" value="0" valueunit="0/1"/>
</UBAMonitorWWMessage>
</EMSRaspi>
Die EMS-Botschaft RCTimeMessage kommt alle 60 sec, beginnt mit dem Header 0x10 00 06 00
und ist damit ein Telegramm von der Bedieneinheit RC300 (Quelle 0x10) an den EMS-Gateway (Ziel 0x00).
Dieses Telegram liefert zum Beispiel folgende Informationen in RCTimeMessage.xml:
<EMSRaspi>
<RCTimeMessage>
<data name="timestamp" value="2019-03-12 20:52:18" valueunit="YYYY-MM-DD hh:mm:ss"/>
<data name="SystemTime" value="2019-03-12 20:49:59" valueunit="YYYY-MM-DD hh:mm:ss"/>
<data name="DayOfWeek" value="1" valueunit="0=Monday...6=Sunday"/>
</RCTimeMessage>
</EMSRaspi>
Die EMS-Botschaft UBASollwerte kommt alle 60 sec, beginnt mit dem Header 0x10 08 1a 00
und ist damit ein Telegramm vom RC300 (Quelle 0x10) an den UBA (Ziel 0x08).
Byte 5 ist die Kessel-Solltemperatur, Byte 6 die Leistungsanforderung HK, und Byte 7 die Leistungsanforderung WW. Mein Python-Script erzeugt hierfür keine XML-Datei.
Die EMS-Botschaft UBAWartungsmeldung kommt alle 60 sec, beginnt mit dem Header 0x08 00 1c 00
und ist damit ein Telegramm vom UBA (Quelle 0x08) an den EMS-Gateway (Ziel 0x00).
Welche Informationen da enthalten sind ist mir nicht bekannt. Das vollständige Telegramm lautet bei mir immer so:
08 00 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4b 00
.
Auch hierfür erstellt mein Python-Script keine XML-Datei.
Dieser Python-Code ist ein erster Schritt und wird sicher noch erweitert werden. Einige Parameter sind noch nicht OK, zum Beispiel die Ansauglufttemperatur. Die meisten Parameter sind aber stimmig und werden auch auch auf der Bedieneinheit Logamatic RC300 so dargestellt. Via erstellter XML-Dateien frage ich die Daten von einem anderen Raspberry Pi ab und speichere alles in einer MySQL-Datenbank.
Auf meinem EMS-Bus kommen viele Botschaften, die ich (noch) nicht interpretieren kann. Am häufigsten kommmt die Hex-Zeichenfolge 0x89 00 09 00
, zweit-häufigste Hex-Zeichenfolge ist 0x90 00 10 00
. Laut EMS-Wiki ist das wohl Polling vom UBA und die Antwort darauf, bei mir vermutlich vom RC300. Code-Mitschnitte anderer EMS-Botschaften in diversen Foren zeigen dieselben Zeichenfolgen, werden aber nicht näher erläutert. Irgendeinen Sinn scheint das also zu haben.
Der komplette Zahlensalat wird auf Wunsch von dem Python-Script in der Datei out.dat
abgelegt (output = True
). Bekannte Botschaften werden mit einem Zeitstempel versehen und als bekannte Botschaft rausgeschrieben. Alle unbekannte Zeichenfolgen werden einfach rausgeschrieben. Um die Darstellung etwas zu vereinfachen, werden die häufigen Polling-Zeichenfolgen 0x89 00 09 00
als Punkt und 0x90 00 10 00
als Komma geschrieben. Mit dieser Datei kann man versuchen, die unbekannten Botschaften auf dem Bus zu entziffern.
Unregelmäßig dazwischen kommen Zeichenfolgen mit zwei Byte, wobei das zweite Byte immer 0x00
ist. Das erste Byte scheint ein Zähler zu sein, der bei 0x8A
(dezimal 138) startet und (häufig, aber nicht immer) bis 0xEF
(dezimal 239) hochzählt, um dann wieder bei 0x8A
neu zu starten. Häufig werden einzelne Werte dazwischen übersprungen. Auch diesen Sinn habe ich noch nicht verstanden.
Unbekannte Botschaften kann man mit der Datei out.dat
versuchen zu entziffern. Mit skipknown = True
werden die bekannten Botschaften weggelassen,
also nur die unbekannten Botschaften und alles andere auf dem EMS-Bus. Wenn der CRC-Code der unbekannten Botschaften ok ist, ergibt diese Botschaft vermutlich einen Sinn (nur welchen?).
Auf meinem EMS-Bus kommen die folgenden mir unbekannten Boschaften mit gültigen CRC-Code:
08 00 2a 00 00 00 00 00 00 00 00 00 cf 00 00 80 00 00 80 00 80 00 80 00 00 93 00 - CRC ok
08 00 07 00 03 01 00 00 00 00 00 00 00 00 00 00 00 da 00 - CRC ok
10 08 35 00 51 01 a0 00 - CRC ok
Allzuviel sinnvolle Informationeen können diese Botschaften nicht enthalten, da viele Nullen vorhanden sind.
mikrocontroller.net Faktensammlung Buderus EMS
Understanding the EMS Bus of Buderus / Nefit boilers
Online-Monitor für Regler der Buderus Logamatic 4000 Serie
Nefit-Buderus-EMS-bus-Arduino-Domoticz
EMS-ESP mit Code für ESP8266