ECL-Bus-Decoder: Unterschied zwischen den Versionen

Aus Hobbyelektronik.org
(ein paar Infos zum Phy)
Zeile 2: Zeile 2:
  
 
Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen.
 
Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen.
 +
 +
= Interface =
  
 
Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt:
 
Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt:
Zeile 16: Zeile 18:
 
</gallery>
 
</gallery>
  
Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird.
+
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.  
 
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 mir aufgefallen ist, dass da zur Spannungsglättung noch ein Elko an der Schaltung hängt. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals.
+
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 27Vss 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.
 
Über T3 kann der Bus (der übrigens mit knapp 27Vss 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.
  
In der Bedienungsanleitung der Anlage 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 brauchbaren Ergebnisse - da der ECA60 an dem Bus so wunderbar funktioniert, wird kurzerhand das Oszilloskop angeschlossen:
+
= Messungen =
 +
 
 +
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 brauchbaren Ergebnisse - da der ECA60 an dem Bus so wunderbar funktioniert, wird kurzerhand das Oszilloskop angeschlossen:
  
 
<gallery>
 
<gallery>
Zeile 30: Zeile 35:
 
Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist.  
 
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. In dessen Low-Phasen werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Also können in dieser Zeit 17 Bit übertragen werden, wobei das erste immer 0 ist.
+
Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. In dessen Low-Phasen 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 der Logic Analyzer daran angeschlossen.
+
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 durchs halbe Haus habe ich selbige durch Leerrohre gelegt. Aus Toleranz wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-)
+
Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus Toleranz wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-)
  
 
Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an:
 
Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an:
 
  
 
[[Datei:Ecl la1.png|800px]]
 
[[Datei:Ecl la1.png|800px]]
Zeile 57: Zeile 61:
 
| Periode (T4-T1) || 20,01ms
 
| 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, [[Datei:Ecl protokollyse.c|half]] ein AVR (Atmega8 mit 12MHz) 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 halbem Bit Wartezeit.
 +
 +
Im Timer0-Interrupt wird nun insgesamt 18 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 18. 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 ganz grob 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.
 +
 +
Auf der PC-Seite werkelt [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt.
 +
 +
Der Ausgabe sieht in etwa wie folgt aus:
 +
 +
<pre>
 +
000000
 +
000000
 +
E00502
 +
584002
 +
282602
 +
DEC602
 +
6E1A02
 +
000000
 +
000000
 +
000000
 +
000000
 +
5E0900
 +
5E1400
 +
000000
 +
000000
 +
D81B00
 +
000000
 +
000000
 +
</pre>
 +
 +
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 sogar periodisch!
 +
 +
Beim weiteren Durchsuchen finden sich folgende Paketköpfe/Adressen: E00502, FCC502, DEC100, 5E0B00, F40D02, E00302, 5E0900, 5E1300, F41302 und 5E2300.
 +
 +
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:
 +
 +
<pre>
 +
5E0B00 FE5100 540000 000200 0C1A00
 +
F40D02 005002 54FE03 FE0302 A21A02
 +
5E0B00 FE5500 540000 000200 101A00
 +
F40D02 005402 54FE03 FE0302 A61A02
 +
5E0900 8A1500 000000 000000 041B00
 +
5E1300 020000 000000 000000 721B00
 +
F41302 1EFE03 FE0302 FC0102 1E1A02
 +
FCC502 FEFF03 FEFF03 000002 B81A02
 +
5E0B00 FE5900 540000 000200 141A00
 +
F40D02 005802 54FE03 FE0302 AA1A02
 +
DEC100 BE2400 EC1200 460000 C41A00
 +
DEC100 DE3400 00C000 8A0000 FA1A00
 +
E00302 3E0802 F44502 000002 601A02
 +
E00502 304A02 262C02 DE4602 D41B02
 +
5E0B00 FE5D00 540000 000200 181A00
 +
F40D02 005C02 54FE03 FE0302 AE1A02
 +
</pre>
 +
 +
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 5E0B00 und F40D02. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert.
 +
 +
Dort stehen für 5E0B00 die Werte 51, 55, 59 und 5D. In Dezimalschreibweise 81, 85, 89 und 93. Schiebt man diese Werte um 2 Byte nach rechts (ganzzahlig durch 4 dividieren), erhält man die eingestellten Temperaturen.
 +
 +
F40D02 scheint die Rückmeldung vom Regler zu sein, der die gesetzte Temperatur bestätigt.
 +
 +
Die Analyse und Auswertung findet mit mehreren PHP-Scripts (dreckig aber schnell) statt.

Version vom 22. März 2011, 21:50 Uhr

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.

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 27Vss 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

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 brauchbaren Ergebnisse - da der ECA60 an dem Bus so wunderbar funktioniert, wird kurzerhand das Oszilloskop angeschlossen:

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. In dessen Low-Phasen 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 Toleranz 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, Datei:Ecl protokollyse.c ein AVR (Atmega8 mit 12MHz) 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 halbem Bit Wartezeit.

Im Timer0-Interrupt wird nun insgesamt 18 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 18. 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 ganz grob 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.

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

Der Ausgabe sieht in etwa wie folgt aus:

000000
000000
E00502
584002
282602
DEC602
6E1A02
000000
000000
000000
000000
5E0900
5E1400
000000
000000
D81B00
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 sogar periodisch!

Beim weiteren Durchsuchen finden sich folgende Paketköpfe/Adressen: E00502, FCC502, DEC100, 5E0B00, F40D02, E00302, 5E0900, 5E1300, F41302 und 5E2300.

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:

5E0B00 FE5100 540000 000200 0C1A00
F40D02 005002 54FE03 FE0302 A21A02
5E0B00 FE5500 540000 000200 101A00
F40D02 005402 54FE03 FE0302 A61A02
5E0900 8A1500 000000 000000 041B00
5E1300 020000 000000 000000 721B00
F41302 1EFE03 FE0302 FC0102 1E1A02
FCC502 FEFF03 FEFF03 000002 B81A02
5E0B00 FE5900 540000 000200 141A00
F40D02 005802 54FE03 FE0302 AA1A02
DEC100 BE2400 EC1200 460000 C41A00
DEC100 DE3400 00C000 8A0000 FA1A00
E00302 3E0802 F44502 000002 601A02
E00502 304A02 262C02 DE4602 D41B02
5E0B00 FE5D00 540000 000200 181A00
F40D02 005C02 54FE03 FE0302 AE1A02

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 5E0B00 und F40D02. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert.

Dort stehen für 5E0B00 die Werte 51, 55, 59 und 5D. In Dezimalschreibweise 81, 85, 89 und 93. Schiebt man diese Werte um 2 Byte nach rechts (ganzzahlig durch 4 dividieren), erhält man die eingestellten Temperaturen.

F40D02 scheint die Rückmeldung vom Regler zu sein, der die gesetzte Temperatur bestätigt.

Die Analyse und Auswertung findet mit mehreren PHP-Scripts (dreckig aber schnell) statt.