Windgeschwindigkeit wird nicht richtig ausgelesen. Ständig 0.00 km/h

Habe die Fragestellung nun überarbeitet

Guten Tag,

ich melde mich wieder und werde meinen Thread noch einmal sauberer überarbeiten, sogut ich es kann.

Ich arbeite an einer Wetterstation. Diese kann mit einem DHT-11 Sensor Temperatur und Feuchtigkeit erfassen. Mit einem Anemometer basierend auf einem Reed-Kontakt erfasst die Station Windgeschwindigkeiten.

Die gesamte Anlage besteht aus zwei Teilen/Modulen. Ein Modul, worauf man im Trockenen die Wetterdaten ablesen kann. Das andere Modul ist draußen dem Wetter ausgesetzt. Das Modul draußen (Outdoormodul) hat einen Arduino Uno, einen RF24L01 sowie alle Sensoren (DHT 11, Anemometer). Das Modul drinnen (Indoormodul) hat einen Mega 2560, das gleiche Funkmodul RF24, ein LCD1602 und ein Joystick.

Das Outdoormodul schickt die Wetterdaten an den Mega 2560 per Funk. Die Wetterdaten werden auf dem LCD 1602 angezeigt. Da nicht alle Daten auf die Anzeige passen, habe ich mehrere Seiten, welche mit dem Joystick auf dem LCD umgeblättert werden können. Seite 1: Temperatur, Seite 2: Feuchte, Seite 3: Wind. Das Indoormodul meldet dem Outdoormodul auch, welche Seite gerade an ist, ob 1, 2 oder 3.

Seite 1 und Seite 2 funktionieren soweit und zeigen mir realistische Werte. Nur bei Seite 3 kommt es gar nicht dazu, dass ausgelesen wird. Dort steht immer 0.00 km/h als Windgeschwindigkeit trotz drehen des Anemometers. Jedoch braucht das Anemometer aber mindestens 3-5 Sekunden Messzeit, um ein gutes Ergebnis zu liefern. Die Methode für die Windmessung heisst windmeasure ( ). Wie müsste ich diese überarbeiten?

Programmcode für die Anlage draußen (mit Sensoren)

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

RF24 radio(7,8);
const byte addresses[][6] = {"12345","23456"};

//Outdoor Module
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN,DHTTYPE);
float t; float h; int Seitenzahl;

const int messzeit=5;
float wvel=0.0;//für (W)ind(vel)ocity
int wind_ct;
unsigned long time=0;
unsigned long previousmillis=0;


void windmeasure() **um diese Methode hier gehts **
{
unsigned long currentmillis=millis();

wind_ct=0;
attachInterrupt(digitalPinToInterrupt(3), countWind, RISING);
if(currentmillis-previousmillis>=5000)
{
detachInterrupt(digitalPinToInterrupt(3));
previousmillis=currentmillis;
}
wvel= (float)wind_ct/(float)messzeit*2.4;
}

void countWind(){
  wind_ct++;
}

void setup() {
Serial.begin(9600); 
dht.begin(); //Sensor wird aktiviert

radio.begin();
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1, addresses[1]);
radio.setPALevel(RF24_PA_MAX);
}

void loop(){
delay(5);
radio.startListening();
if (radio.available())
{
  while (radio.available()){
    radio.read(&Seitenzahl, sizeof(Seitenzahl));
  }
}

delay(5);
radio.stopListening();
if (Seitenzahl==1)
{
t= dht.readTemperature();
radio.write(&t, sizeof(t));
}
if (Seitenzahl==2)
{
h= dht.readHumidity();
radio.write(&h, sizeof(h));
}
if (Seitenzahl==3)
{
windmeasure();
radio.write(&wvel, sizeof(wvel));
}

 
if (isnan(h)||isnan(t)){
  Serial.println("Fehler beim Auslesen!");
  return;}

Serial.print(wind_ct);
}

Programmcode für das Modul mit der Anzeige (Indoor)

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

RF24 radio(5,6);
const byte addresses[][6] = {"12345","23456"};

#include <LiquidCrystal.h>
LiquidCrystal lcd(7,8,9,10,11,12);
byte Celsius[8]={B11100,B10100,B11100,B0000,B00000,B00000,B00000,B00000}; 

int Sensorwert;
int Seitenzahl;
float t; float h; float wvel;

void setup() {
Serial.begin(9600); 
lcd.begin(16,2); 
lcd.createChar(0, Celsius);
radio.begin();
radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1, addresses[0]);
radio.setPALevel(RF24_PA_MAX);
Seitenzahl=1;
}

void loop(){
delay(100);

Sensorwert= analogRead(A1); 

if(Sensorwert>=550)
  {
     Seitenzahl++;
     lcd.clear();
  }
if(Sensorwert<=450)
  {
     Seitenzahl--;
     lcd.clear();
  }

if(Seitenzahl==1)// Seite 1 - Seite 1 - Seite 1 - Seite 1
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&t, sizeof(t));
  
  lcd.setCursor(0,0);
  lcd.print("Temp.:");
  lcd.print(t);
  lcd.write((uint8_t)0);
  lcd.print("C ");
  lcd.setCursor(0,1);
  lcd.print("Seite 1/3");
}

if(Seitenzahl==2)// Seite 2 - Seite 2 - Seite 2 - Seite 2
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&h, sizeof(h));

  
  lcd.setCursor(0,0);
  lcd.print("Feuchte:");
  lcd.print(h);
  lcd.print("%");
  lcd.setCursor(0,1);
  lcd.print("Seite 2/3");
}

if(Seitenzahl==3)// Seite 3 - Seite 3 - Seite 3 - Seite 3
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&wvel, sizeof(wvel));
  
  lcd.setCursor(0,0);
  lcd.print("Wind: ");
  lcd.print(wvel);       //Speed in Km/h
  lcd.print("km/h");
  lcd.setCursor(0,1);
  lcd.print("Seite 3/3");
}

Serial.print(t);
}

Also zum Anfang wäre es nett, wenn Du Deinen Code in Codetags stellst.
Ich hab das jetzt versucht, aber da kommt nichts raus, was irgendwer irgendwie testen kann.

void windmeasure()
{
  unsigned long currentmillis = millis();

  wind_ct = 0;
  attachInterrupt(digitalPinToInterrupt(3), countWind, RISING);
  if (currentmillis - previousmillis >= 5000)
  {
    detachInterrupt(digitalPinToInterrupt(3));
    previousmillis = currentmillis;
  }
  wvel = (float)wind_ct / (float)messzeit * 2.4;
}

Diese Methode wird hier in void loop( ) aufgerufen:

void loop() {
  delay(5);
  radio.startListening();
  if (radio.available())
  {
    while (radio.available()) {
      radio.read(&Seitenzahl, sizeof(Seitenzahl));
    }
  }

  delay(5);
  radio.stopListening();
  if (Seitenzahl == 1)
  {
    t = dht.readTemperature();
    radio.write(&t, sizeof(t));
  }
  if (Seitenzahl == 2)
  {
    h = dht.readHumidity();
    radio.write(&h, sizeof(h));
  }
  if (Seitenzahl == 3)
  {
    windmeasure(); // METHODE !
    radio.write(&wvel, sizeof(wvel));
  }

  if (isnan(h) || isnan(t)) {
    Serial.println(“Fehler beim Auslesen!”);
    return;
  }

  Serial.print(wind_ct);
}

Es braucht schon etwas, was kompiliert - sonst macht das keinen Sinn.
Denn ich kann nicht erkennen, wo Du previousmillis her holst und was damit noch z.B. in oder durch countWind passiert.

Ein bisschen Korinthenka… :slight_smile: : Was Du zeigst sind ‘Funktionen’. ‘Methoden’ sind was anderes, und das sollte man auch auseinanderhalten. Obwohl es Anfangs so gleich erscheint.

Und wie schon gesagt, mit solchen Rudimenten kann man nichts anfangen. Der Fehler liegt meist im ‘geheimen’ Teil :wink: .

Erwartest Du etwa, daß hier 5 Sekunden gewartet wird, bevor der Interrupt wieder detacht wird? Das stimmt leider nicht.

