Wetterstation Windrichtung kodieren und dekodieren

OP #4698207
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.
Gast #4698217
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?
OP #4698227
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.
Gast #4698244
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
OP #4698260
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.
OP #4698326
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
(Firma: matzetronics) #4698365
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
}
Gast #4698374
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.
OP #4698452
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.
Gast #4698470
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
Gast #4698491
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?
OP #4698523
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.
(Firma: matzetronics) #4698529
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.
OP #4698530
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.
Gast #4698556
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 ;-)
OP #4698574
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.
OP #4702763
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren