Prozeda-Decoder: Unterschied zwischen den Versionen
Chris (Diskussion | Beiträge) (→Anmerkungen: Dank erweitert) |
Chris (Diskussion | Beiträge) K (→Displayanzeige: eher dämliche Überschrift korrigiert) |
||
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 163: | Zeile 163: | ||
Leider sind mir über die Inhalte keine näheren Informationen bekannt. | Leider sind mir über die Inhalte keine näheren Informationen bekannt. | ||
− | === | + | ===Display=== |
− | Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt | + | Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt für ein zusätzliches Display. |
− | Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten | + | Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten dementsprechend. |
<!-- use colors they said, it will look great they said --> | <!-- use colors they said, it will look great they said --> | ||
Zeile 183: | Zeile 183: | ||
* <span class="hb2">Zeile 2 auf dem Display</span> | * <span class="hb2">Zeile 2 auf dem Display</span> | ||
* <span class="hb3">Zeile 3 auf dem Display</span> | * <span class="hb3">Zeile 3 auf dem Display</span> | ||
− | * <span class="hb4">Weitere Daten</span> | + | * <span class="hb4">Weitere Daten</span> (siehe unten) |
− | Die weiteren Daten haben sich mir leider nicht erschlossen, | + | Das letzte Zeichen: siehe Prüfsumme |
+ | |||
+ | ====Weitere Daten==== | ||
+ | Die weiteren Daten haben sich mir leider nicht vollständig erschlossen, einige Bits und Bytes lassen sich folgenden Displayelementen zuordnen: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Offset || Bit 7 (0x80) || Bit 6 (0x40) || Bit 5 (0x20) || Bit 4 (0x10) || Bit 3 (0x08) || Bit 2 (0x04) || Bit 1 (0x02) || Bit 0 (0x01) | ||
+ | |- | ||
+ | | 0x26 || || || || || || || || Symbol Info | ||
+ | |- | ||
+ | | 0x27 || || || || || || || || ? | ||
+ | |- | ||
+ | | 0x28 || || || || Pumpe oben || Pumpe mitte || Pumpe unten || || | ||
+ | |- | ||
+ | | 0x29 || || || || || || || || | ||
+ | |- | ||
+ | | 0x2A || || || || || || || || Symbol Einstellungen | ||
+ | |- | ||
+ | | 0x2B || || || || || || || || Relais Rahmen | ||
+ | |- | ||
+ | | 0x2C || || || || Relais 5 || Relais 6 || Relais 1 || Relais 2 || | ||
+ | |- | ||
+ | | 0x2D || || || || || Relais 3 || Relais 4 || Relais 7 || | ||
+ | |- | ||
+ | | 0x2E || || || || Symbol Hand || || || || | ||
+ | |- | ||
+ | | 0x2F || || || || || || || || Symbol Fehler | ||
+ | |- | ||
+ | | 0x30 || || || || || || || || | ||
+ | |- | ||
+ | | 0x31 || || || || || || || || | ||
+ | |- | ||
+ | | 0x32 || || || || Symbol Sonderfkt. || || || || | ||
+ | |- | ||
+ | | 0x33 || || || || Symbol "OK?" || || || || | ||
+ | |- | ||
+ | | 0x34 || || || || ? || || || || | ||
+ | |} | ||
+ | |||
+ | Anmerkungen: | ||
+ | * Bytes 0x35 bis 0x3E sind nicht in der Tabelle aufgeführt, da bei ihnen keine Veränderungen beobachtet wurden, diese stehen immer auf 0x00 | ||
+ | * Die mit Fragezeichen markierten Bits veränderten sich in den Traces, konnten aber keinem Symbol Element auf dem Display zugeordnet werden | ||
+ | * Relais 8 ist unsicher, da es bei Tests nicht angesteuert werden konnte | ||
+ | |||
+ | ====Fehlerhafte Übertragung==== | ||
+ | Die zweite und dritte Displayzeile scheint es bei manchen Reglern (z. B. den Ratiofresh200) einen Bug zu geben. Nach genauerer Untersuchung (abermals vielen Dank an Frank für die Unterstützung!) scheint der verwendete Speicher falsch gemappt zu sein, zumindest erscheinen Texte, die für die zweite Zeile bestimmt sind teilweise im Bereich der Dritten. | ||
+ | |||
+ | Dies ist bei der Anzeige der primären Vorlauftemperatur gut zu sehen: | ||
+ | |||
+ | <gallery> | ||
+ | prozeda_rf200_prim_vorlauf_56.jpg | Messwert 56,9 °C | ||
+ | prozeda_rf200_prim_vorlauf_57.jpg | Messwert 57,0 °C | ||
+ | </gallery> | ||
− | + | <code> | |
+ | Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | ||
+ | <br /> | ||
+ | 00000000 <span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span> <span class="hb1">Prim„r Vorlauf</span><span class="hb2"> </span> | ||
+ | <br /> | ||
+ | 00000010 <span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span> <span class="hb2"> </span><span class="hb3"> 21 .-T </span> | ||
+ | <br /> | ||
+ | 00000020 <span class="hb3">35 37 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span> <span class="hb3">57 74 </span><span class="hb4">..........</span> | ||
+ | <br /> | ||
+ | 00000030 <span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 68 <span class="hb4">...............</span>h | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | ||
+ | <br /> | ||
+ | 00000000 <span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span> <span class="hb1">Prim„r Vorlauf</span><span class="hb2"> </span> | ||
+ | <br /> | ||
+ | 00000010 <span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span> <span class="hb2"> </span><span class="hb3"> 21 .-T </span> | ||
+ | <br /> | ||
+ | 00000020 <span class="hb3">35 36 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span> <span class="hb3">56 74 </span><span class="hb4">..........</span> | ||
+ | <br /> | ||
+ | 00000030 <span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 67 <span class="hb4">...............</span>g | ||
+ | </code> | ||
+ | |||
+ | Im zweiten Drittel der <span class="hb3">dritten Zeile</span> (ab Offset 0x1F) sieht man, dass die Messwerte aus der zweiten Zeile "hineingedrückt" wurden. | ||
+ | |||
+ | Bei einem anderen Regler (kann leider nicht mehr sagen, welcher es war) werden die Daten für die beiden Zeilen korrekt übertragen. Eine Display-Nachricht sieht dann beispielsweise wie folgt aus: | ||
+ | |||
+ | <code> | ||
+ | 00000000 <span class="hb1">20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20</span> <span class="hb2">20 20</span> <span class="hb1"> Kollektor </span><span class="hb2"> </span> | ||
+ | <br /> | ||
+ | 00000010 <span class="hb2">35 30 2E 35 01 43 20 20</span> <span class="hb3">20 34 36 20 05 2D 01 43</span> <span class="hb2">50.5.C </span><span class="hb3"> 46 .-.C</span> | ||
+ | <br /> | ||
+ | 00000020 <span class="hb3">2D 06 20 35 30 20</span> <span class="hb4">01 01 18 00 00 00 00 00 00 00</span> <span class="hb3">-. 50 </span><span class="hb4">..........</span> | ||
+ | <br /> | ||
+ | 00000020 <span class="hb4">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> F5 <span class="hb4">...............</span>õ | ||
+ | </code> | ||
===Messwerte=== | ===Messwerte=== | ||
Zeile 441: | Zeile 529: | ||
[[Kategorie:Solar-Anlage]] | [[Kategorie:Solar-Anlage]] | ||
[[Kategorie:Pirozeda]] | [[Kategorie:Pirozeda]] | ||
+ | [[Kategorie:Zerlegt]] |
Aktuelle Version vom 12. November 2022, 00:06 Uhr
"Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum VBus-Decoder veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort.
So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen.
Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda.
Ein paar Mails später gab es einen Link auf ein Raspberry Pi-Forum - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen.
Aber ich war am Haken ;-)
Inhaltsverzeichnis
Einblick in den Regler
Ein Griff in die Zukunft - 11/2017:
Im Rahmen der Pirozeda-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen:
Controllerboard
Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte.
Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war.
Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt.
Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt...
Leistungsboard
So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen.
Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter.
Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder.
Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können.
Der Datenstick
Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift)
Livedaten
Denn in etwa an der Stelle, hatte ich das Geräusch vom Kratzen eines Plattenspielers im Kopf. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an:
Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht...
In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft.
Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen):
Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ...
Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist:
Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott.
Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen.
Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ.
Folgende Daten purzeln aus dem Programm:
Time | CS | Data |
---|---|---|
0,00850 | 1 | AA 55 55 AA 02 00 |
0,00998 | 1 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |
0,05851 | 1 | AA 55 55 AA 01 00 |
0,05939 | 1 | 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |
0,20858 | 1 | AA 55 55 AA 02 00 |
0,21006 | 1 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |
0,25859 | 1 | AA 55 55 AA 01 00 |
0,25946 | 1 | 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |
0,40867 | 1 | AA 55 55 AA 02 00 |
0,41015 | 1 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |
0,41492 | 1 | 09 |
Nachrichtentypen
Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen:
Länge | Zyklus [ms] | Meldungstyp | Bezeichnung | Anmerkung |
---|---|---|---|---|
1 | 474/531 | - | unbekannt | immer 0x09, immer 11 bit lang |
6 | n/a | - | Meldungstyp | Gibt an, welche Nachrichtentypen folgen |
33 | 201 | 02 00 |
Remote Request (?) | alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |
64 | 201 | 01 00 |
Displayanzeige | ASCII, synchron zum Displayinhalt am Regler |
68 | 1005 | 03 00 |
Messwerte | Gleiches Datenformat wie auf dem Datastick |
70 | 1005 | 03 01 |
Kopfdaten | Spalteninformationen zu den Messwerten und Systeminfos |
260 | - | - | unbekannt | vermutlich Systemparameter |
Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt.
0x09
Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander.
Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen.
Aber warum die komische Länge von 11 bit?
Meldungstyp
Diese Nachricht kündigt andere Nachrichten an. Die letzten beiden Byte geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an:
Offset(h) 00 01 02 03 04 05
00000000 AA 55 55 AA 01 00 ªUUª..
Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt.
Remote Request
Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird).
Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht.
Leider sind mir über die Inhalte keine näheren Informationen bekannt.
Display
Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt für ein zusätzliches Display. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten dementsprechend.
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 20 20 Wagner & Co
00000010 20 20 20 20 20 20 20 20 20 53 6F 6C 61 72 74 65 Solarte
00000020 63 68 6E 69 6B 20 01 00 00 00 01 00 00 00 10 00 chnik ..........
00000030 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 65 ...............e
- Zeile 1 auf dem Display
- Zeile 2 auf dem Display
- Zeile 3 auf dem Display
- Weitere Daten (siehe unten)
Das letzte Zeichen: siehe Prüfsumme
Weitere Daten
Die weiteren Daten haben sich mir leider nicht vollständig erschlossen, einige Bits und Bytes lassen sich folgenden Displayelementen zuordnen:
Offset | Bit 7 (0x80) | Bit 6 (0x40) | Bit 5 (0x20) | Bit 4 (0x10) | Bit 3 (0x08) | Bit 2 (0x04) | Bit 1 (0x02) | Bit 0 (0x01) |
---|---|---|---|---|---|---|---|---|
0x26 | Symbol Info | |||||||
0x27 | ? | |||||||
0x28 | Pumpe oben | Pumpe mitte | Pumpe unten | |||||
0x29 | ||||||||
0x2A | Symbol Einstellungen | |||||||
0x2B | Relais Rahmen | |||||||
0x2C | Relais 5 | Relais 6 | Relais 1 | Relais 2 | ||||
0x2D | Relais 3 | Relais 4 | Relais 7 | |||||
0x2E | Symbol Hand | |||||||
0x2F | Symbol Fehler | |||||||
0x30 | ||||||||
0x31 | ||||||||
0x32 | Symbol Sonderfkt. | |||||||
0x33 | Symbol "OK?" | |||||||
0x34 | ? |
Anmerkungen:
- Bytes 0x35 bis 0x3E sind nicht in der Tabelle aufgeführt, da bei ihnen keine Veränderungen beobachtet wurden, diese stehen immer auf 0x00
- Die mit Fragezeichen markierten Bits veränderten sich in den Traces, konnten aber keinem Symbol Element auf dem Display zugeordnet werden
- Relais 8 ist unsicher, da es bei Tests nicht angesteuert werden konnte
Fehlerhafte Übertragung
Die zweite und dritte Displayzeile scheint es bei manchen Reglern (z. B. den Ratiofresh200) einen Bug zu geben. Nach genauerer Untersuchung (abermals vielen Dank an Frank für die Unterstützung!) scheint der verwendete Speicher falsch gemappt zu sein, zumindest erscheinen Texte, die für die zweite Zeile bestimmt sind teilweise im Bereich der Dritten.
Dies ist bei der Anzeige der primären Vorlauftemperatur gut zu sehen:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66 20 20 Prim„r Vorlauf
00000010 20 20 20 20 20 20 20 20 20 32 31 20 05 2D 54 20 21 .-T
00000020 35 37 20 37 34 20 01 01 18 00 00 01 08 00 00 00 57 74 ..........
00000030 00 00 00 00 18 00 00 00 00 00 00 00 00 00 00 68 ...............h
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66 20 20 Prim„r Vorlauf
00000010 20 20 20 20 20 20 20 20 20 32 31 20 05 2D 54 20 21 .-T
00000020 35 36 20 37 34 20 01 01 18 00 00 01 08 00 00 00 56 74 ..........
00000030 00 00 00 00 18 00 00 00 00 00 00 00 00 00 00 67 ...............g
Im zweiten Drittel der dritten Zeile (ab Offset 0x1F) sieht man, dass die Messwerte aus der zweiten Zeile "hineingedrückt" wurden.
Bei einem anderen Regler (kann leider nicht mehr sagen, welcher es war) werden die Daten für die beiden Zeilen korrekt übertragen. Eine Display-Nachricht sieht dann beispielsweise wie folgt aus:
00000000 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 Kollektor
00000010 35 30 2E 35 01 43 20 20 20 34 36 20 05 2D 01 43 50.5.C 46 .-.C
00000020 2D 06 20 35 30 20 01 01 18 00 00 00 00 00 00 00 -. 50 ..........
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F5 ...............õ
Messwerte
Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 20 00 6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09 .o.E.!.$...Ø.Ä.
00000010 C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00 Ä.Ä.Ä.E.@.Ä.Í...
00000020 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 .......UU.......
00000030 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF ø.............ðÿ
00000040 00 00 20 C9 .. É
Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme.
Kopfdaten
Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen.
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 0D 11 04 00 20 20 20 20 44 61 74 75 6D 20 20 20 .... Datum
00000010 20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20 .. Uhrzeit
00000020 20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00 .. Sekunden ..
00000030 00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 .... Kollektor
00000040 20 20 01 00 24 28 ..$(
- Konstant
- Adresse
- Daten
- Trennzeichen
- Prüfsumme
Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt.
Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf:
Adresse | Bezeichnung |
---|---|
0x00 |
Spaltenbeschreibung 0 |
0x04 |
Spaltenbeschreibung 1 |
0x04 * n |
Spaltenbeschreibung n |
0x20 |
Spaltenbeschreibung 8 |
0xFA |
Systemdaten |
Spaltenbeschreibungen
Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 08 01 Datum ..
00000010 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 09 02 Uhrzeit ..
00000020 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 10 03 Sekunden ......
00000030 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 01 00 Kollektor ..
00000040 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 01 05 Speicher ¹ ..
00000050 20 20 53 70 65 69 63 68 65 72 20 B3 20 20 01 06 Speicher ³ ..
00000060 20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 01 07 Rücklaufanh. ..
00000070 20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 01 00 Rücklaufanh. ..
Wo das vorletzte Byte jeder Spaltenbeschreibung 0x00
war, steht hier der Spaltentyp. Dafür wird hier das letzte Byte hochgezählt, wobei das letzte einer Nachricht immer 0x00
ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature?
Systemdaten
Auch die Systemdaten sind etwas anders aufgebaut als im Datastick:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 FB Wagner & Co .û
00000010 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 00 FC Solartechnik .ü
00000020 XX XX XX XX XX XX XX XX XX XX 00 00 00 00 00 FD XXXXXXXXXX.....ý
00000030 XX XX XX XX XX XX 00 XX XX XX XX 00 00 00 00 00 XXXXXX.XXXX.....
- Systemname
- Seriennummer
- System-Nummer
- System-Version
Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian.
Systemparameter
Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen.
Prüfsumme
Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme.
Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also RevEng heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben so manche eine Vorliebe, das mit der Summe wörtlich zu nehmen.
Warum nicht mal JavaScript?
var msg = "20 00 6F ... C9";
var bytes = msg.split(/ /);
var sum = 0;
for (var i = 0; i < bytes.length; i++)
{
bytes[i] = parseInt(bytes[i], 16);
if (i < bytes.length - 1)
{
sum += bytes[i];
}
}
var csok = (sum & 255) == bytes[bytes.length - 1];
console.log('checksum is %sok', csok ? '' : 'not ');
Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt.
Angezapft
Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden.
Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht.
Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will).
Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können.
Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen.
Als Schnittstelle zum restlichen Programm dienen drei Methoden:
- prozeda_rxData
- prozeda_tick
- prozeda_task
prozeda_rxData
muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt.
prozeda_tick
erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss PROZEDA_MSG_MAXTICKS
angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden.
Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag prozeda_process
gesetzt und damit prozeda_task
zur Ausführung freigegeben.
prozeda_task
ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten prozeda_tick
und dem nächsten prozeda_rxData
noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick
wegkopiert bevor sie von prozeda_rxData
überschrieben werden können.
Hardware
AVR | |
---|---|
Typ | AtMega328P |
Takt | 12 MHz |
Fuses | |
High | 0x0xD9 |
Low | 0x0xCE |
Extended | 0x0xFF |
Details |
Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse.
Timing
Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen.
Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet.
Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben.
Zum Beispiel fallen beim TIMER0_COMOA_vect
beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden.
Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs
Methode | Bezeichnung | Dauer [µs] |
---|---|---|
prozeda_tick | keine Kommunikation | 0,588 |
prozeda_tick | während Kommunikation | 1,338 |
prozeda_tick | 4 Zyklen nach Kommunikation | 1,844 |
prozeda_rxData | - | 1,419 |
prozeda_process | nach MsgType-Nachricht | 8,918 |
prozeda_process | nach Paket != Logdata | 2,339 |
prozeda_process | nach 0x09 | 2,339 |
prozeda_process | nach Logdata | 110,75 |
Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten.
Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead:
Methode | CPU-Zeit [%] |
---|---|
prozeda_tick | 0,968 |
prozeda_rxData | 0,025 |
prozeda_process | 0,101 |
Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung.
Implementierungsstatus
Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre.
Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte.
Programmbeispiel
Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben.
Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden.
Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller.
Anmerkungen
- Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld!
- Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B.
- Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut.
- Es gibt nun eine Implementierung für den Raspberry Pi: Pirozeda
Downloads
Datei:Prozeda-Decoder.zip enthält:
- Hexdump eines Flashimages
- Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung
- Atmel Studio-Projekt zur Emulation des Datasticks
- Atmel Studio-Projekt mit dem Reader der Livedaten