Windmesser auf ESP8266

Hallo an Alle,

mit Hilfe des Codes aus fogendem Post Sonnen Tracker Arduino konnte ich meinen eigenen Windsensor Code basteln, wo bei Erreichen der Windschwelle ein Ausgang geschalten wird, den ich in mein Homekit exportiere und zur Wintergartensteuerung nutzen möchte.
Außerdem habe ich noch ein Potentiometer eingebaut, mit dem man die Windschwelle etwas nach oben oder nach unten korrigieren kann (so war es auch bei meiner 20 Jahre alten Wintergartensteuerung, was meist sehr hilfreich war).

// Begin Variablen Wind
bool windAusgeloest = false;
const byte AnemometerPin = 2;  //Definierter Interrupt Pin 
const byte WindPin = 7; // Ausgang der geschalten wird, wenn Wind ausgelöst ist 
const byte PotentiometerPIN = A0; // Analoger Eingang des Potentiometers
volatile unsigned long windCounter;
float Windgeschwindigkeit;
float Faktor;

const unsigned long messZeit = 2000; //Messzeit in ms
const byte windSchwelle = 30; // km/h
const byte sturmSchwelle = 40; // km/h
const unsigned long umlaufZeit = 10000; // 10 Sekunden
byte umlaufMerker[umlaufZeit / messZeit]; // Anzahl der benötigten Elemente des Array errechnet sich aus den Zeiten
// End Variablen Wind

void setup ()
{
  // Setup Wind
  pinMode(AnemometerPin, INPUT_PULLUP);
  pinMode(WindPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(AnemometerPin), countup, RISING);
  Windmessung(messZeit);

}

void loop ()
{
  //Einlesen der Potiwerte
  int data = analogRead(PotentiometerPIN);
  int Potistellung = map(data, 0, 1023, 1, 16);  // Mapping der Potistellung von 1 bis 15
  Faktor = Potistellung * 0.1; // Potistellung mit 0,1 multipliziert für sinnvollen Faktor
  Serial.print("Potentiometer bei Faktor ");
  Serial.print(Faktor);
  Serial.print("\t aktuelle Windschwelle: ");
  Serial.print(windSchwelle*(Faktor));
  Serial.println(F(" Km/h"));
  delay(messZeit);
  //Ausgabe der Windwerte
  static unsigned long lastprint;
  static unsigned long lastausloeser = 0;
  const unsigned long sperrZeit = 10000; // Wind Sperrzeit 10 Sek.
  if (millis() - lastprint >= messZeit)
  {
    lastprint = millis();
    Serial.print(F("Windgeschwindigkeit: "));
    Serial.print(Windgeschwindigkeit); // Ausgabe der Windgeschwindigkeit in Km/h
    Serial.println(F(" Km/h"));
  }
  Windmessung(messZeit);
  if (Auswertung(umlaufZeit))
  {
    Serial.println(F("Wind ausgelöst"));
    // Hier merken, das ausgelöst wurde:
    windAusgeloest = true;
    lastausloeser = millis();
    Serial.println(F("Auslöser gemerkt"));
  }
  if (windAusgeloest)
  {
    if (millis() - lastausloeser >= sperrZeit)
    {
      windAusgeloest = false;
      Serial.println(F("Ausloeser geloescht"));
    }
    }
  if (windAusgeloest == true) {
digitalWrite(WindPin, HIGH);    //Ausgang geschalten, wenn Wind ausgelöst
} else {
digitalWrite(WindPin, LOW);     //Ausgang aus, wenn Wind ausgelöst falsch
}
}

bool Auswertung(unsigned long intervall)
{
  static unsigned long lastmillis = 0;
  unsigned int wind = 0;
  unsigned int sturm = 0;
  bool ausloeser = false;
  if (millis() - lastmillis >= intervall)
  {
    Serial.println(F("Werte durchzaehlen:"));
    for (byte i = 0; i < sizeof(umlaufMerker); i++)
    {
      if (umlaufMerker[i] >= windSchwelle*(Faktor)) wind++;
      if (umlaufMerker[i] >= sturmSchwelle) sturm++;
      Serial.print(umlaufMerker[i]);
      Serial.print(F("\t"));
    }
    Serial.println();
    lastmillis = millis();
  }
  if ((wind >= 3) || (sturm >= 2))
  {
    ausloeser = true;
  }
  return ausloeser;
}

