EMR7370: Unterschied zwischen den Versionen

Aus Hobbyelektronik.org
K
K (Typo in URL korrigiert)
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
[[Datei:EMR7370_aussen.jpg|thumb|Empfänger]]
 
[[Datei:EMR7370_aussen.jpg|thumb|Empfänger]]
Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade.
+
Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade.
  
 
Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch.
 
Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch.
Zeile 30: Zeile 30:
 
</gallery>
 
</gallery>
  
 +
== Initialisierung ==
 
Zur mutmaßlichen Initialisierung werden folgende Daten übertragen:
 
Zur mutmaßlichen Initialisierung werden folgende Daten übertragen:
  
Zeile 81: Zeile 82:
 
Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht.
 
Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht.
  
 
+
==Datenpaket==
 
[[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]]
 
[[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]]
 
Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden.
 
Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden.
Zeile 92: Zeile 93:
  
 
Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen.
 
Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen.
 +
 +
==Anmeldung==
 +
 +
Zur Anmeldung eines Senders am Empfänger muss die Verbindungs-Taste länger gedrückt werden, danach wird immer wieder 0x25 0x2A, die Adresse (2 Byte) sowie (vermutlich) eine Prüfsumme gesendet. Da die Anmeldung zum Betreiben eines eigenen Empfängers nicht erforderlich ist, behandle ich diese nicht weiter.
  
 
=Datenanalyse=
 
=Datenanalyse=
Zeile 100: Zeile 105:
 
|-
 
|-
 
! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11
 
! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11
 +
|-
 +
| 220,0 || 0,00 ||  0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 00 || BC || 40 || 00 || 6F
 +
|-
 +
| 222,0 || 0,05 ||  0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 38 || BC || 40 || 00 || 37
 +
|-
 +
| 221,0 || 0,26 || 58,0 || 25 || 6A || 54 || 72 || 40 || 74 || 01 || 0C || BA || 40 || 00 || F0
 +
|-
 +
| 222,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 07 || BD || 40 || 00 || F1
 
|-
 
|-
 
| 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4
 
| 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4
Zeile 107: Zeile 120:
 
| 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C
 
| 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C
 
|-
 
|-
| 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25
+
| 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25
 
|-
 
|-
| 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42
+
| 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42
 
|-
 
|-
| 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A
+
| 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A
 
|-
 
|-
| 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D
+
| 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D
 
|-
 
|-
| 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D
+
| 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D
 
|-
 
|-
 
| 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4
 
| 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4
Zeile 126: Zeile 139:
 
|-
 
|-
 
| 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4
 
| 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4
|-
 
| 220,5 || 0,02 || 1,0  || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52
 
 
|}
 
|}
  
Zeile 134: Zeile 145:
 
Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen.
 
Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen.
  
Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist.
+
Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren.
 +
 
 +
==Spannung==
 +
 
 +
Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist.
  
 
Mathematisch kann man die Formel
 
Mathematisch kann man die Formel
Zeile 143: Zeile 158:
  
 
in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte.
 
in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte.
 +
 +
==Leistung==
 +
 +
Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss.
 +
 +
Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss.
 +
 +
==Strom==
 +
Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird.
 +
 +
==Adresse==
 +
Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt.
 +
 +
Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung.
 +
 +
==Geräteklasse (?)==
 +
Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete (außer bei der Anmeldung) unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt.
 +
 +
==Energie==
 +
Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Die zugehörigen Werte stehen in Spalte 9 und 10, wobei auch hier wieder ein Offset von 0x4000 bzw. 16384 zu verzeichnen ist. Die Skalierung ist hierbei etwas krumm, geteilt durch 100 ergibt sich die Energie in kWh, somit wird intern in 10Wh-Schritten gezählt.
 +
 +
==Prüfsumme==
 +
Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet.
 +
 +
Mit dem CRC8-Code des [[VBus-Decoder]]s hatte ich auf Anhieb Erfolg.
 +
 +
==Zusammenfassung==
 +
 +
{| class="wikitable"
 +
|-
 +
! Wert !! MSByte !! LSByte !! Offset !! Faktor !! Bemerkung
 +
|-
 +
| Klasse || 0 || 1 || -- || -- || keine anderen Werte bekannt
 +
|-
 +
| Adresse || 2 || 3 || -- || -- || 
 +
|-
 +
| Leistung || 4 || 5 || 0x4000 || 0,5 || W
 +
|-
 +
| Strom || 6 || 7 || 0x0000|| 0,001 || A
 +
|-
 +
| Spannung || 8 || -- || 0x0000 || 0,5 || V
 +
|-
 +
| Energie || 9 || 10 || 0x4000 || 0,01 || kWh
 +
|-
 +
| Prüfsumme || 11 || -- || -- || -- || CRC aller vorangegangenen Bytes
 +
|} 
 +
 +
=Client=
 +
{{Infobox AVR
 +
| Typ = ATmega8
 +
| Takt = 12
 +
| FuseH = D1
 +
| FuseL = F8
 +
}}
 +
Der nächste Schritt ist natürlich einen eigenen Client zu programmieren.
 +
 +
Verwendet habe ich hierzu den mittlerweile doch etwas betagten ATmega8, der jedoch nach wie vor seinen Zweck erfüllt.
 +
 +
Um es einfach zu halten habe ich das SPI-Interface im Bitbanging-Mode geschrieben, wobei auch die benötigten Pausen (vom Original übernommen) womöglich etwas vorsichtig gewählt sind. Ich halte jedoch niemanden ab, das Timing zu optimieren.
 +
 +
Die Software führt zunächst eine Initialisierung der Hardware durch und überprüft dann im Main-Loop, ob ein vollständiges Datenpaket empfangen wurde. Ist dies der Fall, wird das Paket dekodiert und bei Erfolg in an den entsprechenden Speicherplatz geschoben.
 +
 +
Ohne höheren Debug-Level muss man die Adressen der jeweiligen Sender vorher setzen, sonst sieht man nichts.
 +
 +
Standardmäßig werden die Messdaten alle 10 Sekunden ausgegeben, wird 30 Sekunden nichts empfangen, wird der Empfänger neu initialisiert, wobei ich damit noch etwas unzufrieden bin:
 +
 +
Während Flashen des AVRs ist es immer wieder passiert, dass der Empfänger den Interrupt gesetzt hat, dieser aber nicht abgearbeitet wurde. Das hat zur Folge, dass der Empfang auch nach erneutem Initialisieren einfach nicht funktioniert. Da das Funkmodul keinen Reset-Eingang hat, hilft hier entweder eine bessere Behandlung des Interrupts oder die die Versorgung des Empfängers über den Mikrocontroller zu schalten. Letzteres ist zwar nicht elegant, dafür aber effektiv. Eine der beiden Methoden müsste zur Erhöhung der Zuverlässigkeit noch implementiert werden.
 +
 +
Die Pinbelegung des Funkmoduls ist der Datei RFM01.h zu entnehmen. Die Ausgabe der Daten erfolgt am UART mit 57600 Baud 8N1.
 +
 +
=Download=
 +
