Projekte - Windradüberwachung - Teil 2

ich hatte immer gehört, das diese kleinen China-Windräder "Mist" sind.... Dann ist mir im Web mal ein günstiges Angebot in die Hände gefallen - da bin ich schwach geworden. Diese Dokumentation behandelt ein komplexes Projekt und ist daher umfangreich... Hier der Teil zur Software...

Hier geht es zu Teil 1....

Übersicht

 

Webseite
technische Hinweise
ESP-Programm erläutert
ESP-Programm download

 

Die Webseite als Endprodukt....
hier wollen wir hin...

Wie schon im Basics - Teile zum ESP32 erwähnt, gibt es eine recht einfache Möglichkeit, den ESP als Webserver zu programmieren - somit steht einer Abfrage definierter Werte und einer Fernsteuerung nicht's im Wege.

Die Webseite wird einfach aus einem beliebigen Browser heraus mit ihrer hausinternen ( in Eurem WLAN ! ) IP-Adresse aufgerufen.

Ich habe es mir auf einem alten Windows-Handy ( Kachelpower !! ) angelegt und auf die Startseite geschoben - so komme ich schnell dran.

 

Ist mir zu kompliziert..... =>.... zurück zur Startseite

 

Hinweise, technische Besonderheiten

Beim Programmieren und Testen sind mir einige Besonderheiten aufgefallen, welche zum Verständniss der nachfolgenden Programmierung erwähnt werden müssen.

  1. unsere Widerstände in den Spannungsteilern sind nicht immer genau wie der Nennwert, das hat bei den Messergebnissen Auswirkungen, speziell bei der Ermittlung der Spannung aus dem ACS712, da wir hier mit sehr kleinen Spannungen als Kriterium für die Strommessung bis 30A ( eigentlich -30 bis +30 Ampere ) arbeiten - wir müssen hier also kalibrieren. Das können wir vorab machen, indem wir an unseren Spannungsteiler eine definierte Eingangsspannung z.B. aus einem Labormessgerät anlegen und dann die Ergebniss-Spannung messen. Daraus ergibt sich dann der Korrekturfaktor.
  2. Wie ich feststellen musste, hat das WLAN einen direkten Einfluss nicht nur auf den Hall-Sensor des ACS712 sondern auch auf die Messergebnisse allgemein. Dies versuche ich durch eine programm-interne Kalibrierung auszugleichen.

  3. Neben der Möglichkeit eines WLAN-Webservers für die Kommunikation mit dem heimischen Rechner (bzw. meinem Handy) nutze ich auch die Möglichkeit des Updates über das WLAN ( nennt sich OTA ). Dadurch muss ich nicht bei jeder kleinen Änderung auf den Hof rennen (sind knapp 40m). Updates sollten NUR bei Stillstand des Rotors gemacht werden !!!

  4. Ich habe die Messung der Drehzahl des Rotors über die Frequenz in mittleren Drehzahlen mit einem optischen Messgerät extern gemessen - es passte recht gut. Allerdings scheint sich bei höheren Drehzahlen die Sinus-Kurve der Spannung ( siehe Dokumentation Hardware in Teil1...) mit den Einflüssen der beiden anderen Stromkreise (3-Phasen-Wechselstrom-Generator) manchmal zu überlagern - dann kommen astronomische Werte heraus... Diese habe ich im Programm dann ab 1000 U/min nicht mehr berücksichtigt...( da hätte sich das Windrad ohnehin längst selbst zerlegt).

Ist mir zu kompliziert..... =>.... zurück zur Startseite

Unser ESP-Programm....

Und jetzt zum eigentlichen Programm, ich teile es in die massgebenden Teilbereiche auf und erläutere diese - das gesamte Programm gibt es dann am Ende nochmal komplett als Download für die Arduino-Oberfläche und das ESP32-DevBoard....

Erläuterungen

(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)

[code]
/*   ursprünglicher Code Messtätigkeiten nach Az-Delivery, nutzt die adafruit-
 *   Bibliothek für den ADS1115, WLAN-Code von Wolles-Elektronik-Kiste und
 *   einem "unbekannten aber unvergessenen" Spender aus dem Web ( WLAN-reconnect)
 *   
 *   vorgesehen für einen automatischen regelmässigen Abruf der Daten über meinen
 *   RasPi - der läuft ja ständig durch... Später will ich es dann statistisch
 *   auswerten etc.
 *   
 *   
 *   ACHTUNG.. Variablenauflaufgefahr bei Nutzung ohne RasPi-Abruf (der löscht wieder)
 *   ampere0_mittel,volt1_mittel,leistung_mittel und zaehler summieren sich bei jedem
 *   Durchlauf und können/werden irgendwann einen Überlauf erzeugen, wenn nicht mit
 *   dem RasPi-Abruf die Summierten Werte wieder auf 0 gestellt werden !!!
 *   
 *   Variable als Integer mit max. Wertebereich int = +/-32768...wäre Problem...
 *   
 *   unsigned long (ULong) = 0 bis 4.294.967.295 alle 5sek messen => 60/5=12=>720/h=>17280/Tag
 *   => reicht jedenfalls...für zaehler mehrere Jahre...
 *   
 *   float = +/- 3,4*E38 auch kein Problem....
 *  
 *  
 *   Arbeitsweise, Grundlagen, Elektronik.....
 *   
 *   
 *   Das System misst letztendlich die Leistung (V*A=W) am ADS712 und ADS115 und bildet 
 *   einen Mittelwert über die Anzahl der erfolgreichen Messungen - durch die delay-Zeiten
 *   und unbekannte Antwortzeiten auf WLAN-Connect-Versuche etc. ist die KEIN direkter
 *   Messwert Leistung pro Zeitraum möglich !!! Der ESP kennt selbst keine Zeiten und 
 *   delay ist nicht immer zeitstabil.
 *   
 *   Wenn der RasPi dann in regelmässigen - zeitgesteuerten - Abfragen die Daten ab-
 *   ruft, muss dort eine Auswertung erfolgen - die mittlere Leistung und die Anzahl
 *   der Messungen ( nur als Qualitätskriterium für die Genauigkeit der Angabe der
 *   mittleren Leistung ) müssen vorerst als Grundlage reichen.
 *   
 *   
 *   Der ADS1115 wird vom ESP mit Spannung  !!!  3.3 Volt !!!! versorgt,
 *   die Spannung auf der Mess-Eingangs-Seite darf maximal 0.3 Volt höher und 
 *   minimal -0.3 Volt sein sonst ist der ADS1115 ggf. Schrott
 *   
 *   Der ACS712 wird vom ESP mit 5 Volt versorgt, die Spannung auf der Mess-Seite
 *   scheint wurscht, die Leistung hier max 30A...
 *   
 *   Die Massen GND sind zu koppeln
 *   
 *   SCL am ADS1115 wird mit ESP32-GPIO22  und SDA am ADS1115 mit ESP32-GPIO21 verbunden..
 *   
 *   Die 0-5 Volt Spannung des ACS712 ( Mittelwert soll 2.50 Volt sein ) MUSS
 *   mittels Spannungsteiler auf max. 3.333 Volt herunterskaliert werden, da der 
 *   ADS1115 mit dieser Spannung arbeitet  ( s.o. max. Mess-Spannung ADS1115 ) .
 *   
 *   Die 10-15 V Spannung der Batterieseite (angeblich bis 40 V aus dem Inverter) 
 *   MÜSSEN mittels Spannungsteiler s.o. ebenfalls auf max. 3.3333 V herunterskaliert werden.
*   
 *   Da wir somit MAX 3.333 Volt am ESP anliegen haben, kann die Messgenauigkeit von 
 *   TWOTHIRDS = 0.1875mV auf ONE = 0.125mV bei MAX 4V Messbereich gesetzt werden. 
 *   (siehe Erklärungen unter Punkt gain s.u.....)
 *   
 *   Bei der Strommessung am ACS712-30A ist die Differenz 66mV / 1 Ampere fliessenden
 *   Stroms - das wären bei Messbereich ONE dann real infolge des Spannungsteilers
 *   (5V/3.333V) * 0.125mV = 0.1875mV messbarer Unterschied und somit 66mV/0.1875mV = 
 *   352 Schritte und somit 0.1875/66 = 0.002841 A Messgenauigkeit => das sollte 
 *   ausreichend genau sein....
 *   
 *   Die bereits auf 5V-Niveau vom 3.333V-Messwert am ADS1115 zurückgerechnete Differenz-
 *   Spannung muss also nur durch 66mV = 0.066 V dividiert werden ( 1V = 1000mV/66mV =
 *   15,151515 Ampere...
 *   
 *   Die WLAN-Kommunikation läuft nach grundlegendem Quelltext von Wolles Elektronik-Kiste
 *   
 *   Da die Widerstände real nie genau dem Aufdruck entsprechen, muss der Anpassungsfaktor
 *   iterativ - beim ACS712 ohne Last - durch Gegenmessen ermittelt werden...
 *      
 *   Der ACS712 misst mit einem HALL-Sensor, der Magnetfelder nutzt...
 *   
 *   Es zeigt sich, das die Mess-Spannung des ACS712 von den Umgebungsbedingungen und der
 *   WLAN-Feldstärke abhängt - daher wird nach dem Einschalten eine automatische Kalibrierung
 *   ausgeführt, welcher den NULL-Wert des unbelasteten Sensors misst...
 *   
 *   Bei jedem Mess-Durchlauf wird geprüft, ob sich die WLAN-Feldstärke wesentlich geändert hat,
 *   wenn ja wird neu kalibriert - sofern nicht grad eine höhere Ampere-Zahl gemessen wird bzw. eine
 *   massgebliche Drehzahl vorhanden ist - sonst muss mit dem letzten ermittelten Wert weitergearbeitet 
 *   werden....
 *   
 *   Bei jedem Messdurchlauf wird geprüft, ob WLAN noch anliegt. GGf. wird versucht, sich neu
 *   zu verbinden (5x Software-Versuch ) - dann erfolgt ein Software-Neustart...
 *   
 *   VOR dem Neustart werden die Kennwerte ampere0_mittel,volt1_mittel,Leistung_Mittel, 
 *   Leistung_Max, volt_x und zaehler in den preferences abgespeichert - dort sollen sie auch 
 *   einen Neustart überstehen....
 *   
 *   1. Erweiterung
 *   
 *   
 *   Obwohl eine "händische" Sicherheitsschaltung bereits vorhanden ist  ( 3x100W Widerstände in
 *   Dreiecks-Schaltung als Bremse und Kurzschluss der 3 Wicklungen des Windrades als Haltebremse
 *   wird zusätzlich eine "Software-Bremse" gebaut.   
 *   
 *   Der ESP hält über GPIO4 = ON eine Spannung, welche einen Optokoppler "antreibt", zusätzlich
 *   gibt es eine Kreis-Sättigungsschaltung mit einem 2200myF-Kondensator, welche bei Reboot bzw.
 *   auch bei Stromausfall noch einige Sekunden aktiv bleibt.
 *   
 *   Dann schaltet der Optokoppler ab und auf der Mechanikseite schaltet ein PNP-Transistor durch 
 *   und aktiviert ein Relais - welches dann eine Zugmagnetschaltung aktiviert.
 *   
 *   Auch hier gibt es eine Sättigungsschaltung mit einem 4700müF Kondensator, welche "voll-läuft"
 *   und den Relaiskreis auf Min-Verbrauch reduziert. Das Relais fällt ab und der eingebaute
 *   Magnet hält die Kurzschluss-Schaltung fest
 *   
 *   Ist der Not-Stopp ausgelöst, muss das System von Hand zurückgesetzt werden...
 *   
 *   
 *   2. Erweiterung
 *   
 *  Eine Wechselspannung unterschiedlicher Frequenz zwischen 2 Phasen am Generator
 *  wird mittels Widerstand und Optokoppler abgegriffen - da im Optokoppler selbst
 *  eine Diode vorhanden ist, wird nur eine Halbwelle der Sinuswelle übertragen.
 *  
 *  Der Widerstand wird als Potentiometer 2k ausgeführt und kann dann auf die vorhandenen
 *  Spannungen justiert werden, so dass der Optokoppler "durchschaltet". Dies erfolgt
 *  iterativ in Abhängigkeit der Drehzahl - gemäss kollino-de für 5v etwa 350 Ohm und für
 *  15 V etwa 1.35 kOhm - besser wäre allerdings eine Zenerdiode..... 
 *  
 *  ***************  
 *  ACHTUNG:
 *  
 *  zwischenzeitlich wurde eine Zener-Diode 3.3Volt (??) eingebaut, die Spannung am Optokoppler
 *  ist somit bei allen Quellenspannungen auf diesen Wert begrenzt....
 *  
 *  ****************

 *  Auf der Seite des ESP wird der Pin 34 als Input max. 3.3 Volt ausgelesen und die 
 *  Hoch-Werte werden gezählt....- da die Werte an- und abschwellen muss "solange HIGH" 
 *  als Kriterium genutzt werden...

 *  Eine PULL-DOWN-Schaltung am o.g. Eingangspin 10k PIN zieht den Messpin ohne Spannungs- 
 *  eingang auf GND...( sonst flattert er... )
 *   
 *      ACHTUNG....
  
 *  ALLE MESSVORGÄNGE VOR DER WLAN-KOMMUNIKATION MACHEN, DANN KANN SICH WLAN
 *  BERUHIGEN WÄHREND DER PAUSE  VON 3 sek
 *  
 *     ACHTUNG....
 *     
 *  Die Pins mit ACD2-Wandler werden auch für WLAN genutzt - dies verfälscht eine Messung !!!
 *  Also einen anderen PIN nehmen !!!
 *  Die while-Schleifen müssen einen "Notausgang" haben, da sie sonst hängen, falls sich das
 *  Windrad nicht während der gesamten Messung durchgängig dreht...
 *  
 *  3. Erweiterung
 *  
 *  Einbau einer WLAN-Updatefähigkeit mit der Arduino-OTA
 *  
 * 4. Anpassung 
 * 
 * zaehler wird unsigned long, Begrenzug freq_max auf 100 aufgrund gelegentlicher
 * Ausbrüche bis 20.000 und mehr begrenzt..
 *  
 * 5. Anpassung 
 * 
 * Es wird ein zusätzlicher Link für manuelles Rücksetzen der Summierungswerte per Fernsteuerung
 * implementiert...
 * 
 */