void Windmessung(unsigned long intervall) // Initalisierung und Berechnung für die Windgeschwindigkeit
{
  static unsigned long lastMessung = 0;
  static unsigned int elementeZaehler = 0;
  if (millis() - lastMessung >= intervall)
  {
    detachInterrupt(digitalPinToInterrupt(AnemometerPin));
    Serial.println(windCounter);
    Windgeschwindigkeit = (float)(windCounter * 1.2) / (float)((millis() - lastMessung) / 1000);
    windCounter = 0;
    lastMessung = millis();
    attachInterrupt(digitalPinToInterrupt(AnemometerPin), countup, RISING);
    umlaufMerker[elementeZaehler] = (int)Windgeschwindigkeit;
    elementeZaehler++;
    if (elementeZaehler > (sizeof(umlaufMerker))) elementeZaehler = 0;
  }
}

void countup() // Zähler für die Impulse des Reed Kontakt
{
  windCounter++;

}

(Eventuell kann der Code noch ausgedünnt werden und unnötige Codezeilen entfernt werden.)
Da der Code soweit funktioniert, wollte ich den nächsten Schritt wagen und mir die aktuelle Windgeschwindigkeit und Windschwelle über einen Webserver ausgeben lassen.
Leider verzweifle ich schon daran, den obigen Code auf einem ESP8266 zum Laufen zu bekommen. Der serielle Monitor gibt mir nur ungewöhnliche Werte aus.

Ich hoffe, dass ihr mir bei meinen Problemen helfen könnt

Mit freundlichen Grüßen
Martin

Meine Antwort ist im anderen Thread.
Baue Dir serielle Ausgaben rein, um zu sehen, wo er abschmiert.

Gruß Tommy

Hallo Tommy, danke für den Tip,

ich habe in mein void setup folgende testzeile eingesetzt:

Serial.begin(115200);
  for (int i=10; i>0; i--) {
    Serial.print(i); Serial.print(' '); delay(500);
  }
  Serial.println();

im Serial Monitor zählt er jetzt von 10 auf 1 runter und dann schlägt wieder der Watchdog zu.
Hast noch einen Tip welche seriellen Ausgaben zum überprüfen sinnvoll sind?
Gruß
Martin

Das Problem liegt vermutlich in der loop, also auch serielle Ausgaben einbauen.
Das müssen keine Zählschleifen sein, nur einfache Textausgaben, an denen du anschließend den Fehler festmachen kannst.

Dann ist die Ursache später. Weiter suchen.
Gib doch erst mal an markanten Punkten Deines Sketches eine Ausgabe aus (die alten wieder entfernen), damit Du einen groben Überblick bekommst, wo er überall durch läuft.

Gruß Tommy

Erstmal Danke für eure Tips,

es scheint wirklich im Loop ein Problem zu sein, im Setup kann ich noch alles in die serielle Ausgabe schreiben, das wird auch angezeigt.
Ich habe im loop an die erste Stelle eine serielle Ausgabe gestellt, doch da startet der ESP schon neu. Ich werd morgen Abend nochmal drauf schauen und hoffen mit meinem Anfängerwissen etwas herauszufinden.
Gruß
Martin

Du kannst doch die Anweisungen in der Loop einzeln ausblenden und damit prüfen, wo das Problem auftritt.

Was mich verwundert ist die PinAngabe.
Wie sieht denn die Zuordnung zu den GPIO aus? @HotSystems kannst Du da evtl. mal drauf schaun?
Und was ist da noch so alles beschaltet und ggfls. nicht in Gebrauch?

Das war ne gute Idee.
Der GPIO7 (7) ist garnicht herausgeführt und kann durchaus das Problem am ESP8266 auslösen, da dieser intern genutzt wird.
Somit sollte @Hanimaniac dafür einen anderen GPIO wählen.
Hier kann man nachlesen, welcher GPIO geeignet ist.

Oder auch hier zum nachlesen.

1 Like

Vielen Dank für eure Tips,

ich habe jetzt den WinPin auf GPIO 5 und den AnemometerPin auf GPIO 4 gesetzt,
wobei ich jetzt folgendes Ergebnis im SM habe:

Gib uns Fehlerausgaben bitte auch als Text in Codetags, nicht als Bild.
Dein Code stimmt nicht mit der Fehlermeldung überein, da es in Deinem Code keine TEST1ISR gibt. Willst Du uns veralbern (vorsichtig ausgedrückt)?
Du solltest schon den Quelltext liefern, der die Fehlermeldung erzeugt hat, sonst ist Hilfe unmöglich.

Gruß Tommy

Baue doch den Sketch mal ohne ISR auf.
Wenn du nur Wind messen möchtest, sollte das auch in der loop() funktionieren.

Für den Anfängerfehler mit dem Screenshot möchte ich mich entschuldigen und nichts liegt mir ferner als die Sehenden hier veralbern zu wollen.

Hier der aktuelle Code.


// Begin Variablen Wind
bool windAusgeloest = false;
const byte AnemometerPin = 4;  //Definierter Interrupt Pin 
const byte WindPin = 5; // Ausgang der geschalten wird, wenn Wind ausgelöst ist 
const byte PotentiometerPIN = A0; // Analoger Eingang des Potentiometers
volatile unsigned long windCounter;
float Windgeschwindigkeit;
float Faktor;

const unsigned long messZeit = 2000; //Messzeit in ms
const byte windSchwelle = 30; // km/h
const byte sturmSchwelle = 40; // km/h
const unsigned long umlaufZeit = 10000; // 10 Sekunden
byte umlaufMerker[umlaufZeit / messZeit]; // Anzahl der benötigten Elemente des Array errechnet sich aus den Zeiten
// End Variablen Wind

void setup ()
{
  Serial.begin(115200);
  for (int i=10; i>0; i--) {
    Serial.print(i); Serial.print(' '); delay(500);
  }
  Serial.println();
  Serial.print("TEST1");
  // Setup Wind
  pinMode(AnemometerPin, INPUT_PULLUP);
  pinMode(WindPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(AnemometerPin), countup, RISING);
  Windmessung(messZeit);

}

void loop ()
{
  
    Serial.print("TEST2");
  
  //Einlesen der Potiwerte
  int data = analogRead(PotentiometerPIN);
  int Potistellung = map(data, 0, 1023, 1, 16);  // Mapping der Potistellung von 1 bis 15
  Faktor = Potistellung * 0.1; // Potistellung mit 0,1 multipliziert für sinnvollen Faktor
  Serial.print("Potentiometer bei Faktor ");
  Serial.print(Faktor);
  Serial.print("\t aktuelle Windschwelle: ");
  Serial.print(windSchwelle*(Faktor));
  Serial.println(F(" Km/h"));
  delay(messZeit);
  //Ausgabe der Windwerte
  static unsigned long lastprint;
  static unsigned long lastausloeser = 0;
  const unsigned long sperrZeit = 10000; // Wind Sperrzeit 10 Sek.
  if (millis() - lastprint >= messZeit)
  {
    lastprint = millis();
    Serial.print(F("Windgeschwindigkeit: "));
    Serial.print(Windgeschwindigkeit); // Ausgabe der Windgeschwindigkeit in Km/h
    Serial.println(F(" Km/h"));
  }
  Windmessung(messZeit);
  if (Auswertung(umlaufZeit))
  {
    Serial.println(F("Wind ausgelöst"));
    // Hier merken, das ausgelöst wurde:
    windAusgeloest = true;
    lastausloeser = millis();
    Serial.println(F("Auslöser gemerkt"));
  }
  if (windAusgeloest)
  {
    if (millis() - lastausloeser >= sperrZeit)
    {
      windAusgeloest = false;
      Serial.println(F("Ausloeser geloescht"));
    }
    }
  if (windAusgeloest == true) {
digitalWrite(WindPin, HIGH);    //Ausgang geschalten, wenn Wind ausgelöst
} else {
digitalWrite(WindPin, LOW);     //Ausgang aus, wenn Wind ausgelöst falsch
}
}

bool Auswertung(unsigned long intervall)
{
  static unsigned long lastmillis = 0;
  unsigned int wind = 0;
  unsigned int sturm = 0;
  bool ausloeser = false;
  if (millis() - lastmillis >= intervall)
  {
    Serial.println(F("Werte durchzaehlen:"));
    for (byte i = 0; i < sizeof(umlaufMerker); i++)
    {
      if (umlaufMerker[i] >= windSchwelle*(Faktor)) wind++;
      if (umlaufMerker[i] >= sturmSchwelle) sturm++;
      Serial.print(umlaufMerker[i]);
      Serial.print(F("\t"));
    }
    Serial.println();
    lastmillis = millis();
  }
  if ((wind >= 3) || (sturm >= 2))
  {
    ausloeser = true;
  }
  return ausloeser;
}

void Windmessung(unsigned long intervall) // Initalisierung und Berechnung für die Windgeschwindigkeit
{
  Serial.print("TEST3");
  static unsigned long lastMessung = 0;
  static unsigned int elementeZaehler = 0;
  if (millis() - lastMessung >= intervall)
  {
    detachInterrupt(digitalPinToInterrupt(AnemometerPin));
    Serial.println(windCounter);
    Windgeschwindigkeit = (float)(windCounter * 1.2) / (float)((millis() - lastMessung) / 1000);
    windCounter = 0;
    lastMessung = millis();
    attachInterrupt(digitalPinToInterrupt(AnemometerPin), countup, RISING);
    umlaufMerker[elementeZaehler] = (int)Windgeschwindigkeit;
    elementeZaehler++;
    if (elementeZaehler > (sizeof(umlaufMerker))) elementeZaehler = 0;
  }
}

void countup() // Zähler für die Impulse des Reed Kontakt
{
  Serial.print("TEST4");
  windCounter++;

}

Da ich heut eher weniger Zeit habe war das mit dem Screenshot eine schnelle aber unüberlegte Antwort.
Ich danke für die Hilfe und werde mich nochmal an den Code setzen.

Das hatte ich damals in dem Projekt, aus dem der Code ist, versucht. Das wird nix.
Der Umlauf müsste in 6,6 ms durch sein, was noch machbar wäre.
Der Aenometer hat zwei Auslöser (HIGH/LOW-Flanken) pro Umdrehung. Du musst zwingend beide erkennen.

Ok, soweit steck ich da nicht drin und ziehe meinen Tipp zurück.
Meine Idee wäre, das Projekt mit einem Arduino nachbauen. Wenn das läuft, auf anderen Controller umsetzen.

NEIN!!!
Keine seriellen Ausgaben in einer ISR!

Ich komm auch mit dem Bildschirmbild von oben nicht klar.
Kannst Du mal die Ausgabe aus dem SerMon hier einfügen? - Die, die Du bekommst, wenn der Code auf dem Controller ist.

@HotSystems
Der Code zu Beginn meines Threads funktioniert problemlos auf einem Arduino Pro Mini.
Beflügelt durch meinen Erfolg, dachte ich, den Serial Monitor über ein WebServer abrufen zu können wäre ja auch ganz nett und wollte dann erstmal den Code auf dem ESP zum Laufen bringen, was mich zum Eröffnen dieses Post brachte.

@my_xy_projekt

21:38:41.476 -> ⸮⸮⸮⸮g⸮s⸮⸮g|⸮d⸮l`#⸮e⸮|{⸮$⸮n⸮⸮o⸮l`⸮⸮s⸮l⸮le⸮⸮10 9 8 7 6 5 4 3 2 1 
21:38:46.669 -> TEST1ISR not in IRAM!
21:38:46.669 -> 
21:38:46.669 -> User exception (panic/abort/assert)
21:38:46.669 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
21:38:46.669 -> 
21:38:46.669 -> Abort called
21:38:46.669 -> 
21:38:46.669 -> >>>stack>>>
21:38:46.669 -> 
21:38:46.669 -> ctx: cont
21:38:46.669 -> sp: 3fffff70 end: 3fffffd0 offset: 0010
21:38:46.669 -> 3fffff80:  3ffe8807 fffffffc 00000004 40202b15  
21:38:46.669 -> 3fffff90:  40201530 3ffe8802 3ffee584 3ffee604  
21:38:46.669 -> 3fffffa0:  3fffdad0 00000000 3ffee584 40201439  
21:38:46.669 -> 3fffffb0:  feefeffe 00000000 3ffee5d8 40201f48  
21:38:46.669 -> 3fffffc0:  feefeffe feefeffe 3fffdab0 40100e8d  
21:38:46.669 -> <<<stack<<<
21:38:46.669 -> 
21:38:46.669 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
21:38:46.669 -> 
21:38:46.669 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
21:38:46.669 -> 
21:38:46.669 -> load 0x4010f000, len 3424, room 16 
21:38:46.669 -> tail 0
21:38:46.669 -> chksum 0x2e
21:38:46.669 -> load 0x3fff20b8, len 40, room 8 
21:38:46.669 -> tail 0
21:38:46.669 -> chksum 0x2b
21:38:46.669 -> csum 0x2b
21:38:46.669 -> v00042de0
21:38:46.669 -> ~ld

Na ja Gut zu wissen :wink: Dann könnte man doch ein Teiler davor basteln zB auf TTL Basis, dem whre das danach auch egal ob die Signale Symmetrisch oder nicht sind, bei einer Umdrehung nur einmal H / L am Ausgang. Habe vor entweder einen Anemometer kaufen oder basteln :wink:

Dann wäre es doch einfacher die im Pro mini erhaltenen Daten per UART auf den Wemos zu schicken und diese dann auf der Website anzuzeigen.

So bin ich auch mit meinen Arduino Projekten umgestiegen.
Waren zwar anfangs 2 Controller, hat aber problemlos funktioniert.

Zumal da ja dann auch noch der Webserver drauf laufen muss und evtl. auch noch OTA.