ECL-Bus-Decoder

Aus Hobbyelektronik.org

Eine etwas andere Sichtweise und Aufarbeitung der Protokollanalyse kann dem Artikel ECL-Bus-Protokoll entnommen werden. Dieser Artikel wird archiviert, sobald alle Infos übertragen/aktualisiert wurden.

Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz koscher war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken.

Wie im Blog erwähnt bin ich durch einen (un)glücklichen Zufall an ein ECA60 von Danfoss gekommen.

In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben.

Interface

Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt:

Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan:

Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen.

Messungen

Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der VBus er mit den Pegeln 0V/Busspannung arbeitet.

Das Oszilloskop ist hier gleicher Meinung:

Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist.

Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen.

Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen.

Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-)

Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an:

Ecl la1.png

Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen.

Ecl la2.png

Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen:

Bitdauer (T2-T1) 0,415ms
Teilpaketlänge (T3-T1) 7,26ms
Inaktiv-Phase (T4-T3) 12,75ms
Periode (T4-T1) 20,01ms

Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist.

Protokollanalyse

Hardware

Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und Datei:Ecl protokollyse.c) etwas nach:

INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen.

Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist.

Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann.

Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering.

Software

Auf der PC-Seite werkelt zunächst Hterm, das die Daten entgegennimmt.

Der Ausgabe sieht in etwa wie folgt aus:

000000
000000
F00201
2C2001
141301
6F6301
370D01
000000
000000
000000
000000
AF0400
2F0A00
000000
000000
EC0D00
000000
000000

die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt.

Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird.

Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch.

Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201.

Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt.

Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen:

AF0500 FF2800 2A0000 000100 060D00
FA0601 002801 2AFF01 FF0101 510D01
AF0500 FF2A00 2A0000 000100 080D00
FA0601 002A01 2AFF01 FF0101 530D01
AF0500 FF2C00 2A0000 000100 0A0D00
FA0601 002C01 2AFF01 FF0101 550D01
AF0500 FF2E00 2A0000 000100 0C0D00
FA0601 002E01 2AFF01 FF0101 570D01

In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert.

Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt.

Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor.

Nach näherer Analyse der Daten ergab sich folgende Geräteliste:

Busteilnehmer

Adresse Bezeichnung
0 Broadcast
A ECA 60 Raumleitgerät
E ECA 86 Alarm- und Temperaturüberwachungsmodul
F ECL 300 Regler

ECL 300

ECL 300

Das/Der 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.

Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt:

RJ12 Sub-D
4 Rx 3
5 Tx 2
7 GND 5

Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen)

Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts.

Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr.

Adresse Anschluss
0xFA B8
0x32 B5
0x34 B4 ?
0xF8 B3 ?
0xFC B7 ?
0x38 B2
0x3C B1

Produktseite bei Danfoss

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

Produktseite bei Danfoss

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.

Produktseite bei Danfoss

Pakete

Sender/Empfänger Typ Bezeichnung Häufigkeit
AF 04 Innentemperatur (ECA 60) 125/h
AF 05 Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) --
AF 09 Abfrage Tagesprogramm 63/h
AF 11 Zeit setzen --
EF 60 Temperaturfühler ECA 86 125/h
F0 01 Außentemperatur 125/h
F0 02 Aktuelle Zeit 125/h
FA 05 Solltemperatur am ECL 300 setzen --
FA 06 Bestätigung Setzen Solltemperatur (Antwort auf AF05) --
FA 09 Tagesprogramm (Antwort auf AF06) 63/h
FE 62 Setzen Relais an ECA 86 125/h

Die Häufigkeit bezieht sich auf eine Stunde, 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.

In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren.

Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet.

AF04 (Innentemperatur)

100 exemplarische Messwerte der Temperatur am ECA 60

Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist.

AF04  10101011 00001011  00000000 00000000  00000000 00000000
      !!!!!!!! ?!!!!!!!  00000000 00000000  00000000 00000000
          Temperatur

Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle.

Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet.

Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm).

AF05/FA05/FF05 (Solltemperatur, ...)

AF05  11111111 00101010  00101000 00000000 11101100 10000011
      ???????? 00!!!!!0  ???????? !!!!!!!0 !!!!!!!0 ?0000!!!
                 Soltmp.                   Abw.tmp.      Modus

Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen.

Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte.

Solltemperatur

Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1).

Abweichende Temperatur

Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6].

Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden.

Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt:

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

Das Setzen einer 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 wieder Verbinden 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 im ECA60 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.

Betriebsart

Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet.

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

Die restlichen möglichen Stati sind mir nicht bekannt.


AF06/FA06 (Bestätigung Solltemperatur)

Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden.

AF09/FA09 (Tagesprogramm)

Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen.

Um diese Daten zu erhalten, muss es folgendes auf den Bus legen:

AF09  00000010 00000000  00000000 00000000  00000000 00000000
      00000!!! 00000000  00000000 00000000  00000000 00000000
           Tag

Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6.

Der ECL300 antwortet dann wie folgt:

FA09  00001111 11111111  11111111 11111111  11110000 00000000
      !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!!
      ^ 23:30                                         00:00 ^

Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet.

In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr.

AF11/F002 (Zeit setzen/Aktuelle Zeit)

F002 *** TODO ***
     0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!!
      Sekunde  Minute    Stunde     Tag     Jahr   WTagMona

Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags.

Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12).

Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren.

EF60 (Temperatursensoren ECA86)

EF60  10000001 00011110  01101000 00001001 00100011 00000000
EF60  01110101 00011111  00000000 01100000 01000101 00000000
      !!!!!!!! !!!!!!!!  !!!!!!!! !!!!!!!! !!!!!!!! 00000000
       Temperatur Bx/x    Temperatur Bx/x   Index

Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt.

Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden.

Das 7. Byte gibt an, um welche Werte es sich handelt.

F001 (Außentemperatur)

F001  *** TODO ***
      !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ????????
         Temperatur                Modus

In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur.

Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis.

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

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

Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht.

FE62 (Setzen Relais an ECA 86)

Prüfsumme

Wie bereits im Blog bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt).

Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann.

Was fehlt noch?

Störung

Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden.

Aktives Auslesen

Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten?

Firmware

AVR
Typ ATmega8
Takt 12 MHz
Fuses
High 0xCB
Low 0xFD
Engbedded com logo.png Details


Die Firmware für AVRs (oder besser gesagt C-Code) belegt einen Pin- (INT0) und einen Timer-Interrupt (TIMER0), mit denen das Signal vom ECL-Bus gesampelt wird.

Die ISRs hierfür können in jeder beliebigen C-Datei stehen. die aufgerufenen Funktionen werden vom Compiler inline eingefügt. Damit das ohne zusätzlichen Speicherplatz funktioniert, musste ich (da ich es zugegebenermaßen nicht besser weiß), den Code fürs Sampeln in die H-Datei des Decoders einfügen. (Wer eine bessere/richtige Methode kennt, ich freue mich über Feedback!)

In der Main-Schleife des Programms muss zusätzlich ecl_decode() aufgerufen werden, welche das zuletzt empfangene Paket auswertet und in die Variable ecl_data schreibt.

Die Funktion sollte alle 8-12ms aufgerufen werden, damit kein Paket verpasst wird. Hier könnte noch etwas Optimierungsbedarf bestehen. Die Praxis wird zeigen, wie (un)günstig die aktuelle Einlesemethode ist.

Um flexibel zu bleiben, verwendet der Code einige Präprozessoranweisungen, über die die einzulesenden Daten sowie Speicherbelegung beeinflusst werden können. Über die Konfiguration kann auch das Debugging konfiguriert werden.

Die Beschaltung ist - wie oben weiter oben zu lesen - sehr einfach. Der ECL-Bus wird über einen Optokoppler galvanisch getrennt. Der Kollektor des Optos wird über einen Pull-Up nach oben gezogen (der AVR-interne dürfte hierfür reichen, momentan wird ein externer vorausgesetzt) und das Signal an PD2 (INT0) weitergegeben.

In der Standardkonfiguration lässt der Code nur eine an PD6/PD7 gegen Masse angeschlossene Duo-LED (Grün an PD6, Rot an PD7) je nach empfangenem Paket/Status kurz aufleuchten.

Konkrete Daten erhält man, wenn man das rudimentäre Debugging aktiviert und am UART bei 19200 Baud 8N1 lauscht.

Download

Datei:ECLBus.zip Version 0.1, AVR-Studio-Projekt