[/code]

Wie ihr seht, ist das Programm mit der Zeit immer weiter gewachsen - die Erläuterungen habe ich für mich gemacht, um meine Schritte und die Hintergründe nachvollziehen zu können - zu Teilen gibt es bei der eigentlichen Programmstelle dann noch weitere Erläuterungen

Ist mir zu kompliziert..... =>.... zurück zur Startseite

Bibliotheken und Definitionen

(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)

[code]

// Variablen, Bibliotheken einbinden

// ******* für die WLAN-Kommunikation.....******


// für das Updaten über WLAN
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>


// für die WEB-Antwort des Programmes
#include <WebServer.h> 
#define PORT 80

const char* ssid = " ******* ";             // der Name Eures WLAN !!!
const char* pass = " ******* ";             // das Password Eures WLAN !!!

WebServer server(PORT); 

// dies sind die Befehls-Links zu den Prozeduren und
// Ausgabe-Webseiten - die Seiten können auch mit z.B.
// ".ip-adresse./schalten1" direkt aufgerufen werden

String link_1= "<a href=\"/momentan\">Momentanwerte abrufen...</a>";
String link_2= "<a href=\"/mittel\">Mittelwerte abrufen...</a>";
String link_3= "<a href=\"/calibrate\">WLAN-Werte kalibrieren...</a>";
String link_4= "<a href=\"/stoppen\">Not-Stopp ausloesen...</a>";
String link_5= "<a href=\"/neustart\">Neustart ausloesen...</a>"; // nur temp
String link_6= "<a href=\"/ruecksetzen\">Mittelwerte zuruecksetzen...</a>"; // nur temp
// es gibt einen siebten unsichtbaren link, der die Mittelwerte abruft
// und dann zurücksetzt - nur für die Abfrage durch den RasPi gedacht...



//***********für die Mess-Tätigkeiten Strom und Spannung  *******

#include <Wire.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
int16_t adc0 , adc1;                   // Messkanal A0 und A1 werden verwendet - direkt auf GND gemessen

// GLOBALE Variablen...

unsigned long zaehler = 0;             // wir zählen die Durchläufe zwischen den Browser-Abfragen...
float ampere0_Mittel = 0.00000;        // Mittelwert für gemessene Ampere - summierend
float volt1_Mittel = 0.00000;          // Mittelwert für gemessene Spannung ( Bereich 12 V )summierend
float Leistung_Mittel = 0.00000;       // Mittelwert Leistung des Abrufzeitraums
float ampere0 = 0.0000;                // temporärer Messwert
float volt1 = 0.0000;                  // temporärer Messwert
float volt0 = 0.0000;                  // temporärer Messwert
float adc0_mittel = 0.0000;            // i2c Werte werden addiert und durch Anz Messungen gemittelt
float adc1_mittel = 0.0000;            // i2c Werte werden addiert und durch Anz Messungen gemittelt
float Leistung_Max = 0.0000;           // Absolutwert - durchs Speichern über gesamte Zeit
float Ampere0_Max = 0.0000;             // Absolutwert - durchs Speichern über gesamte Zeit
float volt_x = 2.5100;                 // Grundwert ACS712 - ohne Last - wird später noch kalibriert..
long rssi_x = -80;                     // letzte massgebende WLAN-Feldstärke
long rssi_y = -80;                     // aktuelle WLAN-Feldstärke
float R0_Korr = 1.492537;              // zentraler Korrekturwert für Widerstandsverhältnisses Strommessung
float R1_Korr = 12.0001;               // zentraler Korrekturwert für Widerstandsverhältnisses Spannungsmessung 0-40V

// ************** für das Abspeichern der Daten ****************


// es werden "Ordner" und "Dateien" verwaltet - besser scheint die Denkweise
// archiv und eintrag....
#include <Preferences.h>
Preferences preferences;


// ************** für die Frequenzmessung und Drehzahlberechnung ****************

int FREQ_PIN = 34; // ein adc-pin ohne internen widerstand pull - KEINEN WLAN-Pin verwenden !!!
unsigned long lastmicro, micro_mess_A, micro_mess_E ; // für die Zeitmessung
double freq, freq_max; // die Frequenz
int drehz;   // die Drehzahl




[/code]

            

#include bindet die "Spezial"bibliotheken als Unterprogramme mit ein, ihr findet sie in der Arduino-Oberfläche im Bibliotheksverwalter. Jede Bibliothek bringt auch Testprogramme mit - schaut Sie Euch mal an. Es gibt für fast alle Hardware bzw. Anwendungen fertige Bibliotheken.
int, float, double etc.das sind die jeweiligen Variablentypen, hier müsst Ihr mal das Web bemühen - es gibt einfach zu viele Typen um es hier zu erklären...

z.B.

Preferences preferences

die Variable preferences wird der Bibliothek Preferences zugewiesen, damit greifen wir später dann darauf zu (ACHTUNG  P ist nicht p..)

Ist mir zu kompliziert..... =>.... zurück zur Startseite

 

void setup - der erste - einmalige - Durchlauf

(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)

[code]


//***********************************************
//***********************************************
// Definitionssequenz beim ersten Durchlauf...
//***********************************************
//***********************************************



void setup() {

  Serial.begin(115200); // zum seriellen Monitor Frequenz einstellen

  //*********** zuerst mal den Pin 4 aktivieren - für Notschaltung
  pinMode(4, OUTPUT);
  digitalWrite (4, HIGH ); // es fliesst Strom und der Optokoppler bleibt an

  
  // ******* für die WLAN-Kommunikation.....******

  Serial.print("Connecting to: ");
  Serial.println(ssid);
 
  
  // warten bis WLAN verbunden ist....... 
  // hier würde er ohne Rückmeldemöglichkeit ohne WLAN hängen, bis WLAN da ist, 
  // wir starten daher nach 5 Versuchen neu...damit sich etwas tut...
  int wifi_retry = 0;
  while( (WiFi.status() != WL_CONNECTED) && ( wifi_retry < 5) ){
      wifi_retry++;
      WiFi.begin(ssid, pass);
      delay(5000); // über die Mesh dauert es ggf. etwas länger...
      Serial.print(".");
      }
  if ( wifi_retry >= 5){
      ESP.restart();
      }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP-Address of ESP32 module: ");
  Serial.println(WiFi.localIP());


  // für das Updaten
  
  ArduinoOTA.setHostname("Wind_ESP");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.begin();



  // handleRoot ist die Startseite bei Aufruf mit der IP-Adresse
  // die anderen sind die Subseiten s.o.
  server.on("/",handleRoot);
  server.on("/momentan", momentan_1);
  server.on("/mittel", mittel_1);
  server.on("/calibrate", calibrate_1);
  server.on("/stoppen", stoppen_1);
  server.on("/neustart", neustart_1);
  server.on("/ruecksetzen", ruecksetzen_1);
  server.on("/RasPi", RasPi_1); // unsichtbarer Link - nur für den RasPi-Abruf
  server.begin();

  // 5 sek warten, damit WLAN sich etabliert hat....
  delay(5000); 
  
  // für die ERSTKALIBRIERUNG - hier die aktuelle WLAN-Stärke ermitteln
  // die Werte gehen von -0 bis -100 dBm - gut ist -30dBm schlechter wäre dann
  // z.B. -50 dBm
  rssi_x = WiFi.RSSI();
  Serial.print("aktuelle WLAN-Stärke [dBm] ");
  Serial.println(rssi_x);

  // 5 sek warten, damit WLAN sich etabliert hat....
  delay(5000);


  // ************** für das Abspeichern der Daten ****************

  // Wir lesen ggf. bei einem vorherigen Software-Neustart gespeicherte Daten 
  // aus und setzen diese Einträge dann auf den Vorgabewert - löschen geht
  // nicht - dann könnten wir später nicht schreiben...

  // einen "Ordner" anlegen/verwenden = Archiv...
  preferences.begin("Daten", false);
  // Variable aus Dateien "Name der Variable" lesen = Einträge...
  // wenn nicht vorhanden gibt es einen Vorgabewert....
  ampere0_Mittel = preferences.getFloat("Ampere_Mittel", 0);
  volt1_Mittel = preferences.getFloat("Volt_Mittel", 0);
  volt_x = preferences.getFloat("Volt_Cal", 2.51);
  Leistung_Mittel = preferences.getFloat("Watt_Mittel", 0);
  Leistung_Max = preferences.getFloat("Watt_Max", 0);
  Ampere0_Max = preferences.getFloat("Ampere_Max", 0);
  freq_max = preferences.getDouble("Freq_Max", 0);
  zaehler = preferences.getULong("Counter", 0);
  // Variable in Dateien "Name der Variable" schreiben = Einträge...
  preferences.putFloat("Ampere_Mittel", 0);
  preferences.putFloat("Volt_Mittel", 0);
  preferences.putFloat("Volt_Cal", 2.51);
  preferences.putFloat("Watt_Mittel", 0);
  preferences.putFloat("Watt_Max", 0);
  preferences.putFloat("Ampere_Max", 0);
  preferences.putDouble("Freq_Max", 0);
  preferences.putULong("Counter", 0);
  preferences.end();


  //***********für die Mess-Tätigkeiten Strom und Spannung *******

  // Einstellen der Messgenauigkeit - max. V am ADS1115 beachten !!!!
  // wäre beim ESP bei mir also 3.3 Volt....
  
  //gain
  // ads.setGain(GAIN_TWOTHIRDS);// 2/3x +/- 6.144V 1bit = 0.1875mV default
  ads.setGain(GAIN_ONE); // 1x +/- 4.096V 1bit = 0.125mV
  // ads.setGain(GAIN_TWO); // 2x +/- 2.048V 1bit = 0.0625mV
  // ads.setGain(GAIN_FOUR); // 4x +/- 1.024V 1bit = 0.03125mV
  // ads.setGain(GAIN_EIGHT); // 8x +/- 0.512V 1bit = 0.015625mV
  // ads.setGain(GAIN_SIXTEEN); // 16x +/- 0.256V 1bit = 0.0078125mV
  ads.begin();


  // ERSTKALIBRIERUNG nach aktueller lokaler WLAN-Stärke s.o.
  // Mehrfachmessung für Fehlerausgleich 0+1+2...+9 <10 sind 10 Durchläufe
  int adc_x = 0;
  for (int i=0;i<100;i++){
      adc_x += ads.readADC_SingleEnded(0);
  }
  // und Mittelwertbildung als INT sowie NULL-Voltwert ACS712
  adc_x = round (adc_x / 100 );
  volt_x = ads.computeVolts(adc_x)* R0_Korr;  // Nullwert ACS712 bei aktuellem WLAN....



  // ************** für die Frequenzmessung und Drehzahlberechnung ****************

  // zuerst mal den LESE-PIN aktivieren, per Pull-Down runtergezogen auf 0
  pinMode(FREQ_PIN, INPUT);



  } // ENDE SETUP


[/code]

was machen wir....

  1. wir starten den Kommunikationskanal zum Seriellen Monitor der Arduino-Oberfläche - nach dort können wir Kontroll-Meldungen mit Serial.print... ausgeben.
  2. Wir starten das WLAN und verbinden uns. Ich habe in meinem Router eingestellt, das der ESP immer die gleiche IP-Adresse bekommt und NICHT aus dem WLAN raus darf....(ins Internet).
  3. Wir starten die OTA-Software um später per WLAN updaten zu können.
  4. Wir definieren unsere spätere Webseite.
  5. Wir lesen unsere Variablen-Bibliothek ( falls bereits vorhanden, sonst werden Standardwerte gelesen) und schreiben sie dann gleich wieder, sonst wäre sie beim nächsten Start ja nicht da.... Ein Update des ESP löscht eine ggf. vorhandene Variablen-Bibliothek ! ein Neustart nicht...
  6. Wir stellen die "Auflösung" unseres Mess-Chips ADS1115 ein => siehe Erläuterung s.o. bzw. Handbuch...
  7. Erstkalibrierung unseres Mess-Systems nach der aktuellen WLAN-Stärke ( wir messen die Spannung und multiplizieren sie mit unserem Korrekturwert für den Spannungsteiler => wir haben eine Eingangs-Vergleichsspannung bei "ruhendem System"), die aktuelle WLAN-Stärke haben wir kurz vorher auch gespeichert und dann sicherheitshalber 5 sek gewartet, damit das WLAN seine "Abstimmungen" erledigt hat und halbwegs im Ruhezustand ist...
  8. Zuweisung eines PIN's am ESP für die Frequenzmessung...

Ist mir zu kompliziert..... =>.... zurück zur Startseite

 

void root - der sich immer wiederholende Durchlauf

(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)

[code]



  //***********************************************
  //***********************************************
  // ständig wiederholender "Kreisdurchlauf"
  //***********************************************
  //***********************************************





void loop() {

  //***********für die Mess-Tätigkeiten Strom und Spannung *******

  //  ** die Mess-Seite Strom über den ACS712

  // max. 5V mit Spannungsteiler: + => 10k => ESP => 20k => GND
  // auf 3.333 Volt umgesetzt => rechnerischer Faktor 5/3.333 = 1.5000015
  // durch Kabel,WLAN,ungenaue Widerstände muss dieser Faktor kalibriert werden
  // siehe unten..... 
  // Der angebliche NULL-Wert des ACS712 sind 2.50 Volt bei 0 Ampere
  // Stromfluss - für jedes Ampere erhöht/verringert sich die Voltzahl
  // um 66mV = 0.066 Volt - eine entsprechende Mess- und Rechengenauigkeit
  // ist also sinnvoll...

  // Mehrfachmessung für Fehlerausgleich 0+1+2...+9 <10 sind 10 Durchläufe
  adc0 = 0.0000;
  adc0_mittel = 0.0000;
  for (int i=0;i<50;i++){
      adc0 = ads.readADC_SingleEnded(0);
      adc0_mittel = adc0_mittel + adc0;
  }
  // und Mittelwertbildung als INT
  adc0 = round (adc0_mittel / 50 );
     
  // Dieser Faktor muss genau ermittelt werden -  er ist von den Widerständen
  // und deren Genauigkeit abhängig  - 19.9kQhm - 20.000kOhm - 20.100 kOhm
  // sind ein Unterschied...Übersetzung der Widerstände möglichst OHNE WLAN
  // messen und Faktor ermitteln...
  volt0 = ads.computeVolts(adc0) *  R0_Korr; // z.B. gemessen 1.675  errechnet 2.514 Soll 2.50 ohne Last
  Serial.print("Volt an pin A0: ");
  Serial.println(volt0,5);

  // gemessene Spannung - Null-Wert = Differenzspannung //// 66mV/Ampere=0.066V/Ampere
  // eine Abweichung des Nullwertes von 2.51V zu 2.50V = 0.01V / 0.066 = 0.1515 A
  ampere0 = ( volt0 - volt_x ) / 0.066;
  Serial.print("Stromfluss (A) : ");
  Serial.println(ampere0,3);

  // für Mittelwertbildung aufsummieren
  ampere0_Mittel = ampere0_Mittel + ampere0;

  delay(1000); // notwendig für Kanalwechsel am ADS1115



  //  ** die Messseite auf 0-15 Volt ( angeblich max. 40 Volt) Spannung

  // max. 40V mit Spannungsteiler: + => 220k => ESP => 20k => GND
  // auf 3.3333 Volt umgesetzt => rechnerischer Faktor 40/3.3333 = 12.0001 
  // dieser Faktor muss ebenfalls kalibriert werden s.u.

  // Mehrfachmessung für Fehlerausgleich
  adc1 = 0.0000;
  adc1_mittel = 0.0000;
  for (int i=0;i<50;i++){
      adc1 = ads.readADC_SingleEnded(1);
      adc1_mittel = adc1_mittel + adc1;
  }
  // und Mittelwertbildung als INT
  adc1 = round (adc1_mittel / 50 );

  // Dieser Faktor muss genau ermittelt werden -  er ist von den Widerständen
  // und deren Genauigkeit abhängig  - 19.900kQhm - 20.000kOhm - 20.100 kOhm
  // sind ein Unterschied...Übersetzung der Widerstände möglichst OHNE WLAN
  // messen und Faktor ermitteln...
  volt1 = ads.computeVolts(adc1)*  R1_Korr;
  Serial.print("Volt an pin A1: ");
  Serial.println(volt1,3);

  // für Mittelwertbildung aufsummieren
  volt1_Mittel = volt1_Mittel + volt1;

  delay(1000); // notwendig für Kanalwechsel am ADS1115


  // für Mittelwertbildung der erfolgten Messungen V/A zaehler hochzählen 
  zaehler = zaehler + 1 ;
  


  //  **********  Mittelwertbildung für Weitergabe  **********

  // Mittelwertbildung Leistung aus Ampere * Volt / Anzahl Messungen
  // wird bei jedem Durchlauf aktuell neu berechnet...
  Leistung_Mittel = (ampere0_Mittel / zaehler) * (volt1_Mittel / zaehler);

  // Weitergegeben werden dann bei Aufruf über WLAN Leistung_M, der
  // RasPi kennt die Frageintervalle und kann daraus die Leistung/Zeit berechnen.... 
  // zaehler und Mittelwert-Summierung wird dann in der Antwort-Prozedur wieder auf 0 gesetzt.... 

  // Maximalwertbildung Leistung...aus aktuellen Messwerten
  if ( (ampere0 * volt1) > Leistung_Max ){
    Leistung_Max = ( ampere0 * volt1);
    }

  // Maximalwertbildung Ampere...aus aktuellen Messwerten
  if ( (ampere0) > Ampere0_Max ){
    Ampere0_Max = ( ampere0 );
    }


// ************** für die Frequenzmessung und Drehzahlberechnung ****************

  // wir müssen prüfen, ob überhaupt eine Spannung am Generator vorhanden ist
  // da sonst die nachfolgende Frequenzmessung hängen bleibt, da while.....Schleifen 
  // verwendet werden...freq und drehz wird hier auch als Steuervariable 1/0 verwendet..
  // 1.000.000 micros = 1 sek
  
  freq=0;
  drehz=0;
  lastmicro = micros();    // für die Abbruchsteuerung, falls das in der Messung Windrad stehen bleibt...
  micro_mess_A = lastmicro; // Zeitpunkt_Mess-Anfang
  micro_mess_E = lastmicro; // Zeitpunkt _Mess-Ende

  // wir testen 1.000.000 microsekunden = 1 sek lang...
  while ( (micros() - lastmicro) < 1000000 ){ 
        if ( 1 == digitalRead(FREQ_PIN)) {
           freq=1; // als Kennung - wir haben einen positiven Pegel gefunden...
           }
        } // endwhile
        
  // NUR - wenn ein pos. Pegel gefunden wurde...sprich das Rad dreht sich..
  if ( freq == 1) {  // nur beginnen wenn pos. Ladung vorhanden war

      freq = 0;    // zurücksetzen in jeder Schleife...
      drehz = 0 ;  // zurücksetzen in jeder Schleife, wird auch als Steuervariable genutzt

      // schwellende Messwerte synchronisieren - mit Notausgang...

      lastmicro = micros();
      while ( 0 == digitalRead(FREQ_PIN) ) {
         if ( ( micros() - lastmicro) > 1000000 )  { // Abbruch, wenns zu lange dauert...
            drehz=-1; // Kennzeichen das es Probleme gab - Messwert unbrauchbar...
            break;
            }
          } // endwhile
          
      lastmicro = micros();          
      while ( 1 == digitalRead(FREQ_PIN) ) {
         if ( ( micros() - lastmicro) > 1000000 ) { // Abbruch, wenns zu lange dauert...
             drehz=-1; // Kennzeichen das es Probleme gab - Messwert unbrauchbar...
             break;
             }
          } // endwhile
                  
      micro_mess_A = micros(); // jetzt wechselt er von HIGH auf LOW  = Startzeit


      // Durchlaufschleife für 50 Wechsel HIGH-LOW.... - mit Notausgang
      // 50 Hz sind 50 Wechsel/sek = 50 Peaks/sek d.h. für 100 Wechsel müssten
      // wir 2 sek durchgängig - ohne Fehler - messen...


      for ( int i = 0; i < 50; i++) {

          lastmicro = micros();
          while ( 1 == digitalRead(FREQ_PIN) ) {
             if ( ( micros() - lastmicro) > 1000000 ){ // Abbruch, wenns zu lange dauert...
                 drehz=-1; // Kennzeichen das es Probleme gab - Messwert unbrauchbar...
                 break;
                 }
              } // endwhile

          lastmicro = micros();
          while ( 0 == digitalRead(FREQ_PIN) ) {
             if ( ( micros() - lastmicro) > 1000000 ) { // Abbruch, wenns zu lange dauert...
                drehz=-1; // Kennzeichen das es Probleme gab - Messwert unbrauchbar...
                break;
                }
              } // endwhile

          if ( drehz == -1 ){
              break; // es gab Probleme, wir machen mit der for... nicht mehr weiter...
              }
              
          }// for int i
     
      micro_mess_E = micros(); // jetzt wechselt er von LOW auf HIGH  = Endzeit

      //  Auswertung  Eingangswert freq = 1  und drehz = 0  bzw. -1 (abgebrochen)

      // für 50-Perioden s.o. haben wir x microsekunden gebraucht....
      // 1sek = 1.000.000 microsekunden => freq = ANZ * ( 1.000.000 / micros )

      // Vermeidung Diff/0 und Vermeidung von unbrauchbaren Messwerten...
      // Wertevergleich   ==   bzw. != sind die Operatoren....
      // nach etwa 78 Stunden nullt sich angeblich die interne micros-Schleife am ESP,
      // wenn wir dann messen ist ende < anfang, wir rechnen nur wenn die beiden Messwerte
      // passend sind - dann gibt es auch keine Div/0...
      
      if ( (micro_mess_E > micro_mess_A) && (drehz != -1) ){

          // aktuelle Frequenz errechnen...
          freq = 50 * ( 1000000.0 / ( micro_mess_E - micro_mess_A) );
          
          // Es kommt gelegentlich zu Ausrutschern der Messergebnisse und sehr hohen angeblichen 
          // Frequenzen - da aber eine Frequenz von 100 Hz einer Drehzahl von 1000 U/min entspräche 
          // und diese aber sehr unwahrscheinlich ist.....das Windrad wäre längst auseinandergeflogen !!

          if ( freq < 100 ){

              //Drehzahl errechnen...
              // wir haben mehrere Periodenwechsel je Umdrehung....erst mal 6 angenommen...
              // 1 min = 60 sek....=> U/min...
              drehz = round ( 60 * freq / (6) );

              // ggf. als Maximalwert übernehmen...
              if (freq > freq_max){ 
                  freq_max = freq;
                  }
            
              } // if freq < 100
              else{
              freq=-1;
              drehz=-1;
              }  // end else if freq < 100

        } // Ende micro+drehz<>-1
        else{    // FEHLMESSUNG
        freq=-1;
        drehz=-1;
        } // endelse micro+drehz<>-1
        
      } // Ende Eingangsbedingung das ein pos. Messwert vorliegt... also freq = 1...
      else{   // DREHT SICH NICHT
      freq = 0;
      drehz = 0;
      } // end else Eingangsbedingung das ein pos. Messwert vorliegt...



  // ERGEBNISS:
  // wir haben jetzt entweder einen brauchbaren Wert für Frequenz und Drehzahl...
  // oder beide Werte sind NULL (dreht sich nicht ) oder beide Werte sind -1(Fehlmessung)....




  // ******* für die WLAN-Kommunikation.....******


  // auf einen notwendigen WLAN-Neustart prüfen - dann sind noch
  // die letzten gültigen WLAN-volt_x-Faktoren vorhanden....
  int wifi_retry = 0;
  while( (WiFi.status() != WL_CONNECTED) && ( wifi_retry < 5) ){
      wifi_retry++;
      WiFi.disconnect();
      WiFi.mode(WIFI_OFF);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, pass);
      delay(5000); // wird nicht gezählt, es gibt auch keinen Messwert dafür
                   // über die Mesh dauert es ggf. etwas länger...
  }
  if(wifi_retry >=5){
      // Wir speichern die letzten Daten vor dem Neustart in preferences..
      // einen "Ordner" anlegen/verwenden = Archiv...
      preferences.begin("Daten", false);
      // Variable in Dateien "Name der Variable" schreiben = Einträge...
      preferences.putFloat("Ampere_Mittel", ampere0_Mittel);
      preferences.putFloat("Volt_Mittel", volt1_Mittel);
      preferences.putFloat("Volt_Cal", volt_x); //
      preferences.putFloat("Watt_Mittel", Leistung_Mittel);
      preferences.putFloat("Watt_Max", Leistung_Max);
      preferences.putFloat("Ampere_Max", Ampere0_Max);
      preferences.putDouble("Freq_Max", freq_max);
      preferences.putULong("Counter", zaehler);
      preferences.end();
      // und Neustart...
      ESP.restart(); // Die bisher gesammelten Daten sollten gespeichert sein...
  }


    
  //**  er fragt bei jedem Durchlauf ob eine Anfrage vorliegt und beantwortet


  // für das Updaten
  if ( (WiFi.status() == WL_CONNECTED) ){ // Absturz bei fehlendem WLAN vermeiden
    ArduinoOTA.handle();
  }
  
  // diese ggf. und arbeitet ansonsten ungerührt weiter .....
  // Kein WLAN ist natürlich auch keine Antwort....
  if ( (WiFi.status() == WL_CONNECTED) ) { // Absturz bei fehlendem WLAN vermeiden
     server.handleClient();
     }



  // ** aktuelle lokale WLAN-Stärke - AUTOMATISCHE NACHKALIBRIERUNG
  
  // die Werte gehen von -0 bis -100 dBm - gut ist -30dBm schlechter wäre dann
  // z.B. -50 dBm
  // Kein WLAN heisst wir arbeiten mit dem letzten Wert weiter.....

  if ( (WiFi.status() == WL_CONNECTED) ) { // Absturz bei fehlendem WLAN vermeiden

      // aktuelle WLAN-Stärke messen
      rssi_y = WiFi.RSSI();
      
      // Wenn sich die WLAN-Stärke massgeblich geändert hat...
      if ((( abs(rssi_y) - abs(rssi_x)) > 3) || (( abs(rssi_x) - abs(rssi_y) ) > 3 ))  {

      // ABER nur wenn der Ampere-Wert < 0.25A - sprich keine massgebende Leistung fliesst...
      // und wenn die Drehzahl < 20 U/min ist (auch wenn NULL ) ABER NICHT -1 (Messfehler infolge
      // freq > 100...)
      
      if ( ( abs(ampere0) < 0.25 ) && ( drehz < 20 ) && (drehz != -1) ){
      
          // Warten bis WLAN sich beruhigt hat...
          delay(3000); // wird nicht gezählt, es gibt auch keinen Messwert dafür
        
          // Mehrfachmessung für Fehlerausgleich 0+1+2...+9 <10 sind 10 Durchläufe
          int adc_x = 0;
          for (int i=0;i<100;i++){
                adc_x += ads.readADC_SingleEnded(0);
          }
          // und Mittelwertbildung als INT sowie NULL-Voltwert ACS712
          adc_x = round (adc_x / 100 );
          volt_x = ads.computeVolts(adc_x)*  R0_Korr; 
          
          // Meldung machen
          Serial.print("alte WLAN-Stärke [dBm] ");
          Serial.println(rssi_x);
          Serial.print("aktuelle WLAN-Stärke [dBm] ");
          Serial.println(rssi_y);
         
          // der bisherige WLAN-Wert wird aktualisiert..
          rssi_x=rssi_y;
         
          } // ampere0 < 25
        } // WLAN geändert
    }// WLAN vorhanden

    
  // Allgemeine Pause....
  delay(3000); // wird nicht gezählt, es gibt auch keinen Messwert dafür


} // ENDE LOOP



[/code]

 

Hmpfff.... ich denke ich habe im Programm alles ausführlich dokumentiert....

ArduinoOTA.handle()prüft auf einen OTA-Updatebefehl...
server.handleClient()prüft auf eine Webseitenanfrage und reagiert dann drauf => Subprozeduren...

 Bei beiden Aufrufen gilt - wenn keiner fragt, geht es ungerührt weiter im Text....

Ist mir zu kompliziert..... =>.... zurück zur Startseite

 

void "Subprozedur" - Unterprozeduren mit Aufruf aus Hauptprogramm

(Achtung - der Text [code].....[/code] gehört NICHT zum Programm..)

[code]




//********************************************
//************ die Subproceduren**************
//********************************************


void handleRoot() {
  // die Startseite....
  String message="<h1>Windrad-Steuerung</h1>";
  message += "</BR></BR>";
  message += link_1;
  message += "</BR></BR>";
  message += "</BR></BR>";
  message += link_2;
  message += "</BR></BR>";
  message += "</BR></BR>";
  message += link_3;
  message += "</BR></BR>";
  message += "</BR></BR>";
  message += link_4;
  message += "</BR></BR>";
  message += "</BR></BR>";
  message += link_5;
  message += "</BR></BR>";
  message += "</BR></BR>";
  message += link_6;
  // link7 wird nicht gesendet - ist verborgen nur für den RasPi-Abruf
  server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
}


void calibrate_1(){ // nur für die Ausgabe per Web-aktuelle Werte
  
  // aktuelle WLAN-Feldstärke messen - da wir grad übr WLAN aufgerufen haben ohne weitere Sicherung
  // der bisherige WLAN-Wert wird aktualisiert..
  rssi_x = WiFi.RSSI();
          
  // Warten bis WLAN sich beruhigt hat...
  delay(3000); // wird nicht gezählt, es gibt auch keinen Messwert dafür
        
  // ABER nur wenn der Ampere-Wert < 0.25A - sprich keine massgebende Leistung fliesst...
  // und wenn die Drehzahl < 20 U/min ist (auch wenn NULL )ABER NICHT -1 (Messfehler infolge
  // freq > 100...)
  
      if (( abs(ampere0) < 0.25 ) && ( drehz < 20 ) && (drehz != -1) ) {
      // Mehrfachmessung für Fehlerausgleich 0+1+2...+9 <10 sind 10 Durchläufe
      int adc_x = 0;
      for (int i=0;i<100;i++){
          adc_x += ads.readADC_SingleEnded(0);
          }
      // und Mittelwertbildung als INT
      adc_x = round (adc_x / 100 );
      volt_x = ads.computeVolts(adc_x)*  R0_Korr;    

      String message = "</BR></BR>Kalibrierte Spannung [V]:  ";
      message += String(volt_x, 3); // float to String, three decimal places
      server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
      }
      else
      {
      String message = "</BR></BR>...geht grad nicht...Stillstand abwarten:  ";
      server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
      }
}




void momentan_1(){
  // Anzeige der Momentan-Messwerte Volt + Ampere + aktuelle Leistung
  String message = "</BR></BR>aktuelle Batterie-Spannung [V]:  ";
  message += String(volt1, 3); // float to String, three decimal places
  message += "</BR></BR>     aktuelle Mess-Spannung [V]:  "; 
  message += String(volt0, 3); // float to String, three decimal places
  message += "</BR></BR>     aktuelle kalibrierte NULL-Spannung [V]:  "; 
  message += String(volt_x, 3); // float to String, three decimal places
  message += "</BR></BR>     aktueller Stromfluss [A]:  ";
  message += String(ampere0, 3); // float to String, three decimal places
  message += "</BR></BR>     aktuelle Leistung [W]:  ";
  message += String((ampere0 * volt1), 3); // float to String, three decimal places
  message += "</BR></BR>"; // Leerzeile
  message += "</BR></BR>     letzte Feldstaerke [dBm]:  ";
  message += String(rssi_x); // long to String, no decimal places
  message += "</BR></BR>     aktuelle Feldstaerke [dBm]:  ";
  message += String(rssi_y); // long to String, no decimal places
  message += "</BR></BR>"; // Leerzeile  
  message += "</BR></BR>     aktuelle Frequenz [Hz = 1/s]:  ";
  message += String(freq); // long to String, no decimal places
  message += "</BR></BR>     aktuelle Drehzahl [U/min]:  ";
  message += String(drehz); // long to String, no decimal places
  server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
}



void mittel_1(){
  // Anzeige der aktuellen Mittelwerte - OHNE zurücksetzen....
  String message = "</BR></BR>aktuelle mittlere Leistung [W]: ";
  message += String(Leistung_Mittel, 3); // float to String, three decimal places
  message += "</BR></BR> bei Anzahl Messungen [ ]: ";
  message += String(zaehler); // int to String, no decimal places
  message += "</BR></BR> ";
  message += "</BR></BR> bisherige maximale Leistung [W]: ";
  message += String(Leistung_Max, 3); // float to String, three decimal places  
  message += "</BR></BR> bisherig maximaler Strom [A]: ";
  message += String(Ampere0_Max, 3); // float to String, three decimal places
  message += "</BR></BR> bisherig maximale Frequenz [Hz]: ";
  message += String(freq_max); // float to String, no decimal places  
  server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
}



void stoppen_1(){
  //*********** den Pin 4 DE-aktivieren
  pinMode(4, OUTPUT);
  digitalWrite (4, LOW ); // es fliesst kein Strom und der Optokoppler gejt aus
  // nach dem Leerlauf des Strom-Speichers s.o. haut die Bremsmechaink rein...
  String message = "</BR></BR> Notstopp ausgeloest... ";
  server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK... 

}

void neustart_1(){  // ALLE Mittel- und Maximalwerte werden beibehalten.... !!!!
  
      String message = "</BR></BR> Neustart ausgeloest... ";
      server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
      delay(3000); // damit er noch senden kann
      
      // Wir speichern die letzten Daten vor dem Neustart in preferences..
      // einen "Ordner" anlegen/verwenden = Archiv...
      preferences.begin("Daten", false);
      // Variable in Dateien "Name der Variable" schreiben = Einträge...
      preferences.putFloat("Ampere_Mittel", ampere0_Mittel);
      preferences.putFloat("Volt_Mittel", volt1_Mittel);
      preferences.putFloat("Volt_Cal", volt_x); // der letzte Nullspannungswert gemäss WLAN-Zustand
      preferences.putFloat("Watt_Mittel", Leistung_Mittel);
      preferences.putFloat("Watt_Max", Leistung_Max);
      preferences.putFloat("Ampere_Max", Ampere0_Max);
      preferences.putDouble("Freq_Max", freq_max);
      preferences.putULong("Counter", zaehler);
      preferences.end();
      
      // und Neustart...
      ESP.restart(); // Die bisher gesammelten Daten sollten gespeichert sein...
}


void RasPi_1(){  // NUR RasPi-Abruf - setzt Mittelwerte zurück, Maximalwerte bleiben erhalten!!
  
  String message = "</BR></BR> aktuelle mittlere Leistung [W/sek]: ";
  message += String(Leistung_Mittel, 3); // float to String, three decimal places
  message += "</BR></BR> bei Anzahl Messungen [ ]: ";
  message += String(zaehler); // int to String, no decimal places
  message += "</BR></BR> ";
  message += "</BR></BR> bisherige maximale Leistung [W]: ";
  message += String(Leistung_Max, 3); // float to String, three decimal places
  message += "</BR></BR> bisherig maximaler Strom [A]: ";
  message += String(Ampere0_Max, 3); // float to String, three decimal places       
  message += "</BR></BR> bisherig maximaler Frequenz [Hz]: ";
  message += String(freq_max); // float to String, no decimal places  
  server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK... 

  // Grundwerte der Mittelwertbildung auf 0.00 zurückstellen, da ja übermittelt...
  ampere0_Mittel = 0.0000; // ständig aufsummierend...
  volt1_Mittel = 0.0000; // ständig aufsummierend...
  zaehler = 0; // ständig aufsummierend...
  Leistung_Mittel = 0.0000;
  
}


void ruecksetzen_1(){  // setzt Mittel- und Maximalwerte zurück !!
  
  // Alle Werte imSpeicher (wird bei Neustart ausgelesen) werden auf Vorgabewerte bzw. NULL gesetzt
  // programminterne Zwischenwerte sind bei Neustart auch neu initialisiert....es wird auch der
  // Korrekturwert volt_x dann neu ermittelt...

 String message = "</BR></BR>Mittelwerte zurueckgesetzt...Neustart erfolgt....  ";
 server.send(200, "text/html", message); // 200 bedeutet für den aufrufenden Browser alles OK...
 
  delay(3000); // damit er noch senden kann
      
  // Wir speichern die letzten Daten vor dem Neustart in preferences..
  // einen "Ordner" anlegen/verwenden = Archiv...
  preferences.begin("Daten", false);
  // Variable in Dateien "Name der Variable" schreiben = Einträge...
  preferences.putFloat("Ampere_Mittel", 0);
  preferences.putFloat("Volt_Mittel", 0);
  preferences.putFloat("Volt_Cal", 2.51);
  preferences.putFloat("Watt_Mittel", 0);
  preferences.putFloat("Watt_Max", 0);
  preferences.putFloat("Ampere_Max", 0);
  preferences.putDouble("Freq_Max", 0);
  preferences.putULong("Counter", 0);
  preferences.end();
  
  // und Neustart...
  ESP.restart(); // Die bisher gesammelten Daten werden auf Vorgabewerte gespeichet...

}
[/code]

 Hier reagieren wir auf die per Browser  gesendeten Befehle bzw. Anfragen...

 das ESP-Programm komplett zum Download...

 

ACHTUNG: Die Programmierung ist ein Arbeitsstand, sie funktioniert grundlegend ist aber nicht gegen Fehlbedienung etc. abgesichert. Aber Ihr könnt ein "hängendes Programm" in der Lazarus-Oberfläche jederzeit mit "Halt" abbrechen...

 

 Hier geht es zu Teil 1....

Ist mir zu kompliziert..... =>.... zurück zur Startseite