Forum: Mikrocontroller und Digitale Elektronik Datenübertragung von Außeneinheit einer Wetterstation


von Wolfgang H. (hadroncollider)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe mir von Pollin eine billige »Wetterstation« für 5,95€ geholt, 
die die Raumtemperatur anzeigt und über eine Funk-Außeneinheit die 
Außentemperatur.

Mein Ziel ist es, die Empfängerplatine (auf der ein Himark RX3310A 
sitzt) an einem AVR zu benutzen. Hierüber empfange ich leider auch 
allerlei Störungen, weshalb ich mich erst mal an die Außeneinheit 
gemacht habe. Dort hab ich die Daten, die sie sendet, direkt 
abgegriffen.

Diese Daten habe ich nun einem ATMega32 geloggt und über die serielle 
Schnittstelle zum PC geschickt. Jetzt steht allerdings die Analyse der 
Daten an, damit ich hinter das Protokoll komme.

Dazu habe ich mir ein Perlscript geschrieben, das die Daten lesbarer 
macht. Vielleicht könnte sich die jemand angucken (im Anhang) und 
erkennt dabei etwas. Mag ja sein, dass es mit etwas Glück irgendein 
Standardprotokoll mit einer bestimmten Fehlererkennung ist.

Zum Anhang: Die Temperatur betrug 17,5 °C.

Gruß,
Wolfgang

von Ulrich P. (uprinz)


Lesenswert?

Es wäre wirklich hilfreicher, man hätte ein paar unterschiedliche 
Temperaturen im Logfile. Kannst Du das nicht noch mal an Deinen Logger 
anschließen und warten, bis es sich eingependelt hat. Dann loggen und 
die Schreibtischlampe über dem Teil einschalten. Wenn es eine der 
üblichen Halogenlampen ist, sollte die Temperatur dann ansteigen.
Neben jeden Binär-String bitte die Temperatur schreiben.

Die Werte 1 (0001) und 7 (0111) tauchen in dem Texfile recht häufig auf. 
Es gibt auch einen Block aus vielen 1ern, der als Sync dienen könnte. 
Bit Bit 120 stimmen diese Blöcke überein, dann gibt es Unterschiede.

Es gibt da leider keinen Standard, der eine Temperatur-Kodierung 
beschreibt. Es könnte sein, dass es Nibbels sind, die mehrfach 
übertragen werden. Es kann sein, dass man von einem Bestimmten Null-Punt 
ausgeht und dazu eine binäre Differenz überträgt.
Also: 0x17 0x01 für 17.5° ist ebenso möglich, wie 0x73 für folgende 
Rechnung:
0-Punkt ist -40°C, 7-Bit für 128° ab -40 aufwärz, 1 Bit für 0.5°C

Es hilft auch zu wissen, welche Auflösung das Gerät hat, dann weiß man, 
ob die 1/10°C dezimal oder nur als Bit übertragen werden müssen. Leider 
finde ich auch keine Wetterstation für 5,95€, ist also etwas mühsam.

Gruß, Ulrich

von dc3yc (Gast)


Lesenswert?

Wolfgang,

wenn du dir die 3 Syncblöcke anschaust, wirst du bemerken, dass die drei 
Blöcke fast identische Daten enthalten. Deswegen nehme ich an, dass das 
Telegramm dreimal gesendet wird.
Wie mein Vorschreiber schon sagte, ist es hilfreich, mehrere 
verschiedene Telegramme zu loggen, um Gemeinsamkeiten und /unterschiede 
herauszuarbeiten. Welcher Typ von WS ist es denn?

Servus,
Helmut.

von Düsentrieb (Gast)


Lesenswert?

guck mal hier
http://www.wetterfreaks.de/phpBB/viewforum.php?f=28&sid=76c63af3bd7119c120c4ec3f1e8e3095

evtl findest du passende info, auf jeden fall ähnliche daten zur 
orientierung...

von Wolfgang H. (hadroncollider)


Lesenswert?

