Auswertung Impulse Volkswindmesser

100000 / periode ist eine Integer (long) - Division

100000.0 / periode ist eine Gleitkomma ( float ) - Division

BigBangTheory:
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

Mein ganzer Fehler lag wohl darin, in der Rechnung frequenz = 1000000 / periode zu schreiben: frequenz = 1000000.0 / periode :D.

Gibt es denn eine Möglichkeit festzulegen, wie viele Nachkommastellen man angezeigt bekommen möchte, wenn man solch eine Float-Division durchführt?

Gibt es denn eine Möglichkeit festzulegen, wie viele Nachkommastellen man angezeigt bekommen möchte

Ja, mehrere.
Ist ausserdem keine Frage der Division, sondern der Anzeige.
Schau dir mal Serial.print an

Float hat beim Arduino meist 6 bis 7 Stellen, also z.B. 1.23456 *10^-4
Du kannst dir natürlich mehr Stellen anzeigen lassen (z.B. mit Serial.println(frequenz, 18), aber die machen keinen Sinn.
mehr als die 6-7Stellen genauigkeit wirst du nicht bekommen, und das reicht ja meist auch.

Ich komme aus Delphi/Pascal Welt, deshalb wundere ich ab und an schon was ein C-Compiler so macht

frequenz = 1000000 / periode

Bei Delphi - Wenn frequenz eine Integer Variable wäre wurde der Compiler sofort meckern.
Er will das dies in einer Gleitkomma Variable gespeichert werden soll, weil das Ergebnis ein Gleitkomma sein wird.
Wenn zwei ganze Zahlen dividiert werden ist das meist der Fall

Wenn ich nun in C frequenz expliziert als float definiere muß ich dies dann wirklich so schreiben,
damit auch eine Float-Division durchgeführt wird.

frequenz = 1000000.0 / periode

Ich wäre genauso wie BigBangTheory in diese Falle getappt.

Ist zwar etwas OT sorry dafür, aber dieses Beispiel passte genau für meine Frage

...weil das Ergebnis ein Gleitkomma sein wird.

Der Fehler liegt erstmal im "weil", dann konkret daran dass in c Integer/Integer als Ergebnis immer ein Integer ist. Was sonst :wink:

Ganz fies wird es übrigens, wenn z.B. 1000 und 1000L einen Unterschied macht.
( z.B. wenn man es mit int i = 100 multipliziert und das Ergebnis in einem long ablegt. )

int i = 100;
long l = 1000 * i; 
Serial.print(l); 
if ( l == -31072) Serial.println (" ist ein erstaunliches Ergebnis");

Bei c für MicroController sollte man übrigens auch immer überlegen, ob man tatsächlich den Datentyp float braucht.

michael_x:
Bei c für MicroController sollte man übrigens auch immer überlegen, ob man tatsächlich den Datentyp float braucht.

Schon klar, immer schön die ressourcen schonen.

int i = 100;
long l = 1000 * long( i); 
Serial.print(l); 
if ( l == -31072) Serial.println (" ist ein erstaunliches Ergebnis");

Dann müsste man in diesen Fall einen typecast machen =( oder i gleich als long denfinieren
Danke für solche Hinweise, als Delphi Mensch hätte so einen Fehler nie gesehen.
Ich möchte jetzt keine Diskussion über Programmiersprachen lostreten, weil obsolet ..... C++ hat sich durchgesetzt. :~

Ob C++ zu Objekt Pascal wirklich besser ist ??

Das obigen Beispiel ist ganz simples C und selbst dort gibt es Dinge die in meinen Pascal Augen gar nicht gehen dürften.

C und C++ ist für Masochisten, sagen die einen.

Basic, C# , Java und dein Pascal ist für Weicheier, sagen die anderen.

michael_x:
C und C++ ist für Masochisten, sagen die einen.

Basic, C# , Java und dein Pascal ist für Weicheier, sagen die anderen.

Dann oute ich mich hier mal als masochistisches Weichei XD

Hi Leute,

nachdem mein Windmesser unter "Laborbedingungen XD" super funktioniert und gute Werte angezeigt hat, dachte ich mir als ein Gewitter aufzog, dass ich ihn mal in "freier Wildbahn" testen werde. Ich habe ihn also auf dem Geländer meines Balkons installiert, Y-Draht in die Wohnung gezogen, alles angeschlossen und los gings. Am Anfang kamen super Werte, dann zog das Gewitter über uns hinweg und ich bekam Windgeschwindigkeiten die jenseits von Gut und Böse lagen (über 1000 m/s) und als das Gewitter wieder weg war, waren die Werte wieder okay.

Desweiteren habe ich versucht, den Arduino per Netzteil zu betreiben, wobei ich dabei auch teilweise sehr sehr wilde Werte angezeigt bekam. Ohne Netzteil war dies jedoch nicht der Fall.

Kann es sein das dies daran liegt, weil der Y-Draht nicht abgeschirmt ist?

Oder hat jemand noch eine bessere Idee dazu?

Gruß

BigBangTheory:
Kann es sein das dies daran liegt, weil der Y-Draht nicht abgeschirmt ist?

Oder hat jemand noch eine bessere Idee dazu?

Ja, nicht abgeschirmte Kabel, oder welche an denen die Abschirmung nicht geerdet ist, wirken als Antenne und nehmen Funkwellen auf, auch die bei einem Gewitter entstehenden. Da kommt es darauf an, wie stark Deine PullUp- oder PullDown-Widerstände sind, inwieweit die entgegenwirken.

Ich bin jetzt in diesem vierseitigen Thread nicht drin, was verwendest Du denn zur Auswertung des Reed-Signals am Pin:

  • den internen PullUp-Widerstand?
  • einen externen PullUp- oder PullDown-Widerstand? Welchen Wert hat der Widerstand?

Im Zweifelsfall mal einen niedrigeren Wert probieren, also z.B. 1K statt 10K Pulldown-Widerstand.

Das mit den Funkwellen dacht ich mir schon fast. Wenn früher bei nem alten Radio die Antenne ab war, haben wir auch nen Stück blanken Kupferdraht genommen und den zu ner Antenne gebogen :).

Ich hab da momentan nen 12K Widerstand dran.

Wieso würde denn ein kleinerer Widerstand hier helfen?

Es könnte aber auch ein Überlauf sein, weil das WindRad zu schnell dreht.
Ich habe jetzt nicht den Code im Kopf oder unter der Hand um ihn analysieren zu können.

Grüße Uwe

BigBangTheory:
Ich hab da momentan nen 12K Widerstand dran.

Wieso würde denn ein kleinerer Widerstand hier helfen?

Wenn durch den PullDown-Widerstand höhere Ströme fließen müssen, um zu einer Spannungsänderung am Arduino-Pin zu führen, dann ist für Störungen eine höhere eingekoppelte Energie notwendig, damit der Arduino-Pin auf HIGH gezogen wird.

Ein kleinerer PullDown-Widerstand wirkt also eingekoppelten Störungen auf der Zuleitung entgegen. Je länger eine Zuleitung ist, desto mehr Störungen fängt sie auf. Und daher verwendest Du bei einer längeren Zuleitung besser 1K Pulldown-Widerstände als 12K.

Wie Uwe schreibt, kann aber auch die Software-Auswertung fehlerhaft sein.
Welchen Sketch verwendest Du denn jetzt dafür?

Hey Leute,

momentan verwende ich folgenden Sketch:

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4; // Chip Select, Signal SS (Slave Select)
unsigned long kimpuls = 0;
unsigned long limpuls = 0;
unsigned long periode = 0;
unsigned long Zeitscheibe = 0;
unsigned long i = 0;
unsigned long j = 0;
unsigned long abstand = 0;
int Sekunden = 00;
int Minuten = 54;
int Stunden = 16;
float wind = 0;
float frequenz = 0;

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  //-------------------------------------------------SD-Card - Anfang
  Serial.print("Initialisierung SD-Card...");
  pinMode(10, OUTPUT); // SPI Chip Select als Ausgang setzen, auch wenn nicht genutzt
  if (!SD.begin(chipSelect)) { // Prüfen, ob SD-Card bereit für Initialisierung
    Serial.println("SD-Card nicht bereit oder fehlend");
    return; // nichts weiter zu tun
  }
  Serial.println("SD-Card initialisiert");
//-------------------------------------------------SD-Card - Ende
//  Serial.println("hh:mm:ss;   Windgeschwindigkeit");
  
  
  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.0 / periode;
  wind = 2.58 * (pow(frequenz,0.8927));
  
  if (millis() > Zeitscheibe )    
  { 
    detachInterrupt(0); 
    Zeitscheibe  = millis()+1000;
    Sekunden++;
//-------------------------------------------------Zeit Berechnung - Anfang  
  if (Sekunden==60){
   Minuten++;
   Sekunden=0;
  }
  if (Minuten==60){
    Stunden++;
    Minuten=0;
  }
  if (Stunden==24){
    Stunden = 0;
  }
//-------------------------------------------------Zeit Berechnung - Ende    
    if (micros()-i > 4311965 )
    {
     wind = 0; 
    }
    if (periode == 0){
      wind = 0;
    }
    
//-------------------------------------------------Speicherung auf SD-Karte - Anfang    
 File dataFile = SD.open("wind.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.print(Stunden);
    dataFile.print(" ; ");
    dataFile.print(Minuten);
    dataFile.print(" ; ");
    dataFile.print(Sekunden);
    dataFile.print(" ;   ");
    dataFile.print(wind);
    dataFile.print(" ; m/s;   ");
    dataFile.print(i);
    dataFile.println(" ;   Zeitpunkt des Interrupts in Mikrosekunden");
    dataFile.close();
    }  
  // kann die Datei auf der SD-Karte nicht geöffnet werden, wird folgende Fehlermeldung angezeigt
  else {
    Serial.println("error opening wind.csv");
  }
//-------------------------------------------------Speicherung auf SD-Karte - Ende
// Ausgabe der Werte auch auf dem Serialmonitor:

    Serial.print(Stunden);
    Serial.print(" ; ");
    Serial.print(Minuten);
    Serial.print(" ; ");
    Serial.print(Sekunden);
    Serial.print(" ;   ");
    Serial.print(wind);
    Serial.println(" ; m/s;   ");
//    Serial.print(i);
//  Serial.println(" ;   Zeitpunkt des Interrupts in Mikrosekunden");

    attachInterrupt(0,Interrupt,RISING);
  }
}

Ich habe, auch wenn das Windrad stand, beim Gewitter, aber auch wenn ich ein Netzteil an den Arduino angeschlossen habe, sehr große Werte bekommen. Ich tippe da dann doch eher auf die Störsignal-Variante.

Ich würde auch gern zur festen Installation des Windmessers ein Koaxialkabel verwenden, welches ja abgeschirmt sein müsste, oder?

Mir stellt sich da nun jedoch die Frage, wie ich es an den Arduino anschließen kann. Der Innenleiter ist ja easy, aber wie mach ich es mit dem Außenleiter? Ich Stück vom Kabel zurückschneiden und den Außenleiter verdrillen zum anschließen?

Werd das ganze mal mit nem kleineren Widerstand ausprobieren :).

Habe den Code nur kurz angesehen.

Du hast in der main Loop dies:

 attachInterrupt(0,Interrupt,RISING);

Im Setup auch, so soll es auch sein, aber warum auch in der main Loop ?

BigBangTheory:
momentan verwende ich folgenden Sketch:

unsigned long i = 0;

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

Also erstmal zum Sketch: Der weist einige extrem merkwürdige Fehler auf.
Das ständige attachInterrupt in der loop hat rudirabbit bereits angesprochen.

Weiterhin können Interrupts gar nicht von anderen Interrupts unterprochen werden, daher ist das Sperren und Freigeben von Interrupts in der Interrupt-Behandlungsroutine völlig überflüssig. Es reicht daher vollkommen:
void Interrupt()
{
i = micros();
}

ABER: Variablen, auf die sowohl von normalem Code aus als auch von Interrupt-Code aus zugegriffen wird, müssen zwingend mit dem Attribut "volatile" deklariert werden, also:

volatile unsigned long i = 0;

Ich schau mir das nochmal näher an, was der Code machen soll und poste ggf. mal Alternativ-Code.

BigBangTheory:
Ich habe, auch wenn das Windrad stand, beim Gewitter, aber auch wenn ich ein Netzteil an den Arduino angeschlossen habe, sehr große Werte bekommen. Ich tippe da dann doch eher auf die Störsignal-Variante.

Ja, die Beschreibung klingt schwer nach Störungen.
Der PullDown-Widerstand ist wirklich korrekt angeschlossen?
Das Netzteil ist wohl ein sogenanntes "Schaltnetzteil"?
Hat das irgendwelche Prüfzeichen drauf, TÜV, GS, VDE, oder ist das Chinaware ohne alles?

BigBangTheory:
Werd das ganze mal mit nem kleineren Widerstand ausprobieren :).

Genau, erstmal den kräftigeren PullDown-Widerstand mit dem kleineren Ohm-Wert testen, 1K statt 12K an der langen Reed-Sensorzuleitung.

BigBangTheory:
Ich würde auch gern zur festen Installation des Windmessers ein Koaxialkabel verwenden, welches ja abgeschirmt sein müsste, oder?

Koaxkabel haben heute oft sogar eine zweifache Abschirmung und kosten ganz gut Geld.
Aber selbst einfaches Telefon-Verlegekabel ist mit so einer Art hauchfeiner Alufolie abgeschirmt. Kann man aber nicht Löten, die Folien-Abschirmung muss wohl per Schraubanschluss angeschlossen werden.

BigBangTheory:
Mir stellt sich da nun jedoch die Frage, wie ich es an den Arduino anschließen kann. Der Innenleiter ist ja easy, aber wie mach ich es mit dem Außenleiter? Ich Stück vom Kabel zurückschneiden und den Außenleiter verdrillen zum anschließen?

Die Abschirmung müßte irgendwo an eine Erdung angeschlossen werden, mindestens an einem Ende.
Normalerweise würde der Windmesser wohl auf einem geerdeten oder mit Blitzableiter geschützten Mast montiert werden. Dann würde die Abschirmung auf der Sensorseite an die Erdung des Mastes angeschlossen werden. Und auf der Arduino-Seite an den Schutzleiter des Stromnetzes. Oder ein Wasser- oder Heizungsrohr (falls die Heizungsanlage Metallrohre hat) im Haus.

Also erstmal zum Sketch: Der weist einige extrem merkwürdige Fehler auf.
Das ständige attachInterrupt in der loop hat rudirabbit bereits angesprochen.

Das "attachInterrupt(0,Interrupt,RISING);" habe ich im loop, weil ich ein Stück davor im loop ein "detachInterrupt(0);" eingebaut habe, damit meine Ausgabe, welche jede Sekunde einmal statt findet, nicht von einem Interrupt zerschossen wird.

Die Interrupt-Routine und die Variablenbezeichnung "volatile unsigned long i = 0;" habe ich abgeändert :).

Ja, die Beschreibung klingt schwer nach Störungen.
Der PullDown-Widerstand ist wirklich korrekt angeschlossen?
Das Netzteil ist wohl ein sogenanntes "Schaltnetzteil"?
Hat das irgendwelche Prüfzeichen drauf, TÜV, GS, VDE, oder ist das Chinaware ohne alles?

Das Netzteil das ich verwende ist ein Festspannungs-Schaltnetzteil von Conrad Elektronik. Hier der Link dazu:

http://www.conrad.de/ce/de/product/514209/VOLTCRAFT-FPPS-9-6W-Steckernetzteil-Steckernetzgeraet-Festspannungs-Schaltnetzteil-9V-660mA-6-Watt

Koaxkabel haben heute oft sogar eine zweifache Abschirmung und kosten ganz gut Geld.
Aber selbst einfaches Telefon-Verlegekabel ist mit so einer Art hauchfeiner Alufolie abgeschirmt. Kann man aber nicht Löten, die Folien-Abschirmung muss wohl per Schraubanschluss angeschlossen werden.

Mal ne doofe Frage, aber...ich will Kabelkanäle verwenden, durch die ich mein Y-Kabel ziehe. Was ist, wenn ich um das Y-Kabel Alufolie Wickel (1-2 Lagen, Klebestreifen dran und fertig. Das wär doch dann auch ne Abschirmung und vor allem günstiger als nen Koax-Kabel, oder?

Das mit dem Widerstand wird morgen ausprobiert :).

Gruß

F-Stecker <-> BNC/F Adapter <-> BNC Buchse wäre ne Möglichkeit für Koaxkabel. Letztere gibt es zum Löten und mit Klemmen