Vorschlag: Studiere BlinkWithoutDelay und verzichte erst einmal auf Interrupts.

Ok. Danke fürs Feedback. Werde meine Frage noch etwas nach bearbeiten in 2 Tagen, wenn ich wieder dran bin

Beschreibe doch mal in gaanz normalen Worten was das Programm können soll. Unter bewusster Weglassung von irgendwelchen Programmierbegriffen.

Ein Beispiel das das Prinzip dieser Erklärung demonstrieren soll:
Man könnte einen Arduino auch dazu benutzen
Alle 15 Sekunden lang 2 Sekunden eine Hupe zu betätigen.
Beim ersten Hupen Lampe an, beim zweiten Hupen Lampe aus
Beim dritten Hupen Lampe wieder an usw.

Diese Beschreibung enthält keinerlei Programmiererbegriffe: sondern nur
etwas soll in regelmäßigen Abständen passieren
Das Zeitintervall
Und das was man dann beobachten kann.
2 Sekunden Hupen, Lampe an/aus.

Jetzt poste eine Beschreibung was dein Programm machen soll.
Wenn du diese Beschreibung gepostest hast dann kann man dir Tips geben wie man das programmiertechnisch am besten realisiert.

viele Grüße Stefan

Ich?
Nein.

Guten Tag,

ich melde mich wieder und werde meinen Thread noch einmal sauberer überarbeiten, sogut ich es kann.

Ich arbeite an einer Wetterstation. Diese kann mit einem DHT-11 Sensor Temperatur und Feuchtigkeit erfassen. Mit einem Anemometer basierend auf einem Reed-Kontakt erfasst die Station Windgeschwindigkeiten.

Die gesamte Anlage besteht aus zwei Teilen/Modulen. Ein Modul, worauf man im Trockenen die Wetterdaten ablesen kann. Das andere Modul ist draußen dem Wetter ausgesetzt. Das Modul draußen hat einen Arduino Uno, einen RF24L01 sowie alle Sensoren (DHT 11, Anemometer). Das Modul drinnen hat einen Mega 2560, das gleiche Funkmodul RF24, ein LCD1602 und ein Joystick.

Das Modul draußen schickt die Wetterdaten an den Mega 2560 per Funk. Die Wetterdaten werden auf dem LCD 1602 angezeigt. Da nicht alle Daten auf die Anzeige passen, habe ich mehrere Seiten, welche mit dem Joystick auf dem LCD umgeblättert werden können. Seite 1: Temperatur, Seite 2: Feuchte, Seite 3: Wind.

Seite 1 und Seite 2 funktionieren soweit und zeigen mir realistische Werte. Nur bei Seite 3 kommt es gar nicht dazu, dass ausgelesen wird. Dort steht immer 0.00 km/h als Windgeschwindigkeit. Jedoch braucht das Anemometer aber mindestens 3-5 Sekunden Messzeit, um ein gutes Ergebnis zu liefern. Die Methode für die Windmessung heisst windmeasure ( ). Wie müsste ich diese überarbeiten?

Programmcode für die Anlage draußen (mit Sensoren)

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

RF24 radio(7,8);
const byte addresses[][6] = {"12345","23456"};

//Outdoor Module
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN,DHTTYPE);
float t; float h; int Seitenzahl;

const int messzeit=5;
float wvel=0.0;//für (W)ind(vel)ocity
int wind_ct;
unsigned long time=0;
unsigned long previousmillis=0;


void windmeasure()
{
unsigned long currentmillis=millis();

wind_ct=0;
attachInterrupt(digitalPinToInterrupt(3), countWind, RISING);
if(currentmillis-previousmillis>=5000)
{
detachInterrupt(digitalPinToInterrupt(3));
previousmillis=currentmillis;
}
wvel= (float)wind_ct/(float)messzeit*2.4;
}

void countWind(){
  wind_ct++;
}

void setup() {
Serial.begin(9600); 
dht.begin(); //Sensor wird aktiviert

radio.begin();
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1, addresses[1]);
radio.setPALevel(RF24_PA_MAX);
}

void loop(){
delay(5);
radio.startListening();
if (radio.available())
{
  while (radio.available()){
    radio.read(&Seitenzahl, sizeof(Seitenzahl));
  }
}

delay(5);
radio.stopListening();
if (Seitenzahl==1)
{
t= dht.readTemperature();
radio.write(&t, sizeof(t));
}
if (Seitenzahl==2)
{
h= dht.readHumidity();
radio.write(&h, sizeof(h));
}
if (Seitenzahl==3)
{
windmeasure();
radio.write(&wvel, sizeof(wvel));
}

 
if (isnan(h)||isnan(t)){
  Serial.println("Fehler beim Auslesen!");
  return;}

Serial.print(wind_ct);
}

Programmcode für das Modul mit der Anzeige (Indoor)

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

RF24 radio(5,6);
const byte addresses[][6] = {"12345","23456"};

#include <LiquidCrystal.h>
LiquidCrystal lcd(7,8,9,10,11,12);
byte Celsius[8]={B11100,B10100,B11100,B0000,B00000,B00000,B00000,B00000}; 

int Sensorwert;
int Seitenzahl;
float t; float h; float wvel;

void setup() {
Serial.begin(9600); 
lcd.begin(16,2); 
lcd.createChar(0, Celsius);
radio.begin();
radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1, addresses[0]);
radio.setPALevel(RF24_PA_MAX);
Seitenzahl=1;
}

void loop(){
delay(100);

Sensorwert= analogRead(A1); 

if(Sensorwert>=550)
  {
     Seitenzahl++;
     lcd.clear();
  }
if(Sensorwert<=450)
  {
     Seitenzahl--;
     lcd.clear();
  }

if(Seitenzahl==1)// Seite 1 - Seite 1 - Seite 1 - Seite 1
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&t, sizeof(t));
  
  lcd.setCursor(0,0);
  lcd.print("Temp.:");
  lcd.print(t);
  lcd.write((uint8_t)0);
  lcd.print("C ");
  lcd.setCursor(0,1);
  lcd.print("Seite 1/3");
}

if(Seitenzahl==2)// Seite 2 - Seite 2 - Seite 2 - Seite 2
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&h, sizeof(h));

  
  lcd.setCursor(0,0);
  lcd.print("Feuchte:");
  lcd.print(h);
  lcd.print("%");
  lcd.setCursor(0,1);
  lcd.print("Seite 2/3");
}

if(Seitenzahl==3)// Seite 3 - Seite 3 - Seite 3 - Seite 3
{
  delay(5);
  radio.stopListening();
  radio.write(&Seitenzahl, sizeof(Seitenzahl));
  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&wvel, sizeof(wvel));
  
  lcd.setCursor(0,0);
  lcd.print("Wind: ");
  lcd.print(wvel);       //Speed in Km/h
  lcd.print("km/h");
  lcd.setCursor(0,1);
  lcd.print("Seite 3/3");
}

Serial.print(t);
}

Das da nur 0 rauskommen kann, wundert mich nicht.
wind_ct verliert beim verlassen von windmeasure seinen Wert und wird beim wiedereintritt in die Funktion mit 0 initialisiert.

Ich hab mal was gebastelt, wovon ich denke, das es besser ist.
Bitte überlege, ob Du wirklih das detachen/attachen in der Funktion brauchst?! Ich sage nein, habs aber drin gelassen.
Da ich keine Hardware habe, ungetestet.

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

RF24 radio(7, 8);
const byte addresses[][6] = {"12345", "23456"};

//Outdoor Module
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
float t; float h; int Seitenzahl;
unsigned long time = 0;


volatile int wind_ct = 0;
float wvel = 0.0; //für (W)ind(vel)ocity

void windmeasure()
{
  static unsigned long previousmillis = 0;
  unsigned long currentmillis = millis();
  if (currentmillis - previousmillis >= 5000)
  {
    detachInterrupt(digitalPinToInterrupt(3));
    wvel = (float)wind_ct / (float)(currentmillis-previousmillis) * 2.4;
    wind_ct=0;
    previousmillis = millis();
    attachInterrupt(digitalPinToInterrupt(3), countWind, RISING);
  }
}

void countWind() {
  wind_ct++;
}

void setup() {