Pages: 1 2 [3] 4 5 6   Go Down
Author Topic: Auswertung Impulse Volkswindmesser  (Read 6124 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Leute,

nachdem hier bisher sehr wenig weiter passiert ist, weil ich leider keine Zeit für das Projekt gefunden hab, nun ein neuer Anlauf.

Irgendwie bekomm ich das Kontaktprellen nicht weg, egal wie hoch in den delay pack.

Jetzt hab ich nochmal ganz rudimentär angefangen und mir direkt die Werte in der Interrupt Routine ausgeben lassen.

Hierbei sieht man, dass mein "RISING" immer genau 2 Werte kommen.

Ich habe dafür folgenden Code verwendet:

Code:
int i = 0;
unsigned long j;


void setup()
{
  Serial.begin(9600);

  attachInterrupt(0,Interrupt,RISING);
}

void Interrupt()
{

  noInterrupts();
  j = micros();
  delay(100);
  Serial.print("Wert Nr. ");
  Serial.print(i++);
  Serial.print(";");
  Serial.println(j);
  interrupts();


}


void loop()
{
  }

Dabei bekomm ich folgende Ausgabe im Serial Monitor:

Wert Nr. 0;2402216
Wert Nr. 1;2402996
Wert Nr. 2;3884176
Wert Nr. 3;3885744
Wert Nr. 4;5123992
Wert Nr. 5;5124788
Wert Nr. 6;6213224
Wert Nr. 7;6214328
Wert Nr. 8;7237460
Wert Nr. 9;7238324
Wert Nr. 10;8308352
Wert Nr. 11;8309476
Wert Nr. 12;9405480
Wert Nr. 13;9407204
Wert Nr. 14;10376576
Wert Nr. 15;10378008
Wert Nr. 16;11555068
Wert Nr. 17;11556632
Wert Nr. 18;12729400
Wert Nr. 19;12731160
Wert Nr. 20;13625240
Wert Nr. 21;13626140
Wert Nr. 22;14694512
Wert Nr. 23;14696212
Wert Nr. 24;15819660
Wert Nr. 25;15820572
Wert Nr. 26;16833956
Wert Nr. 27;16835348
Wert Nr. 28;18306752
Wert Nr. 29;18307868
usw...

Dabei beträgt der Mittelwert über alle Abstände, die sich bei 2 aufeinander direkt folgenden Impulsen ergeben: 1249,.. Mikrosekunden
Der Maximalwert beträgt: 1760 Mikrosekunden.
Der Minimalwert beträgt: 780 Mikrosekunden.

Nun habe ich auch schon versucht ein delayMicroseconds() das etwas über dem maximalwert liegt einzuführen, damit das kontaktprellen aufhört. leider ohne erfolg.

könnt ihr mir da weiterhelfen? habt ihr vielleicht noch ideen?

danke schonmal für eure antworten!
Logged

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2455
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Irgendwie bekomm ich das Kontaktprellen nicht weg, egal wie hoch in den delay pack.

Erinnerst Du Dich eigentlich an diesen Thread:
http://forum.arduino.cc/index.php?topic=156239.0
Und dort an meine "Reply #1" im Thread?
Und dort an meine "Reply #3" im Thread?

Das ist doch jetzt exakt dasselbe, was Du hier im März bereits vorgetragen hast: "Wind Datenlogger zählt 2 mal bei einem Impuls"

Und jetzt hältst Du denselben Vortrag über denselben Windmesser in diesem Thread noch einmal.

Wenn Du tatsächlich immer zwei Schaltungen bei einer Vorbeibewegung des Magneten hast, davon eine extrem kurze, dann ist das kein Prellen, sondern dann ist das eine Einbaulage des Reedkontakts mit zwei Schließungen. Das gibt es und das ist nichts besonderes. Wenn Du es immer noch nicht glaubst, dann klicke nochmal auf die im März von mir geposteten Links zum Reekontakthersteller Meder und schaue Dir die Animationen an!

Da ist nichts zu entprellen, sondern Du mußt eben beide Schließungen bei der Auswertung berücksichtigen: Die kurze und die lange Dauer zwischen zwei Schließungen des Kontakts.

Du kannst sogar eine Plausibilitätsprüfung durchführen und feststellen, ob tatsächlich ein Kontaktprellen vorliegt:

- Du mißt die Zeit für einen kurzen Impuls in Mikrosekunden
- Du mißt die Zeit für einen langen Impuls in Mikrosekunden
- Plausibilitätsprüfung: Die der lange Impuls muß mindestens zehnmal so lang sein wie ein kurzer Impuls
- Wenn ja: Dauer beider Impulse zusammenzählen = Zeit für eine Umdrehung, sonst Messung verwerfen

Da es teils um sehr kurze Zeiten geht (bei der kurzen Schließdauer) ermittelst Du die Impulse am besten mit einer Interruptbehandlungsroutine. Jede Impulsdauer packst Du aus der Interruptbehandlungsroutine abwechselnd in Variablen ("volatile" deklariert) z.B. Impuls_A und Impuls_B.

Und in der loop-Funktion schaust Du in regelmäßigen Zeitabständen nach den beiden Variablen, ermittelst ob eine mindestens 10mal größer ist als die andere, und wenn ja zählst Du sie zusammen und berechnest aus der Summe/Gesamtdauer der beiden Werte die Windgeschwindigkeit.



Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 118
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wenn Du

'Hierbei sieht man, dass mein "RISING" immer genau 2 Werte kommen'

heraus gefunden hast, dann nimm dies als einen stabilen Sensor Parameter. Impulse / 2 und habe fertisch...

Setze am Besten die Plausibilitätsbetrachtung um, dann filters Du eine Menge Fehler heraus.

Greetz,

Linpo
Logged

العشب أخضر، أن الكرة مستديرة،

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ jurs

Du hast da vollkommen Recht. Ich hab das ganze nochmal getestet. Es werden genau 2 Signale durch den Reedkontakt pro Umdrehung erzeugt, wobei ein kurzer und ein langer Impuls entsteht.

Sorry nochmal für meine Beratungsresistens smiley-grin.

Momentan bin ich soweit, dass ich mir die Werte (die Abstände zwischen den einzelnen Schaltungen) im Serial Monitor ausgeben lasse.

Hierbei sieht man, dass zuerst ein kurzer und dann ein langer Impuls entsteht.

In der Interrupt Routine frage ich nun ab, ob meine Variable "Abstand" größer ist als 1000 (es hat sich gezeigt das der kurze Impuls max. 640 Mikrosekunden groß ist). Dann wird der Abstandswert in die Variable limpuls gespeichert (langer Impuls)...ansonten wird der Wert in der Variable kimpuls gespeichert (kurzer Impuls).

Hier der Code:
Code:
unsigned long i,abstand,kimpuls,limpuls;
unsigned long j=0;



void setup()
{
  Serial.begin(9600);

  attachInterrupt(0,Interrupt,RISING);
}

void Interrupt()
{

  noInterrupts();
 
  i = micros();
 
  abstand = i-j;
 
  j=i;
 
  if (abstand >= 1000)
  {
   limpuls=abstand;
  Serial.print("langer Impuls: ");
  Serial.println(limpuls);
  }
  else
  {
   kimpuls=abstand;
  Serial.print("kurzer Impuls: ");
  Serial.println(kimpuls);
  }

  interrupts();


}


void loop()
{

}

Mein vorrangiges Ziel besteht momentan darin, aus den Abständen (kurzer + langer Impuls) eine Periode zu bekommen, anhand derer ich direkt nach jeder Periode die ich gemessen habe, die Windgeschwindigkeit zu berechnen.

Hierzu habe ich anhand der Werte des Herstellers zu Frequenz und Windgeschwindigkeit in Excel eine Formel erstellt, die den Werten des Herstellers des Anemometers gleicht.

Nun meine Frage:

Wie kann ich es programmiertechnisch elegant lösen, das genau ein kurzer und ein langer Impuls addiert werden (die beide zusammen gehören) und dann erst wieder der nächste kurze und der nächste lange Impuls aufsummiert werden, nicht aber schon der bereits benutze lange und dann der nächste kurze Impuls?

Vielen Dank für eure Antworten!

Hier noch eine kurze Ausgabe meine Serial-Monitors:
langer Impuls: 1288736
kurzer Impuls: 548
langer Impuls: 1373776
kurzer Impuls: 552
langer Impuls: 940952
kurzer Impuls: 500
langer Impuls: 891320
kurzer Impuls: 496
langer Impuls: 571136
kurzer Impuls: 496
langer Impuls: 454896
kurzer Impuls: 496
langer Impuls: 422892

usw...
Logged

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 236
Posts: 20280
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Summiere einfach 2 aufeinanderfolgende Impulse ohne zu kontrollieren ob es ein langer oder kurzer impuls ist.

lang - kurz und kurz - lang sind gleichwertig. Es ist egal in welcher Reihenfolge die Impulse kommen, Hauptsache es sind 2 aufeinanderfolgende.

Grüße Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Stimmt. Es ist ganz egal wie rum ich die Werte aufsummiere.

Wenn ich das Programm mit folgendem Code nun durchlaufen lasse, bekomme ich aber kaum bzw. keine Werte.

Ich habe nun angefangen mir die Werte der einzelnen Variablen auszugeben. Hierbei ist mir aufgefallen, dass bis zur Variable "periode" die Werte auch richtig ausgegeben werden.

Hierbei tritt nun folgendes Problem auf:

Bsp.: periode = 1354464

Ab "periodes" (Umrechnung der Mikrosekunden in Sekunden), bekomm ich anstatt bspw. periodes = 1354464 / 1000000 = 1,354464 nur folgende Werte:

0
0
1
1
usw. (periodes als unsigned long)

0..00
0.00
1.00
usw. (periodes als float)

Welchen Variablentyp müsste "periodes" haben, damit die Zahl bspw. "1,354464" richtig dargestellt wird?

Sind die nachfolgenden Variablen frequenz und wind mit den richtigen variablentypen float und double ausgestattet?

Vielen Dank für eure hilfreichen Antworten!

Anbei noch mein aktueller Code:
Code:
unsigned long i,abstand,kimpuls,limpuls, periode;
float frequenz, periodes;
double wind;
unsigned long j=0;



void setup()
{
  Serial.begin(9600);

  attachInterrupt(0,Interrupt,RISING);
}

void Interrupt()
{

  noInterrupts();
 
  i = micros();
 
  abstand = i-j;
 
  j=i;
 
  if (abstand >= 1000)
  {
   limpuls=abstand;
  }
  else
  {
   kimpuls=abstand;
  }
  periode = kimpuls + limpuls;
  periodes= periode / 1000000;
  frequenz = 1 / periodes;
  wind = 2.58 * (pow(frequenz,0.8927));
  interrupts();


}


void loop()
{

}
Logged

Offline Offline
Edison Member
*
Karma: 31
Posts: 1048
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich würde garnix addieren.

ich würde einfach den kurzen Impuls ignorieren, und nur die micros() bei der Flanke des langen abspeichern.

in etwa so: (keine Garantie, ohne Test schnell geschrieben)
Code:
void Interrupt(){
  noInterrupts(); 
  i = micros(); 
  if (i-j > 1000){ 
    periode =i-j;
    j=i; 
    periodes= periode / 1000000;
    frequenz = 1 / periodes;
    wind = 2.58 * (pow(frequenz,0.8927));
    interrupts();
  }
}

Wobei ich nach wie vor die ganze Berechnung ausserhalb des Interrupts machen würde.
Logged

Grüße
Gunther

Offline Offline
Sr. Member
****
Karma: 4
Posts: 369
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 Hallo BigBangTheory,

Ich habe vor längerer Zeit auch mit diesem Volkswindmesser eine Wetterstation gebaut.

Das Prellen des Reedkontaktes war damals das erste Problem, ich habe den Reedkontakt ausgebaut und eine kleine Gablellichtschranke (glaube die war aus nem kaputten Drucker) eingebaut.
Dann braucht man noch eine Lochscheibe, damals selbst gebaut - gibt es aber auch zu kaufen.

Wenn ein sauberes Recheckesignal kommt, ist die Sache Softwaremässig einfacher zu händeln.  

Dannach stimmen die Werte des Windmessers nicht mehr mit denen überein die vom Hersteller angegeben sind.
Habe damals an einem windstillem Tag das Ding aus dem Auto gehalten und mit einem geeichtem Windmesser eine Tabelle aufgebaut. ( Bin natürlich nicht selbst gefahren)
Ein kleines Testprogramm auf dem Atmel und ein LCD zeigte mir die Impulse pro Sekunde an.

Heute würde ich auch die Impulsdauer messen  smiley-wink

Nachtrag: Mein Anemometer mit Reedkontakt zeigte damals nicht das Verhalten wie jurs beschreibt (also kurzer und langer Impuls)
              Mus aber auch zugeben das Posting nicht genau genug durchgelesen zu haben - sorry dafür.
« Last Edit: June 04, 2013, 09:50:32 am by rudirabbit » Logged

Arduino UNO,MEGA,Pro Mini Ethernet Shield

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die ganze Berechnung werde ich denke ich noch aus der Interrupt Routine herausnehmen.

Das Problem an dem ich momentan nicht weiter komme ist, dass wenn ch den von aus der Variable Periode umrechne, also durch 1000000 teile, ich dann in der Ausgabe der Variable periodes sehr merkwürdige Werte erhalte.

Habe ich hier den falschen Variablentyp gewählt?

Das Problem habe ich in meinem letzten Post noch genauer erklärt.

Wär toll wenn ihr mir da helfen könntet smiley!
Logged

Offline Offline
Sr. Member
****
Karma: 4
Posts: 369
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Versuche es mal nach dem Vorschlag von guntherb:

Quote
Bei der Umrechnung
Frequenz = 1 / (Periodendauer * Umrechnung);
Bin ich mir nicht sicher. Aber ich weiß, dass der Arduino mit sehr kleinen Zahlen Probleme hat.
Ich würde das eher so lösen:

Umrechnung = 1000000;
Frequenz = Umrechnung / Periodendauer ;
Logged

Arduino UNO,MEGA,Pro Mini Ethernet Shield

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Leute,

ich habe jetzt die Berechnung des ganzen aus der Interrupt in die Loop-Routine überführt. guntherb's Vorschlag mit der Berechnung der Frequenz habe ich ebenso umgesetzt.

Wenn ich mir nun die Periode in Mikrosekunden jede Sekunde anzeigen lasse, funktioniert das wunderbar. Lass ich mir hingegen die Periode anzeigen, dann hakt das ganze und ich seh nur folgende Werte:

1
1
2
2
1
4
1
usw...

Was mache ich hierbei falsch? Muss ich für die Frequenz einen anderen Variablentyp verwenden oder woran kann das ganze liegen?


Hier noch mein aktueller Code:
Code:
unsigned long i,abstand,kimpuls,limpuls, periode, Zeitscheibe, frequenz, wind;
unsigned long j=0;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(0,Interrupt,RISING);
}