Pollin bietet den Artikel leider nicht mehr an, habe ich gerade
festgestellt. Die Bestellnummer war 830 212. Im beigelegten Zettel steht
nur:
- Temperaturanzeigebereich: -50 °C bis 70 °C
- Empfohlener Temp.bereich, Sensor (außen): -20 °C bis 60 °C
- Anzeigegenauigkeit: 0,1 °C

Ich habe eine Reihe weiterer Messergebnisse angehängt. (Die Datei hat
Unix-Zeilenumbrüche.)
Bitte beachtet den Anhang aus meinem ersten Post nicht mehr: Dort
fehlten die letzten Bits (Fehler im Programmcode).

Edit:
Wie man die Temperatur daraus liest, weiß ich jetzt. :)
1
19,5 Grad
2
111111111111111111111111111111
3
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0111 0111 0001 0111 0111 0111
4
111111111111111111111111111
5
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0001 0111 0001 0111 0001 0111
6
111111111111111111111111111111
7
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0111 0001 0001 0111 0111 0001
8
111111111111111111111111111
9
10
20,1 Grad
11
111111111111111111111111111111
12
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0001 0111 | 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0111 0111 0111 0111 0001 0001 0111 0111
13
111111111111111111111111111
14
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0001 0111 | 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0111 0111 0001 0111 0001 0001 0001 0111
15
111111111111111111111111111111
16
0001 0111 0111 0001 0111 0111 0111 0111 | 0111 0111 0001 0111 | 0111 0111 0111 0111 | 0111 0111 0111 0001 | 0111 0111 0111 0001 0001 0001 0111 0001
17
111111111111111111111111111

0111 ist eine Null, 0001 eine Eins. Das niedrigstwertige Bit ist rechts.
Der erste Abschnitt von | nach | sind die Zehner der Temperatur, der 
zweite Abschnitt die Einer und der dritte die eine Nachkommastelle.

Mal ein paar andere Temperaturen messen, um noch auf negative 
Temperaturen zu kommen. Momentan genau das richtige Wetter dafür.

Das Bearbeiten hat meinen Anhang gekillt. Hier ist er nochmal: 
http://de.pastebin.ca/820396

von Wolfgang H. (hadroncollider)


Lesenswert?

Interessiert das Thema jemanden?

Hier der Aufbau für Minustemperaturen:
1
-4,5 Grad
2
111111111111111111111111111111
3
0001 0111 0111 0001 | 0001 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0111 0111 0111 0001 0111 0001
4
111111111111111111111111111
5
0001 0111 0111 0001 | 0001 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0001 0111 0111 0001 0001 0001
6
111111111111111111111111111111
7
0001 0111 0111 0001 | 0001 0111 0111 0001 | 0001 0111 0111 0001 | 0111 0001 0111 0001 | 0111 0001 0111 0001 | 0111 0111 0111 0001 0111 0001 0001 0111
8
1111111111111111111111111111

Während positive Temp. mit
1
0001 0111 0111 0001 | 0111 0111 0111 0111
anfangen, fangen negative so an:
1
0001 0111 0111 0001 | 0001 0111 0111 0001

Die Zehner, Einer und die Nachkommastelle sind wie bei den positiven 
Temperaturen kodiert. Hier im Beispiel ergibt sich 95,5. Von diesem Wert 
subtrahiert man 100 und erhält die richtige Temperatur: -4,5 °C

Die Datenübertragung erfolgt übrigens immer in Celsius. Auch wenn 
Fahrenheit für die Anzeige gewählt ist.

von Volker (Gast)


Lesenswert?

Hallo Wolfgang

Ich habe das auch mal mit der WS-308G von Pollin versucht, aber 
irgendwie kam da nur Müll raus. Wie genau hast du denn die Rohdaten des 
Senders verarbeitet um an die Bitwertigkeiten zu kommen?  Oder hast du 
den Ausgangspegel einfach nur mit einer festen Frequenz abgetastet?

Gruß, Volker

von Ulrich P. (uprinz)


Lesenswert?

Ich kann dem Protokoll dann noch die fehlenden Bytes zuordnen:
1
0001011101110001 0111011101110111 0111011101110001 0111000100010001 0111000101110001 0111011101110111 0111000100010111 
2
  1   0   0   1    0   0   0   0    0   0   0   1    0  1   1   1     0   1   0   1    0   0   0   0    0   1   1   0
3
9 0 1 7 5 0 6
4
0001011101110001 0111011101110111 0111011101110001 0111000100010001 0111000101110001 0111011100010111 0001011101110111 
5
  1   0   0   1    0   0   0   0    0   0   0   1    0  1   1   1     0   1   0   1    0   0   1   0    1   0   0   0
6
9 0 1 7 5 2 8
7
0001011101110001 0111011101110111 0111011101110001 0111000100010001 0111000101110001 0111011101110001 0111000100010001
8
  1   0   0   1    0   0   0   0    0   0   0   1    0  1   1   1     0   1   0   1    0   0   0   1    0   1   1   1
9
9 0 1 7 5 1 7

Die 9 0 sollte die Adresse der Außenstation sein, damit sie von anderen 
unterschieden werden kann.

Das letzte Nibble ist das low Nibble der Prüfsumme aller zuvor 
gesendeten Nibbles:
9+0+1+7+5+0 = 0x16 -> low nibble = 0x6
Jedes Datagramm wird 3 mal gesendet, dabei wird das vorletzte Nibble in 
der Reihenfolge 0 -> 2 -> 1 verändert und die Prüfsumme angepasst.

Gruß, Ulrich

von Martin K. (maart)


Lesenswert?

Wie sieht es denn mit einer Prüfsumme aus? Ich meine, wie wird die 
berechnet? Ich hatte mich damals auch mal an ein Lidl-Thermometer 
gewagt, Auslesen ging gut, wenn man auf die Prüfsummensicherung 
verzichtet. (also nicht ganz optimal, Daten selber senden konnte ich 
somit definitiv nicht)


Gruß, Martin

von Ulrich P. (uprinz)


Lesenswert?

Hmm... Ich vermute mal, dass Du vergessen hast die Seite neu zu laden, 
denn sonst wäre Dir aufgefallen, dass Deine Frage direkt im Post über 
Deinem von mir beantwortet wird...

Gruß, Ulrich

von Martin K. (maart)


Lesenswert?

>dabei wird das vorletzte Nibble in
>der Reihenfolge 0 -> 2 -> 1 verändert und die Prüfsumme angepasst.

Hm, vielleicht stehe ich jetzt auf dem Schlauch: wie wird die 
Prüfsumme jetzt angepasst?

von Ulrich P. (uprinz)


Lesenswert?

Es wird die Temperatur immer drei mal übertragen.
Im ersten Paket ist das vorletzte Nibble 0, im zweiten 2 und im dritten 
1.
Die Prüfsumme ist die Summe aller Bytes hexadezimal, das zuvor 
beschriebene Zähler-Nibble geht in die Prüfsumme mit ein. Die Prüfsumme 
wird auf die unteren 4 bit beschränkt, die oberen fallen einfach weg 
(alles HEX):
9+0+1+7+5+0 = 16 -> Prüfsumme = 6
9+0+1+7+5+2 = 18 -> Prüfsumme = 8
9+0+1+7+5+1 = 17 -> Prüfsumme = 7

Man beachte die ungerade Anzahl an Nibbles, ein Controller, der das 
Protokoll als Sender emuliert, muss also vorweg ein 1111 Paket senden. 
Die Anzahl der vorab gesendeten 1en ist aber in dem Trace 
unterschiedlich. Ich gehe davon aus, dass es mit einem SPI einfach zu 
emulieren ist. Man setzt das Interface auf ruhend = 1. Ein Datagramm 
sendet man mit einem Byte Adresse ( 90), 10er 1ner Temperatur in einem 
Byte, 1/10el und Counter in einem Byte und zuletzt die Prüfsumme im 
high-Nibble des letztem Bytes gefolgt von einem F.
1
uint8_t TH, TD; // Temperatur, Temperatur 1/10
2
...
3
void send_datagramm( TH, TD)
4
{
5
  uint8_t i, Dcount;  // Counter, Datagramm Counter
6
  uint8_t crc;     // Prüfsumme
7
  
8
  Dcount = 0x40; // Dcount mit einer zuerst unsichtbaren 1 vor laden
9
  for( i=0; i<3; i++) {
10
11
    crc = (TH>>4)+(TH&0x0F)+(TD)+(Dcount&0x03);
12
  
13
    spi_tx( 0x90);     // sende Adresse / Sync?
14
    spi_tx( TH);     // sende Temperatur 10er/1er
15
    spi_tx( (TD<<4)|(Dcount&0x03));  // Temperatur 1/10 im high, counter im low-nibble
16
    spi_tx( (CRC<<4)|0x0F);  // prüfsumme im high- F im low-nibble
17
    Dcount >>= 1; // schiebe Dcount um ein Bit nach rechts
18
  }
19
}

Zur Berechnung von Dcount:
Zuerst is Dcount 00000100. Da wir Dcount mit & 0x03 auf die beiden 
letzten Bits beschränken, bleibt für das erste Datagramm 00 übrig.
Dann ist Dcount 00000010. Also senden wir eine 10
Zuletzt ist Dcount 00000001 -> ergo senden wir eine 01 in den 
zuständigen 4 Bits

So, mehr kann ich jetzt wirklich nicht mehr beschreiben.

von Martin K. (maart)


Lesenswert?

>So, mehr kann ich jetzt wirklich nicht mehr beschreiben.

Ich danke dir! Ich werde mir heute Abend mal meine damals 
mitgeschriebenen Protokolle nochmal ansehen.

von Ulrich P. (uprinz)


Lesenswert?

Viel Erfolg. Wenn sie anders aussehen, kannst Du sie auch mal posten, 
das entschlüsseln macht immer wieder Spaß :)

Ist wie Sudoku, aber halt mit Nutzeffekt.

Gruß, Ulrich

von Wolfgang H. (hadroncollider)


Angehängte Dateien:

Lesenswert?

Volker wrote:
> Wie genau hast du denn die Rohdaten des
> Senders verarbeitet um an die Bitwertigkeiten zu kommen?

Ich habe den von mir benutzten Code angehängt. Sehr schön ist der nicht, 
aber er tut offensichtlich. Die beste Vorgehensweise damit ist, den AVR 
zu resetten und dann den Sender zu resetten, damit er sendet.

Ich benutze dafür das Atmel-Evaluationsboard (die Version ohne Funk) von 
Pollin. An PA0 hängt die Datenleitung des Senders, PD4 ist ein Taster, 
PD5 und PD6 sind LED und PD7 ist ein Buzzer.

Wenn Daten empfangen werden, blinkt PD5. Wenn eines der Arrays (siehe 
Code) 85 Elemente enthält, geht PD6 an. Wenn nach 85 gespeicherten 
Werten immer noch Daten kommen, geht PD6 aus und der Buzzer piept kurz.

Die Arrays enthalten die Dauern, wie lange, gemessen in 
Loop-Durchläufen, low und high auf der Datenleitung anlag.

Wenn PD6 leuchtet, kann man den Taster drücken und die Arrays werden auf 
der seriellen Schnittstelle ausgegeben. Mit diesen Werten habe ich dann 
mein Perlscript gefüttert, das daraus Nullen und Einsen macht. Falls 
Interesse besteht, lade ich das noch hoch.

Ulrich P. wrote:
> Die 9 0 sollte die Adresse der Außenstation sein, damit sie von anderen
> unterschieden werden kann.

Die 0 dient bereits zur Erkennung von Minustemperaturen. Ob die 9 als 
Kennung des Senders dient, werde ich überprüfen. Habe zwei solcher 
Stationen.

Großes Danke für die Aufschlüsselung der Prüfsumme!

von Volker (Gast)


Lesenswert?

@Wolgang

Ja, danke - habe deinen Code mal kurz überflogen. Du pollst also den 
Datenausgang welcher direkt den Sender moduliert - hattest du ja auch in 
deinem 1. Posting so geschrieben :-)

Gruß, Volker

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.