Forum: Mikrocontroller und Digitale Elektronik Windrichtungsanzeige auswerten


von pascalts (Gast)


Lesenswert?

Moin!

Ich habe seit einiger Zeit ein kleines privates Wetterstationsprojekt, 
wie es so viele gibt. Die meisten der Daten kann ich einfach und gut 
auslesen (Temperatur, Feuchte, Luftdruck, Wind, Böen, ...), derzeit 
scheitere ich jedoch am Windrichtungs"messer".

Kurz zum Aufbau: Im rotierenden Teil des Windrichtungsmessers befindet 
sich ein Neodymmagnet, welcher 8 Reedschalter betätigt. Zu 99,99% ist 
nur ein Reedschalter betätigt.

Die Reedschalter werden mit VCC versorgt, in Serie ist je ein anderer R 
geschaltet.

Richtung: R_M

N:  33  kOhm
NO:  64,8  kOhm
O:  120  kOhm
SO:  16  kOhm
S:  3,9  kOhm
SW:  2,21  kOhm
W:  1  kOhm
NW:  8,15  kOhm

Ich habe diese Widerstände mittels eines Spannungsteilers mit einem 9k1 
Ohm R auf GND gelegt.

VCC
 |
[R_M]
 |
 |------ Analog In
 |
[R2]
|
GND

Der Analog-Input ist ein 12bit ADC, also 0 bis 4095. Das funktioniert 
soweit gut - ich bekomme Messwerte, die ich einer Richtung zuordnen 
kann. Nun wackelt der Windrichtungsmesser aber wie der Schwanz eines 
freudigen Hundes, innerhalb von 1 Sekunde habe ich also gern mal von SW 
über W bis NW alles abgedeckt an Werten. Wie stelle ich am schlausten 
eine Auswertung an, damit ich sagen kann: In den letzten X Minuten wehte 
der Wind vorrangig aus Richtung XZY?

PS: Ich bin mit einem ESP32 + Arduino-IDE unterwegs. Gute 
Programmierkenntnisse vorhanden, wenn auch eher aus anderen 
(objektorientierten) Sprachen.

Gruß

Pascal

von my2ct (Gast)


Lesenswert?

pascalts schrieb:
> Wie stelle ich am schlausten
> eine Auswertung an, damit ich sagen kann: In den letzten X Minuten wehte
> der Wind vorrangig aus Richtung XZY?

Du könntest einen gleitenden Mittelwert über X Minuten rechnen.
Das war einfach.

von blue2monster (Gast)


Lesenswert?

Wenn du dir auf jeden Eingangs-Pin nen Interrupt legst.
Dann bei Änderung die Zeit misst seit dem letzten Interrupt


Zeit_seit letzter Änderung = millis() - letzteWindänderung;
letzteWindänderung = millis();

und das dann in ein Array mit x Einträgen schreibst
Dann hast suchst du in dem Array nach den Einträgen mit der größten 
Dauer.
Und damit hast du die vorherschende Windrichtung.

Kombinieren kannst du das beim ESP32 mit einem Deep-Sleep: Wake aus 
Interrupt bei Pin Change.

Und schon braucht dein ESP deutlich weniger Strom

von HildeK (Gast)


Lesenswert?

my2ct schrieb:
> Du könntest einen gleitenden Mittelwert über X Minuten rechnen.

Oder ein Medianfilter verwenden. n Werte in einem Array ablegen, 
sortieren und der am häufigsten vorkommende Wert liegt dann in der 
Mitte.
Die gemessenen Werte würde ich in einen Ringpuffer schreiben, den dann 
in ein zweites Array sortieren und dort auswerten.

von Peter O. (peter_o)


Lesenswert?

Hallo,
wie wäre es denn, wenn du das Signal erstmal über ein RC-Glieg 
"glättest"? Am Ausgang von deinem Spannungsteiler einen 10 KOhm 
Widerstand und danach einen größeren Kondensator (> 100 µF) gegen GND. 
Die Spannung an dem Kondensator dann an deinen Analogeingang. Dann hast 
du allerdings keine Spannungsstufen mehr, sondern ein stufenlosen 
Verlauf. Je größer der Kondensator, desto träger wird die Anzeige.

von my2ct (Gast)


Lesenswert?

HildeK schrieb:
> Die gemessenen Werte würde ich in einen Ringpuffer schreiben, den dann
> in ein zweites Array sortieren und dort auswerten.

Ein gleitender Mittelwert ist da deutlich pflegeleichter. Ein zweites 
Array und das Sortieren kann man sich sparen und die Auswertung 
beschränkt sich auf das Addieren von 3 Werten und teilen durch die 
Anzahl der Messwerte.

von my2ct (Gast)


Lesenswert?

Peter O. schrieb:
> wie wäre es denn, wenn du das Signal erstmal über ein RC-Glieg
> "glättest"?

Damit bekommt man aber nicht den Mittelwert der letzten X Minuten, weil 
die Sprungantwort des Filters dafür sorgt, das alte Messwerte mit 
geringerem Gewicht in das Ergebnis eingehen, als neue.

von Jefe (Gast)


Lesenswert?

Üblich sind 2-min-Mittel und 10-min-Mittel. Jeweils gleitend.

von HildeK (Gast)


Lesenswert?

my2ct schrieb:
> Ein gleitender Mittelwert ist da deutlich pflegeleichter.
Pflegeleicht ist beides. Und Sortieren ist auf einem µC kein Act.

Das Problem ist jedoch, dass die gemessenen Pegel nicht einen linearen 
Zusammenhang haben entlang der Rosette. Und selbst wenn, spätestens beim 
Ringschluss des Kreises gibt es dann einen Sprung. Da einen Mittelwert 
nehmen führt doch zu beliebigen Ergebnissen.
So würde mit den oben genannten Zahlen z.B. ein Pendeln zwischen SO und 
O im Mittel den Wert für Nord ergeben, der zwischen W und NW dann Süd 
anzeigen ...
Deshalb geht m.E. auch der Vorschlag von Peter O. nicht, es ist ja das 
selbe im analogen Bereich.

Mit dem Medianfilter können die Schwankungen wie genannt im Lauf der 
Abtastperiode herein kommen - also, wie genannt: "SW über W nach NW". 
Der, der am häufigsten vorkommt liegt dann im Array in der Mitte, 
zumindest solange die Rosette nicht nur im kompletten Kreis rotiert.

Vielleicht liege ich auch falsch und noch besser wäre es, die im 
(gleitenden) Array auftretenden (evtl. klassifizierten) Werte aus einer 
Mehrheitsentscheidung als Ergebnis zu nehmen.
Klassifizieren deshalb, weil der ADC ja auch schon bestenfalls um nur 
einige LSB schwankende Werte liefert und man nur 8 Richtungen 
unterscheiden muss.

So ganz trivial ist das Problem nicht.

von Zombie (Gast)


Lesenswert?

So ein Filter habe ich mal in C++ realisiert, muss mal suchen.

Ein mögliche Lösung wäre: Winkel in komplexe Zahl wandeln, komplexe Zahl 
filtern, komplexe Zahl wieder in Winkel zurückwandeln.

von HildeK (Gast)


Lesenswert?

HildeK schrieb:
> Mit dem Medianfilter können die Schwankungen wie genannt im Lauf der
> Abtastperiode herein kommen - also, wie genannt: "SW über W nach NW".
> Der, der am häufigsten vorkommt liegt dann im Array in der Mitte,
> zumindest solange die Rosette nicht nur im kompletten Kreis rotiert.

Ich muss mich korrigieren. Das geht auch nicht.
Es bleibt nur die Mehrheitsentscheidung aus n klassifizierten 
Messwerten.

von Udo S. (urschmitt)


Lesenswert?

Es wäre eventuell zu klären, warum der Windmesser so schnell 
unterschiedliche Richtungen anzeigt.
Wenn er in einem Verwirbelungsfeld irgendwelcher Gebäude(teile) 
positioniert ist, dann kann man sich den ganzen Aufwand sparen, denn 
dann zeigt er nur beliebig falsch an.

von Michael K. (michael_kpunkt)


Lesenswert?

Hallo,

ich stelle mal folgenden Vorschlag zur Diskussion:
Für jede der acht Richtungen gibt es eine Variable. Der Analogwert wird 
in einem festen Zeitraster ermittelt und mit etwas Toleranz einer 
Richtung zugeordnet. Nach jeder Messung wird jeder nicht passenden 
Richtungsvariablen -1 und der passenden 7 addiert. Bei der Addition 
werden Min-/ Maxgrenzen berücksichtigt.

Die Richtungsvariable mit dem grössten Wert entspricht der 
vorherrschenden Windrichtung. Mit dieser Methode ergibt sich ein 
kontinuierliches Ergebnis. Durch die Grösse der Grenzen kann man noch 
eine gewisse Dämpfung einstellen.

Evtl. sollte auch noch die Windgeschwindigkeit berücksichtigt werden. 
Denn gerade bei sehr schwachem Wind wedelt die Wetterfahne stärker. In 
diesem Fall ist es u.U. besser zum Ergebnis "kein Wind aus keiner 
Richtung" zu kommen, als aus "kein Wind aus Nord".

Gruss Micha

von HildeK (Gast)


Lesenswert?

Michael K. schrieb:
> Nach jeder Messung wird jeder nicht passenden
> Richtungsvariablen -1 und der passenden 7 addiert. Bei der Addition
> werden Min-/ Maxgrenzen berücksichtigt.

Wie unterscheidest du 'passend' und 'nicht passend'?
Wenn du das schon weißt, brauchst du nichts mehr auswerten, oder?

von Michael K. (michael_kpunkt)


Lesenswert?

HildeK schrieb:
> Michael K. schrieb:
>> Nach jeder Messung wird jeder nicht passenden
>> Richtungsvariablen -1 und der passenden 7 addiert. Bei der Addition
>> werden Min-/ Maxgrenzen berücksichtigt.
>
> Wie unterscheidest du 'passend' und 'nicht passend'?
> Wenn du das schon weißt, brauchst du nichts mehr auswerten, oder?

Es gibt acht Richtungsvariablen, je eine für N, NO, O, ... NW und eine 
ermittelte Richtung aus dem Analogwert, also eine von acht. Die 
ermittelte Richtung wirkt auf die "passende" die anderen sind die "nicht 
passenden". Bei jeder Messung kann eine andere Richtung die "passende" 
sein. Durch die wiederholte, beschriebene Addition sollte die 
Richtungsvariable aus der der Wind am Häufigsten kam, den grössten Wert 
haben.

Ich hoffe nun ist es verständlicher.

Gruss Micha

von HildeK (Gast)


Lesenswert?

Michael K. schrieb:
> Ich hoffe nun ist es verständlicher.

Ja, ok, danke.
Mit der zulässigen Maximalgrenze stellst du dann quasi die 
Filterfrequenz ein. Hört sich gut an.
Mein Vorschlag mit 'Mehrheitsentscheidung' ist ähnlich, aber 
ungefiltert.

von my2ct (Gast)


Lesenswert?

HildeK schrieb:
> Das Problem ist jedoch, dass die gemessenen Pegel nicht einen linearen
> Zusammenhang haben entlang der Rosette. Und selbst wenn, spätestens beim
> Ringschluss des Kreises gibt es dann einen Sprung. Da einen Mittelwert
> nehmen führt doch zu beliebigen Ergebnissen.

Was meinst du mit keinem linearen Zusammenhang?
Die Verteilung muss doch symmetrisch sein und dann gibt es auch kein 
Problem beim Mitteln.

Um Problemen mit dem Ringschluss aus dem Weg zu gehen, sollte man die 
Messwerte tunlichst so verschieben, dass sie nicht um den 360°-0° Spung 
liegen, i.e. die Modulo-360° raus nehmen. Dann klappt das auch mit der 
Mittelung.

von HildeK (Gast)


Lesenswert?

my2ct schrieb:
> Was meinst du mit keinem linearen Zusammenhang?

War falsch ausgedrückt: hätte stetig heißen sollen. Das ist aber bei den 
o.g. Werten schon mal nicht so. Ich weiß nicht, ob er das anpassen 
könnte.
Wie du den Sprung rausnehmen willst bei 0°/360° verstehe ich nicht ...

von STK500-Besitzer (Gast)


Lesenswert?

Vielleict beschreibe ich ein schon genanntes Verfahren:
Es sind acht Readsensoren vorhanden, also maximal 16 Werte (Magnet löst 
zwei Sensoren aus).
Deren Auftreten könnte man doch in einem Array[16] über eine gewisse 
Zeit summieren.
Nach Ablauf der Zeit wird nach dem größten Wert gesucht, die Richtung 
"gemerkt" und das Array wieder "geleert", damit eine neue Runde beginnen 
kann.

von Wolfgang (Gast)


Lesenswert?

HildeK schrieb:
> Wie du den Sprung rausnehmen willst bei 0°/360° verstehe ich nicht ...

Wenn der Wind z.B. grob aus Nord kommt, kannst du vor der 
Mittelwertbildung zu allen Werten, die kleiner als 180° sind, 360° dazu 
zählen.

Die andere Möglichkeit ist die Winkel als Sinus- und Cosinusanteil 
darzustellen. Dann gibt es keinen Sprung.

von c-hater (Gast)


Lesenswert?

pascalts schrieb:

> Zu 99,99% ist
> nur ein Reedschalter betätigt.

Schon Scheiße. Wenn der Wind mal konstant aus einer ungünstigen Richtung 
weht, könnten aus den verbleibenden 0,01% auch schnell mal 100% (über 
den betrachteten Zeitraum) werden. Das sollte doch eigentlich klar sein, 
oder?

Sprich: wenn die prinzielle Möglichkeit besteht, dass zwei Kontakte 
gleichzeitig betätigt werden, muss man das bereits im Design einplanen.

Außerdem ist da noch das Problem, dass es sich letztlich um einen 
"zyklischen" Messwert handelt. Auch hier ist man sehr gut beraten, das 
Problem schon beim Schaltungsdesign einzuplanen.

Sprich: du hast die Widerstände denkbarst ungünstig bezüglich der 
Anwendung dimensioniert...

Damit bekommst du niemals eine vernünftige Auswertung hin. Nichtmal ich 
könnte das, gegen die Gesetze der Informatik kann auch ich nämlich nicht 
anstinken, das sind Naturgesetze...

Der Trick ist also, sich die beiden Probleme klarzumachen, das Konzept 
zu deren Behebung zu finden und die Widerstände entsprechend dieser 
Lösung zu dimensionieren. Dann wird eine "zeitberuhigte" Auswertung 
wirklich mit jeden stinknormalen Tiefpaß möglich.

von Jacko (Gast)


Lesenswert?

Vor 40...50 Jahren gab es schon Bauvorschläge für eine
"elektronische Wetterfahne". Keine Ahnung mehr, ob es in der
"Funkschau", oder "Elektor" war.

Eine derart blöde Erfassung mit Reedrelais war damals schon
indiskutabel. Das geschah optisch mit Codierung im Gray-Code.

Wikipedia über den Gray-Code: "Seine Besonderheit besteht darin,
dass sich benachbarte Werte um nur ein Bit unterscheiden. Der Vorteil
ist, dass kleine Ungenauigkeiten beim Auslesen nicht direkt zu
Fehlinformationen führen!" Übergangszustände führen auch nicht zu
groben Fehlerfassungen, ...
... Was wohl das Hauptproblem der Reed-Relais-Lösung sein wird.

Mit 6 Leitungen erreicht man dabei eine Unterteilung des
Kreises in 16 * 22,5°. statt 8 * 45° mit 9 Leitungen.
Also nicht nur N-NO-O-..., sondern N-NNO-NO-ONO-O-...

von pascalts (Gast)


Lesenswert?

Moin!

Oh wow, mit sooo vielen Ideen hatte ich nicht gerechnet, Ich versuche 
mal allen gerecht zuwerden.

@my2ct , @Jefe
Ja, Mittelwert habe ich bereits bedacht. Aber unglücklicherweise könnte 
ich dann aus einer Mischung aus O und S auf einen Wert nahe NO (korrekt) 
und SO (falsch) kommen. Bin ich persönlich noch nicht glücklich mit.

@blue2monster
Leider ist nich jeder Pin nach außen geführt. Sonst hätte ich das 
bereits so gemacht. Ich habe nur 2 Pins und "dazwischen" einen sich 
ändernden Widerstand.

@HildeK
Ein Medianfilter klingt gut. Ist als mögliche Lösung akzeptiert und 
sammelt auch die 0,0001% Fehlmessung raus.

@peter_o
Möglich, ein zusätzliches RC-Glied hatte ich bisher nicht bedacht, würde 
ich aber zurückstellen, da es neuen Hardware-Aufwand gibt.

@urschmidt
Das "wedeln" liegt höchstwahrscheinlich an meinem Budget. Der 
Windrichtungsmesser kam für wenig Geld aus Asien (ich bin halt Student, 
Zeit ist eher vorhanden als Geld und was lernen will ich auch). Er 
befindet sich ca 1,5 m Über einem Dach einer Scheune, die im Umkreis von 
50 bis 100m das höchste Gebäude ist. Höher ginge, wäre aber mit Aufwand 
verbunden.

@michael_kpunkt
Das gefällt mir auch und kommt zusammen mit dem Vorschlag von @HildeK am 
meisten.

@c-hater
"Sprich: du hast die Widerstände denkbarst ungünstig bezüglich der
Anwendung dimensioniert..." --> Ich hab die nicht dimensioniert, sondern 
"wie die Katze im Sack" gekauft. Aber ja, ist unglücklich. Jetzt muss 
ich aber damit leben.

Ich werde mich die Tage mal an ein paar Lösungsansätze setzen und dann 
berichten. Erstmal vielen Dank an alle die hier beigetragen haben, ihr 
habt mir wirklich weitergeholfen.

Gruß Pascal

von HildeK (Gast)


Lesenswert?

pascalts schrieb:
> @HildeK
> Ein Medianfilter klingt gut. Ist als mögliche Lösung akzeptiert und
> sammelt auch die 0,0001% Fehlmessung raus.

Nein, das geht leider nicht, ich hatte es ja schon verworfen.
Bei deinem genannten Beispiel passt es, bei Windrichtung Ost mit Pendeln 
zwischen NO und SO leider nicht. Da käme dann NO heraus.
Probiere die Variante von Michael K., mir erscheint diese als 
erfolgversprechend.

von pascalts (Gast)


Lesenswert?

Das muss ich überlesen haben, danke.

Ich werde jetzt ein Array mit int 16 Feldern bauen und jeweils im 
Messzeitraum um 1 Hochzählen, wenn ich einen Messwer einem Feld zuordnen 
kann. Dann muss ich nur noch auswerten, welche Feld den höchsten Wert 
pro Messzeitraum hat und weiß die vorherrschende Windrichtung.

Danke!

von Georg (Gast)


Lesenswert?

pascalts schrieb:
> welche Feld den höchsten Wert
> pro Messzeitraum hat und weiß die vorherrschende Windrichtung.

Wasserdicht ist das auch nicht. Z.B. kann der Wert ständig zwischen NO 
und NW pendeln, ohne dass der Wert N besonders oft vorkommt. Das lässt 
sich nur mit einem Algorithmus auswerten, der "weiss" dass N zwischen NO 
und NW liegt.

Georg

von pascalts (Gast)


Lesenswert?

So, ich habe mal gebastelt.

unsigned int richtung[8]  habe ich nur 8 Felder gegeben, damit ich die 
Fehlmessung "es sind 2 Reedkontakte geschlossen" gleich ausschließe.
1
void richtungLoggen() {
2
  unsigned int mess = analogRead(RICHTUNGPIN);
3
  
4
  if ((110 < mess) and ( mess < 170)) { richtung[0]+=1; }   //ca 140
5
  if ((220 < mess) and ( mess < 280)) { richtung[1]+=1; }   //ca 250
6
  if ((360 < mess) and ( mess < 420)) { richtung[2]+=1; }   //ca 390
7
  if ((610 < mess) and ( mess < 670)) { richtung[3]+=1; }   //ca 640
8
  if ((1000 < mess) and ( mess < 1100)) { richtung[4]+=1; } //ca 1050
9
  if ((1700 < mess) and ( mess < 1800)) { richtung[5]+=1; } //ca 1750
10
  if ((2350 < mess) and ( mess < 2500)) { richtung[6]+=1; } //ca 2400
11
  if ((2800 < mess) and ( mess < 3200)) { richtung[7]+=1; } //ca 3000
12
}
13
14
int getRichtung() {
15
  int maxNr = 0;
16
  int maxWert = 0;
17
  // höchsten Wert ermitteln
18
  for (int i = 0; i<=7; i++) {
19
    if (richtung[i]>maxWert) {
20
      maxWert = richtung[i];
21
      maxNr = i;
22
    }
23
  }
24
  
25
  // Array zurücksetzen
26
  for (int i = 0; i<=7; i++) {
27
    richtung[i] = 0;
28
  }
29
  
30
  return maxNr;
31
}

Die Funktion richtungLoggen() wird zyklisch aufgerufen. Die Werte habe 
ich experimentell ermittelt.

Die Funktion getRichtung() verwende ich beim Übermitteln der Daten. Sie 
gibt nur den Array-Index aus, die weitere Zuordnung mach dann mein 
Frontend.

Ich schaue mal, wie sich die Funktionen bewähren und melde mich dann.

Gruß

Pascal

von pascalts (Gast)


Lesenswert?

Ich muss hier nochmal kurz was anmerken. Klar weiß ich, dass die 
Auswertung noch hinkt. Es könnte richtung[3] und [4] gleich groß sein. 
Woher soll die Funktion dann wissen, was relevanter ist? Es nimmt halt 
den ersten Wert.

Bis mir was besseres eingefallen ist, muss ich aber wohl damit leben.

von HildeK (Gast)


Lesenswert?

pascalts schrieb:
> Ich schaue mal, wie sich die Funktionen bewähren und melde mich dann.

Ja, wäre schön.

Nach dem Vorschlag von Michael K. wäre diese Variante evtl. auch noch 
interessant:
1
  if ((110 < mess) and ( mess < 170)) 
2
  { richtung[0] += 7; } 
3
  else 
4
  { richtung[0] -= 1; }  
5
6
  if ((220 < mess) and ( mess < 280)) 
7
  { richtung[1] += 7; } 
8
  else
9
  { richtung[1] -= 1; }  
10
11
// und so weiter
Du musst dann noch richtung[i] auch nach unten begrenzen.
Je nach Höhe des Begrenzungswerts nach oben sollte eine mehr oder 
weniger starke Filterung bewirken, ebenso wie die Höhe des Inkrements. 
Den Wert 7 fürs Inkrement hatte Michael genannt, mir kommt er eher etwas 
groß vor. Muss man einfach testen ...
Und wenn die Zahlen zweier nebeneinander liegender Windrichtungen 
ähnlich hoch sind (delta < x), dann kannst du das auch als Richtung 
dazwischen einschätzen.

BTW: ich würde mit der Feldreihenfolge von 'richtung' der Reihenfolge 
auf der Rosette folgen. Die Messwerte tun es ja nicht.

pascalts schrieb:
> Ich werde jetzt ein Array mit int 16 Feldern bauen

Warum 16 Felder? Du hast doch nur 8 Kontakte?

von pascalts (Gast)


Lesenswert?

HildeK schrieb:
> Warum 16 Felder? Du hast doch nur 8 Kontakte?

16 Felder deshalb, weil es eine mehr theoretische als praktische Change 
gibt, dass der Magnet 2 Reedkontakte erwischt. Dann hätte man noch 8 
"Zwischenwerte".

Hier ein Link zum Sensor: 
https://de.aliexpress.com/item/1000001854801.html?spm=a2g0s.9042311.0.0.4fc54c4dUwbcO2
1
---------------------------------- (VCC)
2
  |   |   |   |   |   |   |   | 
3
  |   |   |   |   |   |   |   | 
4
 [Ra][Rb][Rc][Rd][Re][Rf][Rg][Rh]
5
  |   |   |   |   |   |   |   | 
6
  |   |   |   |   |   |   |   | 
7
   /   /   /   /   /   /   /   /   (Schalter / Reed a bis h)
8
  |   |   |   |   |   |   |   | 
9
  |   |   |   |   |   |   |   | 
10
---------------------------------- (zu analog in)
11
  |
12
  |
13
 [R2]
14
  |
15
  |
16
---------------------------------- (GND)

Die bisherigen Daten sehen wesentlich konstanter aus, obwohl ich bisher 
keine Wichtung ala +7 -1 vornehme.

Die Windrichtung deckt sich mit der privaten Wetterstation nicht weit 
von mir.

Die nächsten 24 Stunden lasse ich mal ohne Wichtung durchlaufen, danach 
mit (vielleicht +3 oder so). Mal sehen wie sich das entwickelt.

Gruß Pascal

von Michael D. (Firma: indEAS) (indeas)


Lesenswert?

Ich würde es nicht so kompliziert machen. Nimm doch einen 
MLX90242ESE-GAA-000-SP gleich programmiert mit Analogausgang (1,65€ bei 
Mouser). Dazu noch einen PM im Drehpunkt und fertig. Filterung 
elektronisch über RC am Analogausgang.

von HildeK (Gast)


Lesenswert?

pascalts schrieb:
> 16 Felder deshalb, weil es eine mehr theoretische als praktische Change
> gibt, dass der Magnet 2 Reedkontakte erwischt. Dann hätte man noch 8
> "Zwischenwerte".

Da das nach deiner Beschreibung ganz oben nur mit sehr geringer 
Wahrscheinlichkeit auftreten kann, wird der Wert auch kaum vorkommen. Du 
hast z.B. knapp 45° Drehbereich in dem ein stabil geschlossenen 
Kontakt vorhanden ist, aber evtl. nur 1° wenn zwei geschlossen sind. 
Heißt: dein Richtungszähler wird kaum hoch zählen und du hast kaum eine 
Chance, den als häufigsten zu finden. Es muss dann schon Windstill sein 
und die Rosette exakt auf dem Zwischenwert stehen - aber dann gibt es 
sowieso keine Windrichtung 😀. Daher glaube ich, dass du darauf 
verzichten kannst.

Ich würde eher die Grenzen um Werte für einen geschlossenen Kontakt 
etwas enger ziehen, so dass der Wert, den zwei nebeneinander liegende 
gleichzeitig geschlossene Kontakte liefern, ignoriert wird.

Zwischenwerte sind auch erreichbar, wenn zwei nebeneinander liegende 
Windrichtungen ähnlich häufig auftreten, also im Feld dazu den größten 
und den zweitgrößten Wert suchen. Wenn sie ähnlich hoch sind, dann kann 
man auf die Richtung dazwischen schließen.

von pascalts (Gast)


Lesenswert?

Ich glaube du missverstehst mich. Ich habe mich bereits gegen die 16 
Felder entschieden. Ich nutze 8, siehe: 
Beitrag "Re: Windrichtungsanzeige auswerten" : "unsigned int 
richtung[8]  habe ich nur 8 Felder gegeben, damit ich die Fehlmessung 
"es sind 2 Reedkontakte geschlossen" gleich ausschließe."

Derzeit "unsigned int richtung[8]", weil ich nur "+1" mache, wenn ich 
später mit Wertung ála +3 & -1 arbeite natürlich "int richtung[8]".

Gruß

Pascal

von pascalts (Gast)


Lesenswert?

Okay, ich hab jetzt zwar Windstille im Moment, aber trotzdem mal die 
Variante mit Gewichtung noch ausprobiert. Das Ergebnis ist noch 
eindeutiger.
1
void richtungLoggen() {
2
  unsigned int mess = analogRead(RICHTUNGPIN);
3
  
4
  if ((110 < mess) and ( mess < 170)) { richtung[0]+=3; } else { richtung[0]-=1; }  //ca 140
5
  if ((220 < mess) and ( mess < 280)) { richtung[1]+=3; } else { richtung[1]-=1; }  //ca 250
6
  if ((360 < mess) and ( mess < 420)) { richtung[2]+=3; } else { richtung[2]-=1; }  //ca 390
7
  if ((610 < mess) and ( mess < 670)) { richtung[3]+=3; } else { richtung[3]-=1; }  //ca 640
8
  if ((1000 < mess) and ( mess < 1100)) { richtung[4]+=3; } else { richtung[4]-=1; }//ca 1050
9
  if ((1700 < mess) and ( mess < 1800)) { richtung[5]+=3; } else { richtung[5]-=1; }//ca 1750
10
  if ((2350 < mess) and ( mess < 2500)) { richtung[6]+=3; } else { richtung[6]-=1; }//ca 2400
11
  if ((2800 < mess) and ( mess < 3200)) { richtung[7]+=3; } else { richtung[7]-=1; }//ca 3000
12
}

+3 und -1 scheint ein guter Ansatz zu sein.

Dann sieht es schnell so aus:
1
0: -17
2
1: -17
3
2: -17
4
3: -17
5
4: -17
6
5: 51
7
6: -17
8
7: -17

Also wunderbar eindeutig, auch wenn der Richtungsgeber gerade nicht 
"herumschwänzelt". Ich schreibe morgen nochmal, wenn wir wieder Wind 
haben ;-)

Gruß Pascal

von HildeK (Gast)


Lesenswert?

pascalts schrieb:
> Also wunderbar eindeutig, auch wenn der Richtungsgeber gerade nicht
> "herumschwänzelt". Ich schreibe morgen nochmal, wenn wir wieder Wind
> haben ;-)
Ja klar, perfekt eindeutig wäre es auch ohne die +3/-1, das ist der 
Idealfall ohne 'Schwänzeln', interessant ist es mit 'Schwänzeln'!
Ich bin gespannt.

von ek13 (Gast)


Lesenswert?

pascalts schrieb:
> Kurz zum Aufbau: Im rotierenden Teil des Windrichtungsmessers befindet
> sich ein Neodymmagnet, welcher 8 Reedschalter betätigt.

 Zu 99,99% ist
> nur ein Reedschalter betätigt

Wie machen die das?
Kann ich mir nicht vorstellen.

von foobar (Gast)


Lesenswert?

> +3 und -1 scheint ein guter Ansatz zu sein.

Was soll das bringen?  Den aktuellen +3 und alle anderen -1 ist das 
gleiche, wie den aktuellen +4 und alle anderen +-0.  Du zählst also nur 
um 4 statt um 1 hoch - das ist alles.

von foobar (Gast)


Lesenswert?

Sortier das Richtungs-Array doch so, dass die Richtungen von Index n und 
n+1 benachbart sind (45° auseinander) und glätte dann die Werte, z.B.:
1
   for (int i = 0; i<8; i++) {
2
    int glatt = richtung[(i+7)%8] + 2 * richtung[i] + richtung[(i+1)%8];
3
    if (glatt > maxWert) {
4
      maxWert = glatt;
5
      maxNr = i;
6
    }
7
  }

von pascalts (Gast)


Lesenswert?

Vielen Dank für die weiteren guten Ansätze, ich muss euch aber vorerst 
vertrösten, da ich aus Zeit- und Windmangel noch etwas warten muss.

von Achim M. (minifloat)


Lesenswert?

c-hater schrieb:
> Außerdem ist da noch das Problem, dass es sich letztlich um einen
> "zyklischen" Messwert handelt.

Nö, ist kein Problem. Wenn man weiß wie ein Filter zu programmieren ist, 
welches diese Zyklizität berücksichtigt. Kann ich ein Beispiel posten, 
suche es heute Abend noch raus.

pascalts schrieb:
> Ja, Mittelwert habe ich bereits bedacht. Aber unglücklicherweise könnte
> ich dann aus einer Mischung aus O und S auf einen Wert nahe NO (korrekt)
> und SO (falsch) kommen.

Wenn O und S perfekt im Wechsel kommen, wäre doch SO korrekt? Verstehe 
ich jetzt nicht. Oder liegt das an deinem Spannungsteiler?

mfg mf

von Jacko (Gast)


Lesenswert?

Na ist ja beruhigend, dass die Fehlkonstruktion wenigstens bei
Windstille funktioniert.

Viel Spaß noch!

von pascalts (Gast)


Angehängte Dateien:

Lesenswert?

Achim M. schrieb:
> Wenn O und S perfekt im Wechsel kommen, wäre doch SO korrekt? Verstehe
> ich jetzt nicht. Oder liegt das an deinem Spannungsteiler?

Okay, ich versuche es mal grafisch auszudrucken. Im Anhang ein Diagramm, 
die Punkte stellen die Widerstände dar.

45 Grad hat 64,8 kOhm.
90 Grad hat 120 kOhm.
135 Grad hat 16 kOhm.

Angenommen Wir pendeln dauerhaft zwische 135 Grad und 90 Grad, summieren 
den analogRead()-Wert auf und teilen durch die Anzahl der Messerte. Dann 
ist es durchaus möglich, dass wir als Durchschnittswert auf den für 64,8 
kOhm entsprechenden Integer kommen.

Verstehst du nun, warum dies nicht möglich ist?

von sohalt@gmx.de (Gast)


Lesenswert?

änder doch die Widerstände an den Reedschaltern

von HildeK (Gast)


Lesenswert?

foobar schrieb:
> Was soll das bringen?  Den aktuellen +3 und alle anderen -1 ist das
> gleiche, wie den aktuellen +4 und alle anderen +-0.  Du zählst also nur
> um 4 statt um 1 hoch - das ist alles.

Ob sich das gleich verhält, hängt davon ab, wie die Auswertung läuft.
Weit oben, als diese Variante vorgeschlagen wurde, hat man auch gesagt, 
dass man den Zähler auf einen MAX_WERT und einen MIN_WERT begrenzt. Den 
Zähler muss man dann nicht rücksetzen, sondern einfach weiter laufen 
lassen.
Wenn aus der Vergangenheit ein Wert hoch ist oder auf MAX_WERT steht, 
dann würden die anderen, die ggf. gelegentlich auch mal aufwärts zählen 
('schwänzeln') auch langsam aber sicher dem MAX_WERT näher kommen - nach 
deiner Methode.

Subtrahiert man aber bei den anderen einen Wert, dann wird bei einer 
neuen Windrichtung der alte Spitzenwert langsam kleiner und der neue 
steigt schnell an. So ergibt sich ein weicher Übergang auf die neue 
Richtung.

von HildeK (Gast)


Lesenswert?

sohalt@gmx.de schrieb:
> änder doch die Widerstände an den Reedschaltern

Ich habe es nicht nachgerechnet, aber sie scheinen mir durchaus sinnvoll 
gewählt worden zu sein. Denn so kann man tatsächlich unterscheiden, wenn 
zwei nebeneinander liegende Reedkontakt geschlossen sind. Das ergibt 
dann immer einen Spannungswert, der zwischen den Spannungen liegt wenn 
nur ein geschlossener Kontakt vorhanden ist. Dann kann man durch 
sinnvolles engeres Wählen der Messgrenzen (z.B. hier: if ((110 < mess) 
and ( mess < 170)) ) diese Zwischenwerte ausblenden.

von ek13 (Gast)


Angehängte Dateien:

Lesenswert?

c-hater schrieb:
> pascalts schrieb:
>
>> Zu 99,99% ist
>> nur ein Reedschalter betätigt.
>
> Schon Scheiße. Wenn der Wind mal konstant aus einer ungünstigen Richtung
> weht, könnten aus den verbleibenden 0,01% auch schnell mal 100% (über
> den betrachteten Zeitraum) werden. Das sollte doch eigentlich klar sein,
> oder?

genau!
hier mal die Widerstandwerte bei 360° Drehung im Vergleich wenn 2 Reed's 
aktiv sind.

von Graph Læser (Gast)


Lesenswert?

Warum zeichnet ihr Graphen mit kontinuierlichen Linien?
Das ist kein Poti!
Das suggeriert dass f. Werte zw. Rmin und Rmax IMMER 2 Himmelsrichtungen 
abzulesen wären.
Auf Grund der geschalteten Reed-Kontakte trifft das aber nicht zu.
Es gibt nur Messbereiche von Rx+/-(Toleranz, Messfehler), jedoch nie 
Zwischenwerte.

von Achim M. (minifloat)


Lesenswert?

sohalt@gmx.de schrieb:
> änder doch die Widerstände an den Reedschaltern

Wie wäre es mit einem Prinzip ähnlich dem Kelvin-Varley-Divider? Also 
sowas meine ich:
1
VCC
2
 |
3
 1k
4
 +---Sw1--,
5
 1k       |
6
 +---Sw2--*
7
 1k       |  
8
 +---Sw3--*
9
 1k       |
10
 +---Sw4--*
11
 1k       |
12
 +---Sw5--*
13
 1k       |
14
 +---Sw6--*
15
 1k       |
16
 +---Sw7--*
17
 1k       |
18
 +---Sw8--*---ADC
19
 |        |
20
 +--100k--'
21
 |
22
GND

"Sw" jeweils ein Reedschalter.
Leider hat der eine Präferenz für den untersten "Sw8":
# Sw1 und Sw8 gleichzeitig = 0V
# Sw7 und Sw8 gleichzeitig = 0V
# Sw8 allein = 0V
Sonst aber kommt eine Spannung proportional zum Winkel raus.

mfg mf

: Bearbeitet durch User
von Detlef _. (detlef_a)


Lesenswert?

War schon gesagt, komplexe Zahlen mitteln, dann ist man die 'wrap' 
Problematik los.
>>>>>>>>>>>>>>
Ein mögliche Lösung wäre: Winkel in komplexe Zahl wandeln, komplexe Zahl
filtern, komplexe Zahl wieder in Winkel zurückwandeln.
<<<<<<

Norden =   0 + j
Nordosten  1/sqrt(2)+ j*1/sqrt(2)
Osten = 1 + 0*j
etc.pp.

Wenn zwei Relais angezogen sind kriegt man das auch verarbeitet:
Norden und Nordosten: cos(pi/4+pi/8)+j*sin(pi/4+pi/8)

Aufsummieren im Zeitfenster, in Winkel zurückwandeln, fertig ist die 
Laube.

complex rulez!
Cheers
Detlef

von HildeK (Gast)


Lesenswert?

ek13 schrieb:
> hier mal die Widerstandwerte bei 360° Drehung im Vergleich wenn 2 Reed's
> aktiv sind.

Macht ja nichts.
In 99,99% der Fälle ist kommt das nicht vor. Und wenn es in 0,01% 
passiert, dann wird halt die davor erkannte Richtung angezeigt.

Wenn einem das zu unschön ist: deine Berechnung zeigt ja, dass man auch 
die Auswertung mit zwei geschlossenen Reedkontakten eindeutig machen 
kann: man unterscheidet einfach 16 Richtungen. Ich vermute mal, das 
Diagramm wird deutlicher, wenn man die geteilte Spannung aufträgt 
anstatt der Widerstände.

Achim M. schrieb:
> Leider hat der eine Präferenz für den untersten "Sw8":
Linear ist es, wenn nur ein Kontakt geschlossen ist. Bei zwei 
nebeneinander liegenden auch nicht mehr. Nur noch stetig, aber ist das 
wichtig? Kann man doch mappen ...

Um die Präferenz beim 8. Schalter zu umgehen, hilft da nicht noch ein 1k 
zwischen SW8 und GND?
Gibt dann halt bei 1 und 8 gleichzeitig den Wert 49.8%, etwas nah an 4+5 
mit 49%.

von Achim M. (minifloat)


Lesenswert?

HildeK schrieb:
> Gibt dann halt bei 1 und 8 gleichzeitig den Wert 49.8%, etwas nah an 4+5
> mit 49%

Genau das ist ein Problem bei der "Wrap" Problematik und sollte daher 
vermieden werden. Keiner will ein z.B. Ergebnis "Süd", wenn die Fahne 
auf Nord-Nord-West steht.

Detlef _. schrieb:
> War schon gesagt, komplexe Zahlen mitteln, dann ist man die 'wrap'
> Problematik los.

Kanonen auf Spatzen. Mit der Abbildung
  -180° ... 0° ... 179,99...° auf
-32768  ... 0  ... 32767
kann man die wrap-Eigenschaft von int16_t oder beliebigem 
integer-Zahlentyp ausnutzen. Zum Beispiel so:
1
typedef struct
2
{
3
  int32_t accu;
4
  uint8_t shift;
5
  uint8_t init;
6
} cycflt_t;
7
8
cycflt_t your_filter =
9
{
10
  0u, // int32_t accu;  init to zero; overwritten on 1st call
11
  4u, // uint8_t shift; filter tau = (2**shift) * T_cycle; e.g. 4u means 16* T_cycle
12
  0u  // uint8_t init;  non-initialized; overwritten on 1st call
13
};
14
int16_t cycflt_update(cycflt_t* this, int16_t in)
15
{
16
  int16_t diff;
17
18
  // initialized!?
19
  if(this->init == 0)
20
  {
21
    // initialize accu on first call
22
    this->init = 1u;
23
    this->accu = ((int32_t)in) << 16u;
24
  }
25
  else
26
  {
27
    // calculate summation point and update filter accu
28
    diff = in - (int16_t)(this->accu >> 16u);
29
    this->accu += ((int32_t)diff) << ((uint8_t)(16u - shift));
30
  }
31
32
  return((int16_t)(this->accu >> 16u));
33
}
34
35
// ...im laufenden code dann...
36
your_s16_output = cycflt_update(&your_filter, your_s16_input);

mfg mf

: Bearbeitet durch User
von Schlaumaier (Gast)


Lesenswert?

Wieso macht ihr das so kompliziert.

Ein Magnet und Gegengewicht an den Hahn. Die 8 Readkontakte ringförmig 
um den Hahn ausgerichtet.

Sobald ein Readkontakt auslöst weiß ich genau der Wind kommt aus Süden. 
Ist das der letzte Kontakt der Auslöst und hat der nächste NICHT aus 
gelöst weiss ich der Wind kommt aus Süden und im einen Bereich von 45° 
(Bei 8 Sensoren).

Die Drehung des Windes kann ich durch den Vergleich es letzten zum 
vorletzten Sensor ermitteln.

Und wenn ich Stromsparen will muss ich halt eine "Interrupt-Schaltung" 
machen die er Readkontakt auslöst.

Im Prinzip muss ich nur X (in den Fall 8 Schalter) abfragen. Das geht 
sogar mit einen PCF8574 am i2c Bus. ;)

Und um Daten zu sparen, protokolliere ich einfach JEDEN 
Readkontakt-Auslösung. Dann weiß ich folgendes :

1.) Zappelt der Hahn (was man mechanisch unterbinden sollte wenn der auf 
jede Fliege reagiert. Ich würde ein Kugellager nehmen das hat genug 
Eigenwiderstand.
2.) Wie hat der Wind gewechselt (Windrichtung von S -> O oder von O -> 
S)
3.) Wann ist das passiert. Kleines DCF-Modul wäre dann fein.

von Detlef _. (detlef_a)


Lesenswert?

Achim M. schrieb:
> Kanonen auf Spatzen. Mit der Abbildung
>   -180° ... 0° ... 179,99...° auf
> -32768  ... 0  ... 32767
> kann man die wrap-Eigenschaft von int16_t oder beliebigem
> integer-Zahlentyp ausnutzen. Zum Beispiel so:

Stimmt. Gute Idee. War mir in diesem Zusammenhang nicht bewußt.

Cheers
Detlef

von HildeK (Gast)


Lesenswert?

Schlaumaier schrieb:
> 1.) Zappelt der Hahn (was man mechanisch unterbinden sollte wenn der auf
> jede Fliege reagiert. Ich würde ein Kugellager nehmen das hat genug
> Eigenwiderstand.

Ja, und dass soll in der Software unterbunden werden. Und die Vorgabe 
war, der Windrichtungsmesser ist gekauft und soll nicht umgebaut werden.

Du hast erst vorhin angefangen, in diesem Thread zu lesen und dann auch 
nur 3 Beiträge von hinten?

von Wolfgang (Gast)


Lesenswert?

Detlef _. schrieb:
> etc.pp.

Nord + Ost gemittelt ergibt
1/2((0 + j) + (0 + -j)) = 0 + 0*j und nicht 1 + 0*j

von Wolfgang (Gast)


Lesenswert?

Wolfgang schrieb:
> Nord + Ost

Nord + Süd

von Achim M. (minifloat)


Lesenswert?

Schlaumaier schrieb:
> Im Prinzip muss ich nur X (in den Fall 8 Schalter) abfragen. Das geht
> sogar mit einen PCF8574 am i2c Bus. ;)

Um dann 4 Drähte an den Hahn und I2C über einige zig Meter zu führen? 
Jedem das Seine...

von Schlaumaier (Gast)


Lesenswert?

Achim M. schrieb:
> Um dann 4 Drähte an den Hahn und I2C über einige zig Meter zu führen?
> Jedem das Seine...

Quatsch. Der kommt in ein Kasten und ich führe nur die Drähte von den 
Sensoren zu den Kasten. Wenn ich das richtig mache, ist die max. Länge 
der Kabel ca. 15-20 cm.

von pascalts (Gast)


Angehängte Dateien:

Lesenswert?

Ohje, es gibt ja hier schon wieder sooo viele Nachrichten. Dabei wollte 
ich nur sagen, dass ich mit der aktuellen Lösung bereits glücklich bin. 
In der angehängten Grafik kann man meine (nicht finale!) Auswertung 
sehen.

Jetzt zu den neuen Antworten:

@minifloat:

Ich kann und möchte die Hardware nicht ändern. SMD-Löten ist nicht so 
meins. Für ein Projekt, dass man bei 0 beginnt aber eine schöne Idee.

@detlef_a

Auch wenn ich in Abi und Studium brav alles mit i und j durchgekaut 
habe, würde ich es im Moment aufgrund des KISS-Prinzips gern vermeiden.

Für mich ist das Projekt bis auf Feinarbeit erstmal abgeschlossen. Ich 
danke für die Hilfe! Die Community hier ist wirklich 1A und man bekommt 
so wahnsinnig schnell eine (gute, fundierte) Antwort wie nirgendwo.

Gruß Pascal

von Detlef _. (detlef_a)


Lesenswert?

pascalts schrieb:
> KISS-Prinzips

Komplexe Zahlen sind simpel, obwohl ihr Name Anderes vermuten läßt ;)
Alles gut, ging ja auch so.

Cheers
Detlef

von Achim M. (minifloat)


Lesenswert?

pascalts schrieb:
> Für ein Projekt, dass man bei 0 beginnt aber eine schöne Idee.

Wenn du den nichtlinearen Zusammenhang ADC-zu-Winkel auflöst (mit der 
Latte an if-Fensterung) und dann den Winkel in den zyklischen Filter 
rein wirfst, geht es doch auch, oder?

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.