void Interrupt()
{
  noInterrupts(); 
  i = micros();
  interrupts();
}

void loop()
{
  abstand = i-j;

  j=i;
 
  if (abstand >= 1000)
  {
   limpuls=abstand;
  }
  else
  {
   kimpuls=abstand;
  }

  periode = kimpuls + limpuls;
 
  frequenz = 1000000 / periode;
 
  wind = 2.58 * (pow(frequenz,0.8927));
 
  if (millis() > Zeitscheibe )   
  {
    detachInterrupt(0);
   
    Zeitscheibe  = millis()+1000;
   
    Serial.print("Windgeschwindigkeit = ");
    Serial.println(wind);
   
    attachInterrupt(0,Interrupt,RISING);
  }
}
Logged

Offline Offline
Sr. Member
****
Karma: 4
Posts: 369
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Lass ich mir hingegen die Periode anzeigen, dann hakt das ganze und ich seh nur folgende Werte

Du meinst die Frequenz anzeigen ?
Wenn du das Windrad mit der Hand drehst, sind die Werte doch fast plausibel, nur halt etwas ungenau zur späteren Weiterberechnung in Windspeed.
Die Variable frequenz hast du als unsigned long definiert, versuche es mal mit float.

Dein Windmesser (1 imp pro Umdrehung)  hat diese Werte, ist auch dein Zitat:
Quote
m/s   Hz (6 Imp.)   Hz (1 Imp.)
1   2,1            0,35
2   4,6            0,77
3   7,0         1,17
4   10,0     1,67
5   12,5     2,08
6   15,0     2,50
7   18,2     3,03
8   20,9     3,48
9   24,3     4,05
10   27,2     4,53
11   30,5     5,08
12   34,0     5,67
13   36,7     6,12
14   39,7     6,62
15   43,2     7,20
16   46,2     7,70
17   49,6     8,27
18   52,5     8,75
19   56,4     9,40
20   59,6     9,93

