mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wetterstation Windrichtung kodieren und dekodieren


Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich habe folgendes Problem.
Ein Wettersensor sendet die Windrichtung in einem Datenpaket an eine 
Wetterstation. Der Wert für die Richtung ist in einem Nibble enthalten.
Somit sind 16 Windrichtungen möglich.

Der Wert wird allerdings irgendwie kodiert versendet.
Mit folgender C-Function kann der Wert entschlüsselt werden:

byte decodeWindDirection(byte winddir)
  {
    b ^⁼ (b & 8) >> 1;
    b ^⁼ (b & 4) >> 1;
    b ^⁼ (b & 2) >> 1;
    return -b & 0xf;
  }

Übergeben wird der Funktion ein Wert 0 bis 15 (die verschlüsselte 
Windrichtung). Und heraus kommt die unverschlüsselte Windrichtung mit 
Werten 0-15.

Das Ergebnis mit 22.5° multipliziert ergibt die Windrichtung in Grad.

Soviel zur Erklärung.

Hat jemand eine Idee, wie man die Funktion umkehren kann?

Hier eine Tabelle mit einigen Richtungen. z.B Osten ist 90° und der 
Binärwert unverschlüsselt 4. Nach dem Encrypten soll daraus 9 werden.

Für das Decrypten kann obige Funktion verwendet werden, die auch 
funktioniert.

Richtung | Winkel | Dec | Enc
  N      =   0,0° =  0  = 0
 NNO     =  22,5° =  1  = 8
  NO     =  45,0° =  2  = 9
 ONO     =  67,5° =  3  = 11
  O      =  90,0° =  4  = 10
 OSO     = 112,5° =  5  = 14
  SO     = 135,0° =  6  = 15
 SSO     = 157,5° =  7  = 13
  S      = 180,0° =  8  = 12

Wäre schön, wenn jemand eine Idee hat, wie die Funktion umgekehrt werden 
kann.

Gruß Micha.

: Bearbeitet durch User
Autor: Sebastian E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man es sich binäre anschaut, könnte das eine Art Gray-Code sein:

Richtung | Winkel | Dec | Enc | Enc Binär
  N      =   0,0° =  0  = 0   | 0000
 NNO     =  22,5° =  1  = 8   | 1000
  NO     =  45,0° =  2  = 9   | 1001
 ONO     =  67,5° =  3  = 11  | 1011
  O      =  90,0° =  4  = 10  | 1010
 OSO     = 112,5° =  5  = 14  | 1110
  SO     = 135,0° =  6  = 15  | 1111
 SSO     = 157,5° =  7  = 13  | 1101
  S      = 180,0° =  8  = 12  | 1100

Was spricht bei 16 Werten gegen eine Lookup-Table?

Autor: Peter II (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> byte decodeWindDirection(byte winddir)
>   {
>     b ^⁼ (b & 8) >> 1;
>     b ^⁼ (b & 4) >> 1;
>     b ^⁼ (b & 2) >> 1;
>     return -b & 0xf;
>   }

woher kommt denn die Variabel b?

und was soll das Zeichen nach dem ^ darstellen?

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry,

b ist die Windrichtung, die übergeben wird

So ist es vielleicht verständlicher:

> byte decodeWindDirection(byte b)
>   {
>     b ^= (b & 8) >> 1;
>     b ^= (b & 4) >> 1;
>     b ^= (b & 2) >> 1;
>     return -b & 0xf;
>   }

Übrigens, könnte schon sein, dass es der Greycode ist.

Bleibt die Frage, wie man den umdreht.

: Bearbeitet durch User
Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian:

Eine Lookup Tabelle wäre die letzte Option, wenn es keine mathematische 
Lösung gibt.

Schön wäre eine Function wie

byte encodeWindDir(byte dir)
{
  ...
}

die das Ergebnis berechnet.

Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Übrigens, könnte schon sein, dass es der Greycode ist.

00: 0000
01: 0001
02: 0011
03: 0010
04: 0110
05: 0111
06: 0101
07: 0100
08: 1100
09: 1101
10: 1111
11: 1110
12: 1010
13: 1011
14: 1001
15: 1000

Richtung | Winkel | Dec | Enc | Enc Binär | Gray
  N      =   0,0° =  0  = 0   | 0000      |  0
 NNO     =  22,5° =  1  = 8   | 1000      | 15
  NO     =  45,0° =  2  = 9   | 1001      | 14
 ONO     =  67,5° =  3  = 11  | 1011      | 13
  O      =  90,0° =  4  = 10  | 1010      | 12
 OSO     = 112,5° =  5  = 14  | 1110      | 11
  SO     = 135,0° =  6  = 15  | 1111      | 10
 SSO     = 157,5° =  7  = 13  | 1101      |  9
  S      = 180,0° =  8  = 12  | 1100      |  8

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier gibts Code für Hin- und Rückweg vom Gray Code:

https://en.wikipedia.org/wiki/Gray_code#Converting_to_and_from_Gray_code

Und ja, es ist Gray, was da aus dem Windfähnchen kommt.

Autor: Ostwind (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Wikipedia ist doch immer wieder für Überraschungen gut:

https://en.wikipedia.org/wiki/Greycode

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Link ist interessant leider funktioniert das nicht.

Beispiel ich übergebe binär 2 für NO (45°) und 9 soll kodiert raus 
kommen.

Ergebnis ist aber 3

Und die Funktion habe ich verwendet:

// The operator >> is shift right. The operator ^ is exclusive or.

unsigned int binaryToGray(unsigned int num)
{
    return num ^ (num >> 1);
}

Und bei 4 als übergabewert sollte 10 raus kommen, Ergebnis ist aber 6.

Scheint doch nicht ganz Geycode zu sein.

Autor: Peter II (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Scheint doch nicht ganz Geycode zu sein.

kannst du mal alle werte von 0-15 posten, die aus der Funktion 
rauskommen?

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter II schrieb:
> kannst du mal alle werte von 0-15 posten, die aus der Funktion
> rauskommen?


Ich habe die Tabelle etwas erweitert:

Aus dieser Funktion

> byte decodeWindDirection(byte b)
>   {
>     b ^= (b & 8) >> 1;
>     b ^= (b & 4) >> 1;
>     b ^= (b & 2) >> 1;
>     return -b & 0xf;
>   }

kommen folgende Werte:
(Spalte ENC ist Übergabeparameter, Ergebnis in Spalte DEC)

                                ENC
Richtung | Winkel | Dec | Enc | BIN
  N      =   0,0° =   0 = 0     0000
 NNO     =  22,5° =   1 = 8     1000
  NO     =  45,0° =   2 = 9     1001
 ONO     =  67,5° =   3 = 11    1011
  O      =  90,0° =   4 = 10    1010
 OSO     = 112,5° =   5 = 14    1110
  SO     = 135,0° =   6 = 15    1111
 SSO     = 157,5° =   7 = 13    1101
  S      = 180,0° =   8 = 12    1100

 SWS     = 202,5° =   9 = 4     0100
  SW     = 225,0° =  10 = 5     0101
 WSW     = 247,5° =  11 = 7     0111
  W      = 270,0° =  12 = 6     0110
 WNW     = 292,5° =  13 = 2     0010
  NW     = 315,0° =  14 = 3     0011
 NWN     = 337,5° =  15 = 1     0001

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist normaler Graycode, wenn auch gegen den Uhrzeigersinn - also dem 
mathematisch positiven Drehsinn.

: Bearbeitet durch User
Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
16 Werte?! Na also da würde ich ne LookUp machen! Wo siehst du denn da 
ein Problem? Ob ich den Flash mit ner Berechnung zupflaster oder ner 
Progmem... da wäre die Entscheidung aber einfach!

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Das ist normaler Graycode, wenn auch gegen den Uhrzeigersinn - also dem
> mathematisch positiven Drehsinn.

Kannst du das in eine C-Funktion packen?

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Kannst du das in eine C-Funktion packen?

Jep, ich nutze die Funktion von Wikpedia:
float gry2deg(uint16_t grey)
 {
   return 360 - (grayToBinary(grey) * 22.5f);
}
Ich würde normalerweise das Ergebnis nicht als float zurückgeben, 
sondern intern mit Grad mal 10 rechnen, um die 0.5 Grad loszuwerden. 
Also
 
uint16_t gry2deg(uint16_t grey)
 {
return 3600 - (grayToBinary(grey) * 225);
}

: Bearbeitet durch User
Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
geht das auch, wenn man nur Werte 0 - 15 (unkodiert) anstelle der 
Gradzahl übergibt?

Ich rechne lieber mit dem 4-Bit Wert.

Hintergrund ist, evtl. Windrichtung direkt an Wetterstations-Empfänger 
zu senden.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Hat jemand eine Idee, wie man die Funktion umkehren kann?

Eine Tabelle zur Umcodierung benötigt genau 8 Byte. Was willst du denn 
da für eine großartige Funktion schreiben?
Du kannst natürlich die Spiegelsymmetrie im Gray-Code ausnutzen, um das 
algorithmisch umzukodieren, aber meinst du nicht, dass das übertriebener 
Ehrgeiz ist. In wage mal zu behaupten, dass das mit 8 Byte (zusätzlich 
zur Tabellenausleseroutine) nicht kodiert ist.

Und schneller ist die Tabellenmethode auch noch.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Ich rechne lieber mit dem 4-Bit Wert.
Dann definierst du deinen Kram einfach um und setzt eben für 1 nicht NNO 
sondern NNW.

Autor: Simpel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Hintergrund ist, evtl. Windrichtung direkt an Wetterstations-Empfänger
zu senden."

Sende den Code doch ans HAARP-Relay, dann hast du morgen die gewünschte 
Windrichtung...

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simpel schrieb:
> Sende den Code doch ans HAARP-Relay, dann hast du morgen die gewünschte
> Windrichtung...

Und du bist sicher, dass das Ding wieder läuft?
http://www.arrl.org/news/haarp-facility-shuts-down

Autor: Simpel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Wolfgang
Bin nicht mehr up to date... vielleicht ist mei Aluhut oxydiert. :)

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim dekodieren geht's ja auch ohne Tabelle.
Warum sollte es dann umgekehrt nur mit Tabelle gehen?

Ich wollte den Algorithmus.

Klar geht's mit Tabelle. Wenn ich das gewollt hätte, wäre dieser Thread 
nie geschrieben worden.

Übrigens hat das nichts mit HAARP zu tun. Das ist eine andere Baustelle, 
über die ich mich hier nicht auslassen will. Und Wenn man Haarp erwähnt 
sollte man Chemtrail und Geoengeneering auch erwähnen. Ich weis wir 
werden alle besprüht wie Insekten.

Hat aber nichts mit dem Thema zu tun.

Trotzdem danke für eure Hilfe.

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Übrigens hat das nichts mit HAARP zu tun. Das ist eine andere Baustelle,
> über die ich mich hier nicht auslassen will. Und Wenn man Haarp erwähnt
> sollte man Chemtrail und Geoengeneering auch erwähnen. Ich weis wir
> werden alle besprüht wie Insekten.

Soooo... und ich bin raus! :'D

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Jep, ich nutze die Funktion von Wikpedia:float gry2deg(uint16_t grey)
>  {
>    return 360 - (grayToBinary(grey) * 22.5f);
> }
> Ich würde normalerweise das Ergebnis nicht als float zurückgeben,
> sondern intern mit Grad mal 10 rechnen, um die 0.5 Grad loszuwerden.

Was soll die Ausgabe mit einer Auflösung von 0.5 Grad. Der Sensor hat 
eine relative Auflösung von weniger als 6 Prozent vom Messbereich. Eine 
Ausgabe mit einer Auflösung von besser als 0.2 Prozent ist da wohl 
ziemlicher Schwachfug. Oder schreibst du vom Taschenrechner auch immer 
alle 13 angezeigten Stellen ab?

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich habe die Lösung!

Die entscheidenden Hinweise waren, dass es sich um Greycode handelt und 
dass der rückwärts geht.

Das hat mich auf eine Idee gebracht, die funktioniert:

In Assembler sieht die encoder-Routine so aus:

in r24 wird der zu codierende Wert übergeben und codiert zurück gegeben

   encWindDirection:
      COM r24
      Inc r24
      MOV r25,r24
      ANDI r25,$F
      LSR r25
      EOR r24,r25
      ANDI r24,$F
   Ret

Ich hab's mit allen Werten durchgespielt, es funktioniert.

in C umgeschrieben sieht die Funktion etwa so aus (auch getestet):

byte encWindDirection(byte dir)
{
   byte tmp;
   dir = (dir ^ 0x0F);
   dir ++;
   dir &= 0x0F;
   dir = dir ^ (dir >>1);
   return  dir & 0x0F;
}

Hier ein voll lauffähiges Arduino-Programm:

byte encWindDirection(byte dir)
{
   byte tmp;
   dir = (dir ^ 0x0F);
   dir ++;
   dir &= 0x0F;
   dir = dir ^ (dir >>1);
   return  dir & 0x0F;
}



void setup() {
   // put your setup code here, to run once:

   Serial.begin(9600);

   byte wert, ergebnis;
   String ausgabe;
   for (wert=0; ; wert++)
   {
      ergebnis=encWindDirection(wert);
      ausgabe="Wert: " + String(wert,DEC) + " ergibt codiert: " + 
String(ergebnis,DEC);
      Serial.println(ausgabe);
      if (wert==15) break;
   }

}

void loop() {
   // put your main code here, to run repeatedly:

}



Danke an alle für die konstruktiven Infos.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Was soll die Ausgabe mit einer Auflösung von 0.5 Grad

Ich habe nie von einer solchen Auflösung geredet. Der TE hat lediglich 
diese Tabelle gestellt:

Micha R. schrieb:
> Richtung | Winkel | Dec | Enc | BIN
>   N      =   0,0° =   0 = 0     0000
>  NNO     =  22,5° =   1 = 8     1000
>   NO     =  45,0° =   2 = 9     1001
>  ONO     =  67,5° =   3 = 11    1011
>   O      =  90,0° =   4 = 10    1010
>  OSO     = 112,5° =   5 = 14    1110
>   SO     = 135,0° =   6 = 15    1111
>  SSO     = 157,5° =   7 = 13    1101
>   S      = 180,0° =   8 = 12    1100
>
>  SWS     = 202,5° =   9 = 4     0100
>   SW     = 225,0° =  10 = 5     0101
>  WSW     = 247,5° =  11 = 7     0111
>   W      = 270,0° =  12 = 6     0110
>  WNW     = 292,5° =  13 = 2     0010
>   NW     = 315,0° =  14 = 3     0011
>  NWN     = 337,5° =  15 = 1     0001

Und wenn er solche Ergebnisse wieder haben will, ist nun mal ein ,5 bei 
jeder zweiten Gradzahl.

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Was soll die Ausgabe mit einer Auflösung von 0.5 Grad. Der Sensor hat
> eine relative Auflösung von weniger als 6 Prozent vom Messbereich. Eine
> Ausgabe mit einer Auflösung von besser als 0.2 Prozent ist da wohl
> ziemlicher Schwachfug. Oder schreibst du vom Taschenrechner auch immer
> alle 13 angezeigten Stellen ab?

Das mit den 0.5° ist nicht von mir, sondern ergibt sich aus dem 
Windrichtungs-Nibble. Damit lassen sich 16 Positionen darstellen.
Zähle mal die Windrichtungen zusammen, es sind exakt 16.

Will man die Windrichtung in Grad haben, müsste man den decodierten Wert 
mit 22.5° multiplizieren. Daher kommt das. Ansonsten gibt der Wert nur 
die Position an (ähnlich bei einer Uhr mit 1 bis 12).

Ich brauchte aber nur die Kodierung und die Dekodierung von dem Nibble. 
Dir Umrechnung in Grad war klar.

Autor: Stefan B. (sibbl) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um welchen Windsensor genau handelt sichs denn da?

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Will man die Windrichtung in Grad haben, müsste man den decodierten Wert
> mit 22.5° multiplizieren. Daher kommt das.

Die 0.5 in der Ausgabe ist trotzdem beliebig gelogen. Eine Rückgabe in 
vollen Grad ist allemal ausreichend. Nichtmal die Schaltflanken am 
Sensor werden so genau liegen.

Aber natürlich kommen dann die Code-Recycler, die Wert drauf legen, dass 
die Routine auch mit einem 14-Bit Geber noch läuft ;-)

Autor: tmomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Um welchen Windsensor genau handelt sichs denn da?

Bzw. welche Wetterstation soll die Daten empfangen?
Just curious.

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie der Windsensor vom Modell her heißt weis ich nicht.
Der Empfänger ist eine TFA Dostmann, ist auch kompatibel mit Cresta. 
Irgendwas mit WS..., ich habe selbst keine.

Die haben so ein merkwürdiges Funkprotokoll.
Ehrlich gesagt würden mir solche Merkwürdigkeiten für ein Funkprotokoll 
nicht einfallen.

Alles verkodet und dann noch mal verschlüsselt. Obendrein kuriose 
Checksummen und eine reicht ja nicht, muss noch ne 2. her, die völlig 
anders ist.

Also sehr merkwürdiges Funkprotokoll würde ich sagen.

Also da gibt es einfachere Protokolle.

Autor: Stefan B. (sibbl) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe für den WS-Sensor für die Windrichtung eine C-/H-Datei, die die 
Nibbles richtig auswertet. Ich setze sie morgen mal hier rein, falls von 
Interesse....
Ich wollte den Sensor damals in meine Wetterstation einbinden, nur 
verlor ich, nachdem alles fast fertig war die Lust dran.
Aber die Auswertung des Windsensors ging super.

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Ich habe für den WS-Sensor für die Windrichtung eine C-/H-Datei, die die
> Nibbles richtig auswertet. Ich setze sie morgen mal hier rein, falls von
> Interesse...

Hallo Stefan,

natürlich bin ich interessiert, wie das in C gemacht wurde.
Kannst es mir auch per Mail schicken, falls du es nicht veröffentlichen 
willst.

Gruß Micha

Autor: Stefan B. (sibbl) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Micha,

anbei die wichtigsten Dateien für Dein Vorhaben.

Vielleicht hilfts Dir weiter....


Gruss

Autor: Micha R. (michaavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Hi Micha,
>
> anbei die wichtigsten Dateien für Dein Vorhaben.
>
> Vielleicht hilfts Dir weiter....
>
>
> Gruss

Hallo Stefan,

danke für die Dateien. Ich hab mir das mal angeschaut.
Aber es ist anders kodiert. Im Speziellen ist die Windrichtung nach dem 
Grey-Code kodiert. Was ich habe ist nochmal invertiert. Weiterhin wird 
in deinem Source nur dekodiert soweit ich das überblicken konnte, aber 
nicht kodiert.
Auch die Übertragung und das Funkprotokoll ist anders.

Vielleicht hilft mir das später mal weiter, aber nicht für das aktuelle 
Projekt.

Trotzdem danke for den Source.

Micha

Autor: Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha R. schrieb:
> Im Speziellen ist die Windrichtung nach dem
> Grey-Code kodiert. Was ich habe ist nochmal invertiert

Ist das für dich wirklich so ein unüberwindliches Problem?

Georg

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.