* [[Datei:EMR7370.zip]] LA-Aufzeichnungen (mit [http://www.saleae.com/downloads Saleae Logic] einsehbar), Excel-Datei mit ausgewerteten Beispieldatensätzen, Beispielcode ATmega8 (AVR-Studio 5)

Aktuelle Version vom 26. Mai 2015, 19:55 Uhr

Empfänger

Vor einer Weile bin ich durch Kundenwerbung beim "Ramschmax" an einen Funk-Energiekosten-Messgerät EMR7370 gekommen. Da das Teil nicht unbedingt durch Qualität überzeugte, lag es eine gute Weile in der Schublade.

Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch.

Schaltungsanalyse

Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher.

Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt.

Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt.

Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war.

Protokollanalyse

Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren.

Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet.

Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird:

Initialisierung

Zur mutmaßlichen Initialisierung werden folgende Daten übertragen:

0x90D9
0xA67C
0xC080
0xC081
(500ms Pause)
0xCE85
0xCE87
0xC4AB
0xC823
0xC6C7
0xB014
0xC205
0xC080
(188ms Pause)
0xC081
(4ms Pause)
0x94D9
0xC209
(5ms Pause)
0x00
0x90D9
0xC080
(52ms Pause)
0xC081

Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger:

0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87


Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!?

Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen.

Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus!

Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg.

Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht.

Datenpaket

Datenempfang (großer Monitor erforderlich)

Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden.

Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht).

Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist.

Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator.

Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen.

Anmeldung

Zur Anmeldung eines Senders am Empfänger muss die Verbindungs-Taste länger gedrückt werden, danach wird immer wieder 0x25 0x2A, die Adresse (2 Byte) sowie (vermutlich) eine Prüfsumme gesendet. Da die Anmeldung zum Betreiben eines eigenen Empfängers nicht erforderlich ist, behandle ich diese nicht weiter.

Datenanalyse

Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte:

U I P 0 1 2 3 4 5 6 7 8 9 10 11
220,0 0,00 0,0 25 6A 54 72 40 00 00 00 BC 40 00 6F
222,0 0,05 0,0 25 6A 54 72 40 00 00 38 BC 40 00 37
221,0 0,26 58,0 25 6A 54 72 40 74 01 0C BA 40 00 F0
222,5 0,26 58,5 25 6A 54 72 40 75 01 07 BD 40 00 F1
221,5 0,26 58,5 25 6A 54 72 40 75 01 06 BB 40 00 F4
221,5 0,17 39,0 25 6A 54 72 40 4E 00 B1 BB 40 00 71
222,5 0,17 39,5 25 6A 54 72 40 4F 00 B2 BD 40 01 6C
222,5 0,06 2,5 25 6A 54 72 40 05 00 43 BD 40 01 25
223,0 0,03 2,5 25 6A 54 72 40 05 00 25 BE 40 01 42
222,0 0,03 2,0 25 6A 54 72 40 04 00 20 BC 40 01 4A
222,5 0,06 1,0 25 6A 54 72 40 02 00 3E BD 40 01 2D
223,5 0,06 1,0 25 6A 54 72 40 02 00 3C BF 40 01 2D
222,5 0,31 29,0 25 6A 54 72 40 3A 01 3E BD 40 01 F4
222,0 0,37 42,0 25 6A 54 72 40 54 01 74 BC 40 01 A5
223,0 0,35 42,5 25 6A 54 72 40 55 01 66 BE 40 02 AF
221,5 0,19 38,0 25 6A 54 72 40 4C 00 BF BB 40 02 63
224,0 0,13 12,5 25 6A 54 72 40 19 00 8B C0 40 03 C4

Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format.

Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen.

Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren.

Spannung

Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist.

Mathematisch kann man die Formel

\( x=a \cdot y + b \)

in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte.

Leistung

Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss.

Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss.

Strom

Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird.

Adresse

Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt.

Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung.

Geräteklasse (?)

Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete (außer bei der Anmeldung) unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt.

Energie

Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Die zugehörigen Werte stehen in Spalte 9 und 10, wobei auch hier wieder ein Offset von 0x4000 bzw. 16384 zu verzeichnen ist. Die Skalierung ist hierbei etwas krumm, geteilt durch 100 ergibt sich die Energie in kWh, somit wird intern in 10Wh-Schritten gezählt.

Prüfsumme

Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet.

Mit dem CRC8-Code des VBus-Decoders hatte ich auf Anhieb Erfolg.

Zusammenfassung

Wert MSByte LSByte Offset Faktor Bemerkung
Klasse 0 1 -- -- keine anderen Werte bekannt
Adresse 2 3 -- --
Leistung 4 5 0x4000 0,5 W
Strom 6 7 0x0000 0,001 A
Spannung 8 -- 0x0000 0,5 V
Energie 9 10 0x4000 0,01 kWh
Prüfsumme 11 -- -- -- CRC aller vorangegangenen Bytes

Client

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

Der nächste Schritt ist natürlich einen eigenen Client zu programmieren.

Verwendet habe ich hierzu den mittlerweile doch etwas betagten ATmega8, der jedoch nach wie vor seinen Zweck erfüllt.

Um es einfach zu halten habe ich das SPI-Interface im Bitbanging-Mode geschrieben, wobei auch die benötigten Pausen (vom Original übernommen) womöglich etwas vorsichtig gewählt sind. Ich halte jedoch niemanden ab, das Timing zu optimieren.

Die Software führt zunächst eine Initialisierung der Hardware durch und überprüft dann im Main-Loop, ob ein vollständiges Datenpaket empfangen wurde. Ist dies der Fall, wird das Paket dekodiert und bei Erfolg in an den entsprechenden Speicherplatz geschoben.

Ohne höheren Debug-Level muss man die Adressen der jeweiligen Sender vorher setzen, sonst sieht man nichts.

Standardmäßig werden die Messdaten alle 10 Sekunden ausgegeben, wird 30 Sekunden nichts empfangen, wird der Empfänger neu initialisiert, wobei ich damit noch etwas unzufrieden bin:

Während Flashen des AVRs ist es immer wieder passiert, dass der Empfänger den Interrupt gesetzt hat, dieser aber nicht abgearbeitet wurde. Das hat zur Folge, dass der Empfang auch nach erneutem Initialisieren einfach nicht funktioniert. Da das Funkmodul keinen Reset-Eingang hat, hilft hier entweder eine bessere Behandlung des Interrupts oder die die Versorgung des Empfängers über den Mikrocontroller zu schalten. Letzteres ist zwar nicht elegant, dafür aber effektiv. Eine der beiden Methoden müsste zur Erhöhung der Zuverlässigkeit noch implementiert werden.

Die Pinbelegung des Funkmoduls ist der Datei RFM01.h zu entnehmen. Die Ausgabe der Daten erfolgt am UART mit 57600 Baud 8N1.

Download

  • Datei:EMR7370.zip LA-Aufzeichnungen (mit Saleae Logic einsehbar), Excel-Datei mit ausgewerteten Beispieldatensätzen, Beispielcode ATmega8 (AVR-Studio 5)