Logged

Arduino UNO,MEGA,Pro Mini Ethernet Shield

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe bei der Variable Frequenz schon die Variablentypen unsigned long, float, double usw. ausprobiert. Leider mit keinem guten Ergebnis.

Ist es an dieser Stelle möglich mit dem Arduino folgende Rechenschritte durchzuführen?

Bsp.:

periode = 357016

frequenz = 1000000 / periode = 1000000 / 357016 = 2,8009949133932372778811033679163 Hz

Welchen Variablentyp muss in diesem Fall die Variable Frequenz haben?

Wenn ich für die Frequenz den Variablentyp "float" verwende, erhalte ich folgende Ausgaben: 1.00, 2.00 usw. (immer mit .00).

Wenn ich für die Frequenz den Variablentyp "unsigned long" verwende, erhalte ich folgende Ausgaben: 1, 2 usw..

Wär toll wenn ihr mir da weiter helfen könntet!

Gruß

Logged

Germany
Offline Offline
Faraday Member
**
Karma: 49
Posts: 2752
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

100000 / periode ist eine Integer (long) - Division

100000.0 / periode ist eine Gleitkomma ( float ) - Division

« Last Edit: June 04, 2013, 05:11:26 pm by michael_x » Logged

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 236
Posts: 20280
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

frequenz = 1000000 / periode = 1000000 / 357016 = 2,8009949133932372778811033679163 Hz
Ich weiß nicht, war meine Schule so streng?  Aber wenn ich eine solche Rechnung dem Lehrer in Meßtechnik gezeigt hätte, hätte ich sofort die negativste mögliche Note erhalten.
Wieso?
Du gibst als Ergebnis eine Zahl mit einer Genauigkeit von 32 Stellen an, wo Du doch bei der Messung der Periode nur einen Genauigkeit von +/-0,9% ( 3 Stellen) hast. Dese Genauigkeit ist durch den Systemtakt des Arduinos gegeben und der ist durch den Resonator nicht sonderlich genau.

Also kannst Du nur 2,801 Hz schreiben wobei die Tausendstelstelle schon zweifelhaft ist.

Grüße Uwe
Logged

Pages: 1 2 [3] 4 5 6   Go Up
Jump to: