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).


Pegelwandler für EMS-Bus

Mein Schaltplan für einen EMS-Bus-Pegelwandler mit LM393P sieht aktuell so aus:

Schaltplan EMS-Bus Pegelwandler


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.

Oszi-Darstellung EMS-Bussignal


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:

erster Prototyp EMS-Bus mit Pegelwandler am Raspberry Pi


Version 2 auf einer kleinen Platine sah dann so aus und war an einen Raspberry Pi A+ (mit WLAN) angeschlossen:

zweiter Prototyp EMS-Bus mit Pegelwandler am Raspberry Pi


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)!

dritter Prototyp EMS-Bus mit Pegelwandler am Raspberry Pi Zero W


Im November 2019 hab ich die Platine mit einem LM393P neu aufgebaut. Der EMS-Pegelwandler sah dann so aus:

EMS-Bus-Pegelwandler mit LM393P

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:

Platine EMS-Bus Pegelwandler

3D-Platine EMS-Bus Pegelwandler


Und so sieht die Platine nun in Echt aus, und funktioniert sogar:

Platine EMS-Bus Pegelwandler

Ich habe übrigens noch vier (unbestückte) Platinen hier, falls jemand eine haben möchte, bitte kurz per Email melden!


Die Version 5 meines EMS-Pegelwandlers sieht mit fertig bestückter Platine aktuell so aus:

EMS-Bus-Pegelwandler mit LM393P Version 5

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.


Python-Code

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):

Ausgabe Python-Code readEMS.py


EMS-Botschaften (Telegramme)

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:

  • UBAMonitorFast.xml
  • UBAMonitorSlow.xml
  • UBAMonitorWWMessage.xml
  • RCTimeMessage.xml

UBA steht angeblich für Universal-Brennerautomat, bei mir das Buderus-Gas-Brennwertgerät Logamax plus.


Prüfsumme (CRC-Code)

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.


UBAMonitorFast

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="Stoerungs-Code" name="ServiceCode" value="=H" valueunit=""/>
  <data info="Betriebs-Code" name="Errorcode" value="201" valueunit=""/>
  <data name="T_intake_air" value="20.0" valueunit="degC"/>
 </UBAMonitorFast>
</EMSRaspi>


UBAMonitorSlow

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>


UBAMonitorWWMessage

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>


RCTimeMessage

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>


UBASollwerte

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.


UBAWartungsmeldung

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.


Ausblick

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
    Alle 10 sec vom UBA an alle, bei mir immer konstant!
  • 08 00 07 00 03 01 00 00 00 00 00 00 00 00 00 00 00 da 00 - CRC ok
    Alle 60 sec vom UBA an alle, bei mir mmer konstant!
  • 10 08 35 00 51 01 a0 00 - CRC ok
    Alle 120 sec vom RC300 an den UBA, und bei mir immer konstant!

Allzuviel sinnvolle Informationeen können diese Botschaften nicht enthalten, da viele Nullen vorhanden sind.


weitere Links zum Thema

EMS-Telegramm

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