Forum: Mikrocontroller und Digitale Elektronik Wetterstation Windrichtung kodieren und dekodieren


von Micha R. (michaavr)


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
von Sebastian E. (Gast)


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?

von Peter II (Gast)


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?

von Micha R. (michaavr)


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
von Micha R. (michaavr)


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.

von John (Gast)


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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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.

von Ostwind (Gast)


Lesenswert?

Die Wikipedia ist doch immer wieder für Überraschungen gut:

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

von Micha R. (michaavr)


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.

von Peter II (Gast)


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?

von Micha R. (michaavr)


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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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

: Bearbeitet durch User
von Draco (Gast)


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!

von Micha R. (michaavr)


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?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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

Jep, ich nutze die Funktion von Wikpedia:
1
float gry2deg(uint16_t grey)
2
 {
3
   return 360 - (grayToBinary(grey) * 22.5f);
4
}
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
1
 
2
uint16_t gry2deg(uint16_t grey)
3
 {
4
return 3600 - (grayToBinary(grey) * 225);
5
}

: Bearbeitet durch User
von Micha R. (michaavr)


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.

von Wolfgang (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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.

von Simpel (Gast)


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...

von Wolfgang (Gast)


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

von Simpel (Gast)


Lesenswert?

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

von Micha R. (michaavr)


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.

von Draco (Gast)


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

von Wolfgang (Gast)


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?

von Micha R. (michaavr)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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.

von Micha R. (michaavr)


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.

von Stefan B. (sibbl) Benutzerseite


Lesenswert?

Um welchen Windsensor genau handelt sichs denn da?

von Wolfgang (Gast)


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 ;-)

von tmomas (Gast)


Lesenswert?

Stefan B. schrieb:
> Um welchen Windsensor genau handelt sichs denn da?

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

von Micha R. (michaavr)


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.

von Stefan B. (sibbl) Benutzerseite


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.

von Micha R. (michaavr)


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

von Stefan B. (sibbl) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hi Micha,

anbei die wichtigsten Dateien für Dein Vorhaben.

Vielleicht hilfts Dir weiter....


Gruss

von Micha R. (michaavr)


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

von Georg (Gast)


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

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.