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 (low) und ca. 15 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 zum Auslesen der EMS-Botschaften:

Schaltplan EMS-Bus

Als Komperator verwende ich IC LM339N. Außerdem nutze ich im Moment nur das RX-Signal, da ich vom EMS-Bus lediglich lesen möchte, und (noch) nicht darauf schreiben (TX). Ansonsten ist der Aufbau identisch. Diese Schaltung wandelt den Pegel vom EMS-Bus (im folgenden Oszi-Screenshot Kanal 1, oben, orange) in ein sauberes 5-Volt-Pegelsignal um (Kanal 2, unten, blau). Dazu habe ich die beiden EMS-Bus-Signalleitungen einfach 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 5-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


Der zweite Prototyp auf einer kleinen Platine sieht im Moment so aus und ist an einen Raspberry Pi A+ (mit WLAN) angeschlossen:

zweiter Prototyp EMS-Bus mit Pegelwandler am Raspberry Pi


Als aktuell letzter (und dritter) Prototyp werkelt ein Raspberry Pi Zero W vor sich hin. Vorteil: Klein, geringer Stromverbrauch, WLAN integriert:

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


Mit diesem simplen Aufbau 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-Bo tschaften 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 mit 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.