ECL-Bus-Protokoll

Aus Hobbyelektronik.org

Neue Erfahrungen bringen neue Sichtweisen.

Unter dieser Prämisse - und nachdem ich den Artikel des ECL-Bus-Decoders selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen.

Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300.

Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist.

"Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand.

Busteilnehmer

Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert):

  • ECL 300: elektronischer Temperaturregler (ECL 301 ist die 24 V-Version)
  • ECA 60: Raumleitgerät mit Temperaturmessung
  • ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung
  • ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet
  • ECA 86: Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais)

ECL 300

ECL 300

Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen.

Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet.

Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern.

ECA 86

ECA 86

Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern.

Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt.

ECA 60

ECA 60

Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist).

Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert.

Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt.

Einbaumodule

Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen:

  • ECA 71: Modbus-Adapter für die ECL 30x
  • ECA 81: RS-232-Adapter für die ECL 30x
  • ECA 87: RS-232-Datenlogger

In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen "Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."

Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben.

Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts.

Schnittstelle

Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind).

Physischer Layer

Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt.

Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen.

Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle:

Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz:

Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden.

Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm:

Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck).

Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann.

Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben.

Bitübertragung

Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann.

Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität.

Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus:

Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind.

Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder.

Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie normalverteilte Kurven ergeben.

Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen.

Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung:

An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten.

Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen:

Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt:

erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten:

Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen 0x0000 auch zum Beispiel folgendes:

Zeit        Daten
...
20,25630025 0x0000
20,27630175 0x60EF
20,29630150 0x1915
20,31630525 0x0CA8
20,33631175 0x0023
20,35631150 0x0D54
20,37631200 0x0000
20,39631075 0x60EF
20,41631625 0x1952
20,43631700 0x6000
20,45631275 0x0045
20,47631425 0x0D5F
20,49632000 0x0000
...


Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt.

Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden.

Dieses kann die Daten wie folgt ausspucken:

12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8
19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C
20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54
20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F
24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35
25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07
41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF
42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD
42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF
48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C
49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63
49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58
52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34
54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24

Protokoll

Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden.

Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden.

Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die Byte-Reihenfolge der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen.

Header

Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind.

Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger:

Adresse Bezeichnung
0 Broadcast
A ECA 60
E ECA 86
F ECL 300

Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp:

d[0] Typ Sender Empfänger Bezeichnung Häufigkeit
0x04AF 04 A F Innentemperatur (ECA 60) 125/h
0x05AF 05 A F Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) -
0x09AF 09 A F Abfrage Tagesprogramm 63/h
0x11AF 11 A F Zeit setzen -
0x60EF 60 E F Temperaturfühler ECA 86 125/h
0x01F0 01 F 0 Außentemperatur 125/h
0x02F0 02 F 0 Aktuelle Zeit 125/h
0x05FA 05 F A Solltemperatur am ECL 300 setzen -
0x06FA 06 F A Bestätigung Setzen Solltemperatur (Antwort auf 05AF) -
0x09FA 09 F A Tagesprogramm (Antwort auf 06AF) 63/h
0x62FE 62 F E Setzen Relais an ECA 86 125/h

Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden.

Prüfsumme

Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet:

var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ];
var checksum_calc = 0;
var checksum_msg = data[4] & 0xFF;

for(var i = 0; i < 4; i++)
{
    checksum_calc += (data[i] >> 8) & 0xFF;
    checksum_calc += (data[i] >> 0) & 0xFF;
}
checksum_calc &= 0xFF;

console.log("calculated checksum: 0x%s, explected 0x%s", 
    checksum_calc.toString(16), checksum_msg.toString(16)
)

Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück.

Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer.

Payload

Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten

Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert.

Beispiel:

Ecl bus message sample.png

   04       AF        0B       1A        00       00        00       00        0D       D8   
00000100 10101111  00001011 00011010  00000000 00000000  00000000 00000000  00001101 11011000
!!!!!!!! !!!!!!!!  ?!!!!!!! !!!!!!!!  00000000 00000000  00000000 00000000  00001101 !!!!!!!!

In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links.

Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text)

Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar:

  • !: Bedeutung bekannt
  • ?: Bedeutung unbekannt
  • 0: immer low
  • 1: immer high

04AF: Innentemperatur

Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann

   04       AF        0B       1A        00       00        00       00        0D       D8   
00000100 10101111  00001011 00011010  00000000 00000000  00000000 00000000  00001101 11011000
!!!!!!!! !!!!!!!!  ?!!!!!!! !!!!!!!!  00000000 00000000  00000000 00000000  00001101 !!!!!!!!


Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.14:0 Innentemperatur x / 128 0x0B1A 22.203125 °C

Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss.

05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)

  • 0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)
  • 0x05FA: Solltemperatur am ECL 300 setzen

   05       AF        2C       FF        0C       24        82       00        0D       91   
00000101 10101111  00101100 11111111  00001100 00100100  10000010 00000000  00001101 10010001
!!!!!!!! !!!!!!!!  00!!!!!0 ????????  !!!!!!!0 ????????  !0000!!! !!!!!!!0  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.13:9 Soll-Temperatur x 0x16 22 °C
2.14:9 Abweichende Temperatur (Entspannen) (s. u.) 0x06 +6 °C
3.15 Abweichung aktiv s. u. 0x01 aktiv
3.10:8 Betriebsmodus s. u. 2 = Konstante Komforttemperatur
3.7:1 Abweichende Temperatur (Abwesenheit) (s. u.) 0x00 0 °C

Achtung: hier gibt es noch eine kleine Unsicherheit, was 1.7:0 macht und wie es zu 1.13:9 steht.

Abweichende Temperatur

In den Words 2.14:9 und 3.7:1 sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden.

Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt:

if(type == ECL_DIFF_RELAX) 
{
    ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F;
    if(ecl_data.tmp_diff & 0x20) 
    {
        ecl_data.tmp_diff |= 0xC0;
    }
} 
else if(type == ECL_DIFF_AWAY) 
{
    ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F;
    if(ecl_data.tmp_diff & 0x40)
    {
        ecl_data.tmp_diff |= 0x80;
    }
}

Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird.

Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden.

Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern.

Betriebsmodus

Bin Dez Bedeutung
000 0 Manuell
001 1 Zeitgesteuerter Betrieb
010 2 Konstante Komforttemperatur
011 3 Konstante reduzierte Temperatur
100 4 Standby

Die restlichen zustände sind mir nicht bekannt.

06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)

Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden.

09AF: Abfrage Tagesprogramm

Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60.

   09       AF        00       04        00       00        00       00        0D       BC   
00001001 10101111  00000000 00000100  00000000 00000000  00000000 00000000  00001101 10111100
!!!!!!!! !!!!!!!!  00000000 00000!!!  00000000 00000000  00000000 00000000  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.2:0 Wochentag 0=Montag ... 7=Sonntag 0x04 Freitag

Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber:

Bin Dez Bedeutung
000 0 Montag
001 1 Dienstag
010 2 Mittwoch
011 3 Donnerstag
100 4 Freitag
101 5 Samstag
110 6 Sonntag

09FA: Rückmeldung Tagesprogramm

Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF.

   09       FA        FF       3F        81       FF        00       FE        0D       BF   
00001001 11111010  11111111 00111111  10000001 11111111  00000000 11111110  00001101 10111111
!!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.15:3.0 Tagesprogramm als Bitmap s. u. s. u.

Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist.

Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen:

Ecl tagesprogramm.jpg

also:

  • 04:30 - 08:30
  • 11:30 - 23:00

Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben:

         0xFF3F          0x81FF          0x00FE     
LE: 111111110011111110000001111111110000000011111110
BE: 001111111111111111111111100000011111111000000000

So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben.

11AF/02F0: Zeit setzen/aktuelle Zeit

   11       AF        03       20        05       0D        79       79        0D       E7   
00010001 10101111  00000011 00100000  00000101 00001101  01111001 01111001  00001101 11100111
!!!!!!!! !!!!!!!!  0!!!!!!! 0!!!!!!!  00!!!!!! 00!!!!!!  ?!!!!!!! !!!!!!!!  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.14:8 Minuten x 0x03 3
1.6:0 Sekunden x 0x20 32
2.13:8 Tag x 0x05 5
2.5:0 Stunden x 0x0D 13
3.15:12 Wochentag 1=Montag ... 7=Sonntag 0x07 Sonntag
3.11:8 Monat x 0x09 9
3.7:0 Jahr 1900 + x 0x79 2021

In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden.

Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte.

Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage:

Bin Dez Bedeutung
001 1 Montag
010 2 Dienstag
011 3 Mittwoch
100 4 Donnerstag
101 5 Freitag
110 6 Samstag
111 7 Sonntag

60EF: Temperaturfühler ECA 86

Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen.

Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten.

   60       EF        1E       DB        0B       96        00       23        0D       0C   
01100000 11101111  00011110 11011011  00001011 10010110  00000000 00100011  00001101 00001100
!!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  00000000 !!!!!!!!  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.15:0 Temperatur A x / 128 0x1EDB 61,7109375 °C
1.15:0 Temperatur B x / 128 0x0B96 23,171875 °C
2.7:4 Index Temperatur A x 0x02 2
2.3:0 Index Temperatur B x 0x03 3

Für die zweite Gruppe sieht die Nachricht wie folgt aus:

   60       EF        1F       2F        60       00        00       45        0D       42   
01100000 11101111  00011111 00101111  01100000 00000000  00000000 01000101  00001101 01000010

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.15:0 Temperatur A x / 128 0x1F2F 62,3671875 °C
1.15:0 Temperatur B x / 128 0x6000 192 °C
2.7:4 Index Temperatur A x 0x04 4
2.3:0 Index Temperatur B x 0x05 5

Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind.

01F0: Außentemperatur

   01       F0        0A       06        22       FA        00       00        0D       1D   
00000001 11110000  00001010 00000110  00100010 11111010  00000000 00000000  00001101 00011101
!!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  ??!!??!! ????????  00000000 00000000  00001101 !!!!!!!!

Position Bezeichnung Berechnung Wert aus Beispiel Berechnet
1.15:0 Außentemperatur x / 128 0x0A06 20,046875 °C
2.13:12 Betriebsmodus Brauchwasserkreis s. u. 0x02 Komforttemperatur
2.9:8 Betriebsmodus Heizkreis s. u. 0x02 Komforttemperatur

Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt:

Bin Dez Bedeutung
00 0 Reduzierte Temperatur
01 1 Optimierte Aufheizphase
10 2 Komforttemperatur
11 3 Optimierte Absenkphase

Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet.

62FE: Setzen Relais an ECA 86

   62       FE        FF       FF        FF       FF        00       00        0D       5C   
01100010 11111110  11111111 11111111  11111111 11111111  00000000 00000000  00001101 01011100

Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen.

Alarmmodul

Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt.

Downloads

  • Datei:Ecl bus data.zip Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert