Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

So Stand Heute.
Ich habe noch ein paar Ausgaben angepasst. Das betrifft die Serial.print() Ausgabe zum PC. Wenn ich das Gerät mit gelöschen Speicher starte, dann sieht das so aus:
"I2C Fram gefunden". Das sollte immer kommen, denn wenn nicht, ist das wichtigste nicht aktiv. Der Speicher. Dann:
"Aktueller Protokoll Ablagezeiger = 32204" . Das heißt, dass keine Prokolle im Speicher sind. Dann:
"Speicher gelöscht-> Startadresse = 4". Das heißt auch kein einziger Messprotokoll Eintrag ist noch im Speicher.

Dann habe ich mal ein paar Messaufzeichnungen verursacht, habe also die Überwachte Spannung mal stufenweise erhöht, so dass jede Erhöhung die Schwelle zur Aufzeichnung überschreitet. Da passiert am PC nichts. Dann habe ich die gespeicherten Daten zum PC übertragen. Das sieht dann so aus:
########################################
### Messprotokoll Übertragung Start ###
4.5815;20.2.2026;19:17:49;1
4.6654;20.2.2026;19:18:1;2
4.7726;20.2.2026;19:18:2;3
4.8785;20.2.2026;19:18:2;4
4.9706;20.2.2026;19:18:3;5
5.0765;20.2.2026;19:18:3;6
5.1673;20.2.2026;19:18:3;7
5.2786;20.2.2026;19:18:4;8
### Messprotokoll Übertragung Ende ###
########################################
### Messchwellen - Protokoll Ausgabe ###
100;20.2.2026;19:18:42;1
# Messchwelle Protokoll - Ausgabe Ende #
########################################
Das Messschwellen Protokoll sagt, dass am 20.2.2026 um 19:18:42 Uhr die Hysteresse der Messschwelle Automatisch von 50mV auf 100mV wurde. Da innerhalb einer Zeit von einer Minute 8 Soannungserhöhungen waren, die jeweils über die Messschwelle gingen.

Das wars. Hier noch das komplette Protokoll dieser ganzen Aktionen zusammen:

Code: Alles auswählen

I2C FRAM gefunden
Aktueller Protokoll Ablagezeiger = 32204
########################################
# Speicher gelöscht-> Startadresse = 4 #
########################################
########################################
### Messprotokoll Übertragung Start  ###
4.5815;20.2.2026;19:17:49;1
4.6654;20.2.2026;19:18:1;2
4.7726;20.2.2026;19:18:2;3
4.8785;20.2.2026;19:18:2;4
4.9706;20.2.2026;19:18:3;5
5.0765;20.2.2026;19:18:3;6
5.1673;20.2.2026;19:18:3;7
5.2786;20.2.2026;19:18:4;8
###  Messprotokoll Übertragung Ende  ###
########################################
### Messchwellen - Protokoll Ausgabe ###
100;20.2.2026;19:18:42;1
# Messchwelle Protokoll - Ausgabe Ende #
########################################
OK, der Batterieschalter ist inzwischen auch eingebaut. Die Überwachung der Spannung ist auch schon drin. Also es gefällt mir schon seeeehr gut. :(oo):

Das aktualisierte Programm:

Code: Alles auswählen

/* 
    Abfrage von analogen Werten mit dem ESP32
    am ADS1115 mit Weitergabe per I2C an den I2C - FRAM, 
    wenn die Spannung deutlich abweicht vom letzten Messwert. 
    Taste zum Übertragen auf den PC, Taste zum Löschen, bei 32000 byte ist Schluss.
    Schalter für Hohe Schwelle, Autmatische Schwelle, Niedrige Schwelle.
    Anzeige im OLED angepasst 06.02.2026
    Logeintrag bei Automatischer Schwellen Änderung.
    Logeinträge beim Übertrag zum PC auch ausgeben.
    Die Hysterese ist jetzt deutlich verbessert. Sie geht jetzt nach +/- 50mV Stufen 
    Programm im Moment vom 20.02.2026 / ADC_ADS1115_ESP32_Mini_OLE_FRAM_2x4Byte_V51
*/
#include <WiFi.h>
//#define NTP_SERVER "de.pool.ntp.org"
#define NTP_SERVER "Fritz.Box"
#define TZ_INFO "WEST-1DWEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  // Western European Time
//--------------------------------------------------------------------------------------------
#include <Adafruit_ADS1X15.h>  // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
//-----------------------------FRAM-----------------------------------------------------------
#include "Adafruit_EEPROM_I2C.h"
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C i2ceeprom;
#define EEPROM_ADDR 0x50  // the default address!
// -------------------OLED Display einrichten-------------------------------------------------
#include <U8g2lib.h>  // als U8g2 im Bibliotheksverwalter zu finden
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0);
//------------------------ADS1115 16Bit Analog-Digital Sensor---------------------------------
const float multiplier = 0.125F;  // ADS1115-Multiplikator bei einf. Verstärkung
int A_Value;                      // Messwert per GPIO
int adc0;                         // Messwert an Kanal 0 des ADS1115
int adc1;                         // Messwert an Kanal 1 des ADS1115
int adc2;                         // Messwert an Kanal 2 des ADS1115
int adc3;                         // Messwert an Kanal 3 des ADS1115
float A_mv, ads_mv0, ads_mv1;     // Messwert in Millivolt umgerechnet
//--------------------------------------------------------------------------------------------
//----------------------- Spannungsmessungen Speichern ---------------------------------------
int Spannungneu = 0;
int Spannung2neu = 0;
int Spannung2alt = 0;
byte Batterie = 1;
float Messung = 0;
float f = 0;
int Hysterese = 50;  // Steht für 50mV rauf oder runter
int Hysterese2 = 0;
const int Hysteresemax = 1000;
const int Hysteresemin = 50;
//------------------ Zeitdaten FRAM ----------------------------------------
uint8_t buffer[4];  // floats are 4 bytes!
int Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int i = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte Reagieren = 0;
int LogZeiger = 32200;
int LogZeiger2 = 32204;
//-----------------------Taster01---------------------------------------
const byte Loeschen = 32;            // Pin 32 wird Constant für Löschen
byte Loeschenstatus = 0;             // Zum Abfragen des Tatsenpins
byte Loeschenmerker = 0;             // Zum Merken des aktuellen Tatsenstatus
unsigned long Sekundenablauf04 = 0;  // Tastenabfrage von Taster02 300ms aussetzen
const unsigned long Pausezeit04 = 300;
//-----------------------Taster02---------------------------------------
const byte Uebertragen = 25;  // Pin 25 wird Constant für übertragung
byte Uebertragstatus = 0;
byte Uebertragmerker = 0;
unsigned long Sekundenablauf05 = 0;  // Tastenabfrage von Taster02 300ms aussetzen
const unsigned long Pausezeit05 = 300;
//--------------------Tonausgabe PIN 27---------------------------------
const byte TonPin = 27;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//--------------------- Umschalter -------------------------------------
const byte USchalter01 = 12;  // Schalter oben
byte Schalter01Status = 0;
const byte USchalter02 = 4;  // Schalter unten
byte Schalter02Status = 0;
byte SchalterMerker = 0;
//------------------------- Minutentakt zur Zeit - Ausgabe -----------------------------------
unsigned long Sekundenablauf01 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit01 = 60000;
unsigned long Zeitablauf = 0;
//------------------------ PLatzverbrauch am FRAM pro 60sec. ---------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//------------------------ PLatzverbrauch am FRAM pro 1 Std ----------------------------------
unsigned long Sekundenablauf03 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit03 = (60000 * 60);
//-------------------------------- Zeit Messungen --------------------------------------------
unsigned long Messungstart = 0;
unsigned long Messungende = 0;
unsigned long Laufzeit = 0;

//############################################################################################
// ----------------------------------------------------SETUP----------------------------------
//############################################################################################
void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("Analog-Spannungsueberwachung mit ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // -------------------FRAM Ereichbar ??----------------------
  if (i2ceeprom.begin(0x50)) {  // Sie können die neue I2C-Adresse hier einfügen, z. B. begin(0x51);
    Serial.println(F("I2C FRAM gefunden"));
  } else {
    Serial.println(F("I2C-FRAM nicht identifiziert ... überprüfen Sie Ihre Verbindungen.?\r\n"));
    while (1) delay(10);
  }
  //-----------------------ADS 1115---------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //-----------Taster einrichten------------------------------
  pinMode(Loeschen, INPUT_PULLUP);     // Pin 13 fuer Taster01 wird intern auf plus gelegt. Mit GND ueber Taste aktivieren
  pinMode(Uebertragen, INPUT_PULLUP);  // Pin 4 fuer Taster02
  //-----------Schalter einrichten----------------------------
  pinMode(USchalter01, INPUT_PULLUP);  // Umschalter Stellung oben
  pinMode(USchalter02, INPUT_PULLUP);  // Umschalter Stellung unten
  //----------------------- Oled Display ---------------------
  oled.begin();
  oled.clearBuffer();  // Textspeicher löschen
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 50000;
  // Wichtige Startdaten aus dem FRAM holen
  Startdaten_holen();
  Messen();
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();
  //-- Wenn der FRAM nicht voll und Betriebsspannung gut --
  if ((Reagieren < 2) && (Batterie == 1)) {
    if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
      Displayausgabe();
      Sekundenablauf01 = millis();
    }
    Kontrollen();
    Messen();
    if (Reagieren == 1) {
      SpeicherdatenSchreiben();
      Spannung2alt = Spannung2neu;
      tone(TonPin, 1000, 100);  // Piep wenn sich die Spannung ändert.
      Reagieren = 0;
      // Diese beiden Zeilen unten, werden nur gebraucht,
      // wenn eine Ausgabe auf dem PC, nach Speicherung
      // eines Datensatzes, benötigt wird !!
      //SpeicherdatenLesen();
      //testprint();
    }
  }
  //------------------------------------------------------
  //
  //--------------- Ist der FRAM voll ?? -----------------
  if (Speicher >= 32000) {
    oled.clearBuffer();  // Textspeicher löschen
    oled.setFont(u8g2_font_10x20_mf);
    oled.setCursor(20, (2 * 20));
    oled.print(F("FRAM voll"));
    oled.sendBuffer();
    tone(TonPin, 440, 1000);
    Reagieren = 2;
  }
  //------------------------------------------------------
  //
  //------------ Tasten und Schalter Abfrage -------------
  if (Batterie = 1) {
    Tastenabfrage();
    if (Uebertragmerker == 1) {
      DatenzumPC();
      Uebertragmerker = 0;
    }
    if (Loeschenmerker == 1) {
      FRAM_Loeschen();
      Loeschenmerker = 0;
    }
    //---------------------------------------------------
    Schalterabfrage();
  }
  // Wenn Betriebsspannung zu gering, nur noch diese Prüfen
  if (Batterie == 0) {
    Messen();
    Kontrollen();
  }
  /*
  Messungende = millis();
  Laufzeit = Messungende - Messungstart;
  if (Laufzeit >= 20){
  Serial.println(Laufzeit);
  }
  */
}  //---------------------------------- LOOP ENDE ---------------------------------------------

//############################################################################################
//-------------------------- WIFI Verbindung und Zeit holen ----------------------------------
//############################################################################################
void NTP_Zeit() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("FRITZ!Box Gastzugang", "GastvonFranzKoehler");
  while (WiFi.status() != WL_CONNECTED)  // Ist WLAN Connect?
  {
    delay(500);
  }
  struct tm local;
  configTzTime(TZ_INFO, NTP_SERVER);  // ESP32 Systemzeit mit NTP Synchronisieren
  getLocalTime(&local, 10000);        // Versuche 10 s zu Synchronisieren
  WiFi.mode(WIFI_OFF);
}
//---------------------------WIFI Verbindung und Zeit Ende -----------------------------------
//
//############################################################################################
//---------------------------- Startdaten aus FRAM holen -------------------------------------
//############################################################################################
void Startdaten_holen() {
  //------- Speicherzeiger auslesen (Protokoll)---------------
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  //--------Letzten Messwert auslesen (Protokoll)-------------
  i2ceeprom.read(32104, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  //--------Letzte Zeit auslesen (Protokoll)------------------
  i2ceeprom.read(32108, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
  time_t t = Zeitbuffer;
  tm tm;
  //--------Ausgabezähler auslesen (Protokoll)----------------
  i2ceeprom.read(32112, buffer, 4);
  memcpy((void *)&Zaehler, buffer, 4);
  //------- Logzeiger auslesen (Protokoll)--------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  //------- Logzeiger1 Eintragen wenn nötig ------------------
  if (LogZeiger < 32204) {
    LogZeiger = 32204;
    memcpy(buffer, (void *)&LogZeiger, 4);
    i2ceeprom.write(32200, buffer, 4);
  }
  Serial.print(F("Aktueller Protokoll Ablagezeiger = "));
  Serial.println(LogZeiger);
  //--------Prokolldaten Ausgeben-----------------------------
  if (Speicher <= 4) {
    Speicher = 4;
    Serial.println(F("########################################"));
    Serial.println(F("# Speicher gelöscht-> Startadresse = 4 #"));
    Serial.println(F("########################################"));
  } else {
    testprint();
  }
}
//-------------------------------- Startdaten holen Ende -------------------------------------
//
//############################################################################################
//---------------------------------- Displayausgabe ------------------------------------------
//############################################################################################
void Displayausgabe() {
  tm local;
  getLocalTime(&local);
  oled.clearBuffer();               // Textspeicher löschen
  oled.setFont(u8g2_font_6x12_tr);  // Kleine Schrift 6x12
  oled.setCursor(10, (1 * 10));
  oled.print(&local, " Datum: %d.%m.%y");
  oled.setCursor(10, (2 * 10));
  oled.print(&local, " Zeit : %H:%M");  // 16 Zeichen neue Zeit schreiben
  oled.sendBuffer();

  // Messung auf das Display ausgeben
  oled.setFont(u8g2_font_10x20_mf);
  //ADS Kanal 0 anzeigen
  oled.setCursor(20, (2 * 20));
  oled.print(Messung);
  oled.print(F(" Volt "));
  //ADS Kanal 1 anzeigen
  oled.setCursor(20, (3 * 20));
  // if (ads_mv1 < 0) { ads_mv1 == 0; }
  oled.print(ads_mv0);
  oled.print(F(" Volt "));
  oled.sendBuffer();

  /*
    struct tm enthält diese Atribute:
    ===============================================
    Member   Type  Meaning                   Range
    tm_sec   int   seconds after the minute  0-60*
    tm_min   int   minutes after the hour    0-59
    tm_hour  int   hours since midnight      0-23
    tm_mday  int   day of the month          1-31
    tm_mon   int   months since January      0-11
    tm_year  int   years since 1900
    tm_wday  int   days since Sunday         0-6
    tm_yday  int   days since January 1      0-365
    tm_isdst int   Daylight Saving Time flag
    ==============================================
    */
}
//------------------------------------------------------------------------------------------
//############################################################################################
// ------------------------------------ Messung per ADS1115 ----------------------------------
//############################################################################################
void Messen() {
  // - Kanal 0 messen (single-ended)
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0);
  // - Kanal 1 messen (single-ended)
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1);
  // oder
  // - differenzielle Messung an Kanal 0/1
  //adc0 = ads.readADC_Differential_0_1();
  //ads_mv = (adc0 * multiplier);
  //Serial.printf("; I2C: %4.2f mV\n", ads_mv);
  //===============================================
  //------------------------Ist die Spannung verändert ? Ja, dann speichern !-----------------
  // Hier wird die Messung "float" durch das *100, um zwei Kommas nach hinten geschoben
  // und in einen "int" übergeben. Dadurch sind die Werte hinter dem Komma abgeschnitten.
  // Das heißt, aus den gemessenen z.B. "3,1255768" Volt werden 312,55768
  // und mit int sind die stellen hinterm Komma weg.
  // Für den Vergleich als <-> neu bleibt also nur noch der Wert "312"
  // Die dritte stelle hinterm Komma ändert sich schon rel. oft.
  // -----------------------------------------------------------------------------------------
  ads_mv0 = ads_mv0 * 11;
  Spannung2neu = ads_mv0 * 1000;
  if ((Spannung2alt + Hysterese < Spannung2neu) || (Spannung2alt - Hysterese > Spannung2neu)) {
    Reagieren = 1;
  }
  // Veränderte Spannung anzeigen
  Spannungneu = ads_mv0 * 100;
  if (Spannung2alt == Spannungneu) {
  } else {
    // Messung auf das Display ausgeben
    oled.setFont(u8g2_font_10x20_mf);
    //ADS Kanal 0 anzeigen
    oled.setCursor(20, (3 * 20));
    oled.print(ads_mv0);
    oled.print(F(" Volt "));
    oled.sendBuffer();
  }
}

// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  Messung = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Letzen Messwert schreiben (Protokoll)-------------------------------------------------
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(32104, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit vom letzten Messwert Schreiben (Protokoll)---------------------------------------
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(32108, buffer, 4);
  // Speicherzeiger im FRAM schreiben auf 32100 sichern (Protokoll)------------------------
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Zähler von letzten Eintrag schreiben (Protokoll)--------------------------------------
  memcpy(buffer, (void *)&Zaehler, 4);
  i2ceeprom.write(32112, buffer, 4);
  // Display aktualisieren-----------------------------------------------------------------
  oled.setCursor(20, (2 * 20));
  oled.print(Messung);
  oled.print(F(" Volt "));
  //ADS Kanal 1 anzeigen
  oled.setCursor(20, (3 * 20));
  oled.print(ads_mv0);
  oled.print(F(" Volt "));
  oled.sendBuffer();
}
//------------------------------ Schreiben Ende ---------------------------------------------
//
//###########################################################################################
//------------------------------ FRAM Auslesen ----------------------------------------------
//###########################################################################################
void SpeicherdatenLesen() {
  // Messwert auslesen-----------------------------------------------------------------------
  Speicher2 = Speicher - 4;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  // Zeit / Datum auslesen-------------------------------------------------------------------
  Speicher2 = Speicher;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
}
//------------------------------ Auslesen Ende ---------------------------------------------
//
//###########################################################################################
//-------------------------- Automatik Logs im FRAM -----------------------------------------
//###########################################################################################
void AutoLogschreiben() {
  //------- Logzeiger auslesen (Protokoll)---------------------------------------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger2, buffer, 4);
  //------- Ist im FRAM noch Platz für Logeinträge ?? ----------------------------------------
  if (LogZeiger2 <= 32690) {
    //------- Schwelle schreiben --------------------------------------------------------------
    memcpy(buffer, (void *)&Hysterese, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    // Log - Zeit & Datum Schreiben------------------------------------------------------------
    time_t now;
    time(&now);
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&now, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&LogZeiger2, 4);
    i2ceeprom.write(32200, buffer, 4);
    //Serial.println(LogZeiger2);
  }
}
//--------------------------- Automatik Logs Ende -------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("########################################"));
  Serial.println(F("### Messprotokoll Übertragung Start  ###"));
  oled.setFont(u8g2_font_10x20_mf);
  oled.setCursor(20, (2 * 20));
  oled.println(F("Uebertrag"));
  oled.sendBuffer();
  Ausgabezaehler = 0;
  UebertragZeiger = 8;
  for (int i = UebertragZeiger; i <= Speicher; i = i + 4) {
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&f, buffer, 4);
    // Zeit / Datum auslesen-------------------------------------------------------------------
    i = i + 4;
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&Zeitbuffer, buffer, 4);
    time_t t = Zeitbuffer;
    tm tm;
    localtime_r(&t, &tm);
    tm.tm_year += 1900;
    tm.tm_mon += 1;
    Ausgabezaehler++;
    Serial.print(f, 4);
    Serial.print(F(";"));
    Serial.print(tm.tm_mday);
    Serial.print(F("."));
    Serial.print(tm.tm_mon);
    Serial.print(F("."));
    Serial.print(tm.tm_year);
    Serial.print(F(";"));
    Serial.print(tm.tm_hour);
    Serial.print(F(":"));
    Serial.print(tm.tm_min);
    Serial.print(F(":"));
    Serial.print(tm.tm_sec);
    Serial.print(";");
    Serial.println(Ausgabezaehler);
  }
  Serial.println(F("###  Messprotokoll Übertragung Ende  ###"));
  Serial.println(F("########################################"));
  Uebertragmerker = 0;
  //------- Logzeiger auslesen (Protokoll)--------------------
  Serial.println(F("### Messchwellen - Protokoll Ausgabe ###"));
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  if (LogZeiger >= 32204) {
    Ausgabezaehler = 0;
    UebertragZeiger = 32204;
    for (int i = UebertragZeiger; i < LogZeiger; i = i + 4) {
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Hysterese2, buffer, 4);
      // Zeit / Datum auslesen-------------------------------------------------------------------
      i = i + 4;
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Zeitbuffer, buffer, 4);
      time_t t = Zeitbuffer;
      tm tm;
      localtime_r(&t, &tm);
      tm.tm_year += 1900;
      tm.tm_mon += 1;
      Ausgabezaehler++;
      Serial.print(Hysterese2);
      Serial.print(F(";"));
      Serial.print(tm.tm_mday);
      Serial.print(F("."));
      Serial.print(tm.tm_mon);
      Serial.print(F("."));
      Serial.print(tm.tm_year);
      Serial.print(F(";"));
      Serial.print(tm.tm_hour);
      Serial.print(F(":"));
      Serial.print(tm.tm_min);
      Serial.print(F(":"));
      Serial.print(tm.tm_sec);
      Serial.print(";");
      Serial.println(Ausgabezaehler);
    }
  }
  Serial.println(F("# Messchwelle Protokoll - Ausgabe Ende #"));
  Serial.println(F("########################################"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon;
  Serial.print(f, 4);
  Serial.print(F(" Volt ->"));
  Serial.print(&tm, " Datum: %d.%m.%y");
  Serial.print(&tm, " Zeit: %H:%M:%S");
  Serial.print(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
}
//-------------------------------- Testprint Ende ------------------------------------------
//
//##########################################################################################
//--------------------------------- FRAM löschem -------------------------------------------
//##########################################################################################
void FRAM_Loeschen() {
  Serial.println(F("########################################"));
  Serial.print(F("# FRAM wird gelöscht "));
  oled.setFont(u8g2_font_10x20_mf);
  oled.setCursor(20, (2 * 20));
  oled.println(F("Loeschen! "));
  oled.sendBuffer();
  for (i = 0; i <= 32700; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(i, buffer, 4);
  }
  //------- Speicherzeiger auf Start---------------
  // Speicherzeiger = 4 im FRAM auf 32100 sichern
  Speicher = 4;
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  Kontrollzaehler = 0;
  Zaehler = 0;
  Serial.println(F("FRAM IST gelöscht #"));
  Serial.println(F("########################################"));
  oled.setFont(u8g2_font_10x20_mf);
  oled.setCursor(20, (2 * 20));
  oled.println(F("Geloescht"));
  oled.sendBuffer();
  //------ Lockfile Zeiger auf Start 32204 setzen --
  //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
  LogZeiger2 = 32204;
  memcpy(buffer, (void *)&LogZeiger2, 4);
  i2ceeprom.write(32200, buffer, 4);
  //Serial.println(LogZeiger2);
}
//##########################################################################################
//--------------------------------- Taster abfragen ----------------------------------------
//##########################################################################################
void Tastenabfrage() {
  //-----------Loeschen abfragen--------------------------------------------
  if (Zeitablauf - Sekundenablauf04 >= Pausezeit04) {  // 300msec abgelaufen?
    Loeschenstatus = digitalRead(Loeschen);            // Pin von Taster01 abfragen
    if (Loeschenstatus == LOW) {                       // Ist Taster01 gedrueckt?
      Loeschenmerker = !Loeschenmerker;                // Merken dass Taster01 gedrueckt wurde
      Sekundenablauf04 = millis();                     // Die 200ms neu starten
      tone(TonPin, frequenz, tonZeit);                 // Bestätigungston für Tastendruck ausgeben
    }
  }
  //-----------Uebertragen abfragen--------------------------------------------
  if (Zeitablauf - Sekundenablauf05 >= Pausezeit05) {  // 300msec abgelaufen?
    Uebertragstatus = digitalRead(Uebertragen);        // Pin von Taster02 abfragen
    if (Uebertragstatus == LOW) {                      // Ist Taster02 gedrueckt?
      Uebertragmerker = 1;                             // Merken dass Taster02 gedrueckt wurde
      Sekundenablauf05 = millis();                     // Die 200ms neu starten
      tone(TonPin, frequenz, tonZeit);                 // Bestätigungston für Tastendruck ausgeben
    }
  }
}
//##########################################################################################
//-------------------------------- Schalter abfragen ---------------------------------------
//##########################################################################################
void Schalterabfrage() {
  Schalter01Status = digitalRead(USchalter01);
  if (Schalter01Status == LOW) {
    SchalterMerker = 1;
    Hysterese = 50;
  }
  Schalter02Status = digitalRead(USchalter02);
  if (Schalter02Status == LOW) {
    SchalterMerker = 2;
    Hysterese = 1000;
  }
  if ((Schalter01Status == HIGH) && (Schalter02Status == HIGH)) {
    SchalterMerker = 0;
  }
}
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro 60sek. messen
    if ((Kontrollzaehler > 3) && (Hysterese < Hysteresemax) && (SchalterMerker == 0)) {
      Hysterese = Hysterese + 50;
      //Serial.print(F("##### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt erhöht #######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen ob die Schwelle wiede abgesenkt werden kann
  if (Zeitablauf - Sekundenablauf03 >= Pausezeit03) {  // FRAM Aufzeichungen pro Stunde messen
    if ((Kontrollzaehler < 2) && (Hysterese > Hysteresemin) && (SchalterMerker == 0)) {
      Hysterese = Hysterese - 50;
      //Serial.print(F("###### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt runtergesetz ######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen, ob Betriebsspannung des Gerätes zu niedrig
  if (ads_mv1 < 3) {
    oled.clearBuffer();  // Textspeicher löschen
    oled.setFont(u8g2_font_10x20_mf);
    oled.setCursor(20, (2 * 20));
    oled.print(F("Fehler 01"));
    oled.sendBuffer();
    Batterie = 0;
  } else {
    Batterie = 1;
  }
  // Prüfen ob die Zeit wieder vom Server geholt werden muss.
  tm local;
  //00:00:XX = 3600(=1 Std) * std = 0 + min = 0 * 60 = 0 + sec = maximal 59 sec
  uint32_t nbSek = 3600ul * local.tm_hour + local.tm_min * 60ul + local.tm_sec;
  if (nbSek <= 2)  // zwischen 00:00:00 Uhr und 00:00:59 Uhr Zeit vom NTP holen
  {
    NTP_Zeit();
  }
}
//------------------------------- Kontrollen Ende -------------------------------------------
.
Spannungsüberwachung mit FRAM V03.JPG
Spannungsüberwachung mit FRAM V03.JPG (283.81 KiB) 1130 mal betrachtet
Das AkkuShild wird nur auf den ESP32 Mini aufgesteckt und in der Plusleitung zur Batterie ist ein Schalter.

Mein Testaufbau hat noch einen Spannungsteiler am Messeingang mit 10 Kohm zu 100 Kohm. Das ist eindeutig zu hoch. Ich mache mein neues Gerät mit einem Teiler von 2 Kohm zu 20 Kohm, wie hier im Schaltplan. Da wird die Quelle bei max. 36 Volt mit 1,7 mA belastet, das ist hochohmig genug. Mit dem Spannugnsteiler 100 k zu 10 k ist die Spannung viel zu langsam abgesunkten, da habe ich immer so an die 50 gespeicherte Messungen, wenn ich die zu messende Quelle abziehe. :lol: Hier in der Schaltung, ist jetzt auch die Messanzapfung der eigenen Betriebsspannung auf 3,3 Volt enthalten.
Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

So, ich habe heute diesem Gerät ein 7" Nextion Display verpasst. Ich habe so um die 5 Jahre lang nichts mehr mit den Nextion Display gemacht, hatte also absolut keine Ahnung mehr davon. Das heißt ich mußte mir erst mal wieder einen Testaufbau, mit einem 3,5" Nextion an einem Arduino Uno machen, und als es wieder bischen ging, habe ich mein 7" Nextion an dem ESP32 angeschlossen und damit weiter getestet. Und heute hatte ich es so weit, dass es Sinn machte, in dem ESP32 das Programm der Spannungs - Langzeit Überwachung und das Programm für die Kommunikation mit dem 7" Nextion zu vereinen. Und es läuft schon seeeeehr gut. Ich muss noch einige Ideen damit umsetzen, aber es läuft schon fast wieder alles, was mit dem Oled Display und den Schalter und Tastern zur Steuerung gelaufen ist.

Das Nextion - Display ersetzt ja jetzt auch den Merfach - Umschalter für die Messschwelle und die beiden Taster für FRAM löschen und für Daten zum PC übertragen. Das wird ein geiles Gerät. Ich bin jetzt schon ziehmlich Happy damit. Für heute reichts mir, ich will in die Waagerechte, aber morgen gehts weiter.

Hier ist das Programm, für den Moment. Aber noch viel Luft nach oben. :(oo):

Code: Alles auswählen

/* 
    Abfrage von analogen Werten mit dem ESP32
    am ADS1115 mit Weitergabe per I2C an den I2C - FRAM, 
    wenn die Spannung deutlich abweicht vom letzten Messwert. 
    Taste zum Übertragen auf den PC, Taste zum Löschen, bei 32000 byte ist Schluss.
    Schalter für Hohe Schwelle, Autmatische Schwelle, Niedrige Schwelle.
    Anzeige im OLED angepasst 06.02.2026
    Logeintrag bei Automatischer Schwellen Änderung.
    Logeinträge beim Übertrag zum PC auch ausgeben.
    Die Hysterese ist jetzt deutlich verbessert. Sie geht jetzt nach +/- 50mV Stufen 
    Umstieg auf Nextion Display Oled Programmteile entfernt !!
    Programm im Moment vom 28.03.2026 / ADC_ADS1115_NodeMCU_ESP32_Nextion_FRAM_2x4Byte_V70
*/
#include <WiFi.h>
//#define NTP_SERVER "de.pool.ntp.org"
#define NTP_SERVER "Fritz.Box"
#define TZ_INFO "WEST-1DWEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  // Western European Time
//--------------------------------------------------------------------------------------------
#include <Adafruit_ADS1X15.h>  // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
//-----------------------------FRAM-----------------------------------------------------------
#include "Adafruit_EEPROM_I2C.h"
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C i2ceeprom;
#define EEPROM_ADDR 0x50  // the default address!
//--------------------------Serial für Nextion Display----------------------------------------
HardwareSerial Nextion(2);
byte NexT[3] = { 255, 255, 255 };  // global deklarieren
/*
Wird dann so benutzt:
Serial2.write(NexT, 3);
*/
const byte bufferSize = 64;
int Abfragezaehler = 0;
byte PW = 0;
byte PC = 0;
byte ME = 0;
byte MeIO = 0;
byte Seite = 0;  // Nextion Startseite einstellen
//------------------------ADS1115 16Bit Analog-Digital Sensor---------------------------------
const float multiplier = 0.125F;  // ADS1115-Multiplikator bei einf. Verstärkung
int A_Value;                      // Messwert per GPIO
int adc0;                         // Messwert an Kanal 0 des ADS1115
int adc1;                         // Messwert an Kanal 1 des ADS1115
int adc2;                         // Messwert an Kanal 2 des ADS1115
int adc3;                         // Messwert an Kanal 3 des ADS1115
float A_mv, ads_mv0, ads_mv1;     // Messwert in Millivolt umgerechnet
//--------------------------------------------------------------------------------------------
//----------------------- Spannungsmessungen Speichern ---------------------------------------
int Spannungneu = 0;
int Spannung2neu = 0;
int Spannung2alt = 0;
byte Batterie = 1;
float Messung = 0;
float f = 0;
int Hysterese = 50;  // Steht für 50mV rauf oder runter
int Hysterese2 = 0;
const int Hysteresemax = 1000;
const int Hysteresemin = 50;
byte SchalterMerker = 0;
//------------------ Zeitdaten FRAM ----------------------------------------
uint8_t buffer[4];  // floats are 4 bytes!
int Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int i = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte Reagieren = 0;
int LogZeiger = 32200;
int LogZeiger2 = 32204;
int Uebertragmerker = 0;
//--------------------Tonausgabe PIN 27---------------------------------
const byte TonPin = 27;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//------------------------- Minutentakt zur Zeit - Ausgabe -----------------------------------
unsigned long Sekundenablauf01 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit01 = 60000;
unsigned long Zeitablauf = 0;
//------------------------ PLatzverbrauch am FRAM pro 60sec. ---------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//------------------------ PLatzverbrauch am FRAM pro 1 Std ----------------------------------
unsigned long Sekundenablauf03 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit03 = (60000 * 60);
//-------------------------------- Zeit Messungen --------------------------------------------
unsigned long Messungstart = 0;
unsigned long Messungende = 0;
unsigned long Laufzeit = 0;

//############################################################################################
// ----------------------------------------------------SETUP----------------------------------
//############################################################################################
void setup() {
  Serial.begin(115200);
  delay(500);
  Nextion.begin(9600, SERIAL_8N1, 16, 17);
  Serial.println("Analog-Spannungsueberwachung mit ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // -------------------FRAM Ereichbar ??----------------------
  if (i2ceeprom.begin(0x50)) {  // Sie können die neue I2C-Adresse hier einfügen, z. B. begin(0x51);
    Serial.println(F("I2C FRAM gefunden"));
  } else {
    Serial.println(F("I2C-FRAM nicht identifiziert ... überprüfen Sie Ihre Verbindungen.?\r\n"));
    while (1) delay(10);
  }
  //-----------------------ADS 1115---------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 50000;
  // Wichtige Startdaten aus dem FRAM holen
  Startdaten_holen();
  Messen();
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();
  ESPzuNEXT();
  NEXTzuESP();
  //-- Wenn der FRAM nicht voll und Betriebsspannung gut --
  if ((Reagieren < 2) && (Batterie == 1) && (MeIO == 1)) {
    if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
      Displayausgabe();
      Sekundenablauf01 = millis();
    }
    Kontrollen();
    Messen();
    if (Reagieren == 1) {
      SpeicherdatenSchreiben();
      Spannung2alt = Spannung2neu;
      tone(TonPin, 1000, 100);  // Piep wenn sich die Spannung ändert.
      Reagieren = 0;
      // Diese beiden Zeilen unten, werden nur gebraucht,
      // wenn eine Ausgabe auf dem PC, nach Speicherung
      // eines Datensatzes, benötigt wird !!
      SpeicherdatenLesen();
      testprint();
    }
  }
  //------------------------------------------------------
  //
  //--------------- Ist der FRAM voll ?? -----------------
  if (Speicher >= 32000) {
    Nextion.print("Startseite.Meldungen.txt=\"FRAM Speicher ist voll !!\"");
    Nextion.write(NexT, 3);
    tone(TonPin, 440, 1000);
    Reagieren = 2;
  }
}  //---------------------------------- LOOP ENDE ---------------------------------------------

//############################################################################################
//-------------------------- WIFI Verbindung und Zeit holen ----------------------------------
//############################################################################################
void NTP_Zeit() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("FRITZ!Box Gastzugang", "GastvonFranzKoehler");
  while (WiFi.status() != WL_CONNECTED)  // Ist WLAN Connect?
  {
    delay(500);
  }
  struct tm local;
  configTzTime(TZ_INFO, NTP_SERVER);  // ESP32 Systemzeit mit NTP Synchronisieren
  getLocalTime(&local, 10000);        // Versuche 10 s zu Synchronisieren
  WiFi.mode(WIFI_OFF);
}
//---------------------------WIFI Verbindung und Zeit Ende -----------------------------------
//
//############################################################################################
//---------------------------- Startdaten aus FRAM holen -------------------------------------
//############################################################################################
void Startdaten_holen() {
  //------- Speicherzeiger auslesen (Protokoll)---------------
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  //--------Letzten Messwert auslesen (Protokoll)-------------
  i2ceeprom.read(32104, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  //--------Letzte Zeit auslesen (Protokoll)------------------
  i2ceeprom.read(32108, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
  time_t t = Zeitbuffer;
  tm tm;
  //--------Ausgabezähler auslesen (Protokoll)----------------
  i2ceeprom.read(32112, buffer, 4);
  memcpy((void *)&Zaehler, buffer, 4);
  //------- Logzeiger auslesen (Protokoll)--------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  //------- Logzeiger1 Eintragen wenn nötig ------------------
  if (LogZeiger < 32204) {
    LogZeiger = 32204;
    memcpy(buffer, (void *)&LogZeiger, 4);
    i2ceeprom.write(32200, buffer, 4);
  }
  Serial.print(F("Aktueller Protokoll Ablagezeiger = "));
  Serial.println(LogZeiger);
  //--------Prokolldaten Ausgeben-----------------------------
  if (Speicher <= 4) {
    Speicher = 4;
    Serial.println(F("########################################"));
    Serial.println(F("# Speicher gelöscht-> Startadresse = 4 #"));
    Serial.println(F("########################################"));
  } else {
    testprint();
  }
}
//-------------------------------- Startdaten holen Ende -------------------------------------
//
//############################################################################################
//---------------------------------- Displayausgabe ------------------------------------------
//############################################################################################
void Displayausgabe() {
  tm local;
  getLocalTime(&local);
  /*
  oled.print(&local, " Datum: %d.%m.%y");
  oled.setCursor(10, (2 * 10));
  oled.print(&local, " Zeit : %H:%M");  // 16 Zeichen neue Zeit schreiben
  oled.sendBuffer();
  */
  // ------------------------Ausgabe aufs Nesxtion Display----------------------------------
  if (Seite != 0) {
    Nextion.print("page 0");  // Ausgabe Seite ist "page 0"
    Nextion.write(NexT, 3);
    Seite = 0;
  }
  Nextion.printf("Startseite.Volt1.txt=\"%5.3f\"", Messung);
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt2.txt=\"%5.3f\"", ads_mv0);
  Nextion.write(NexT, 3);
  //----------------------------------------------------------------------------------------
  /*
    struct tm enthält diese Atribute:
    ===============================================
    Member   Type  Meaning                   Range
    tm_sec   int   seconds after the minute  0-60*
    tm_min   int   minutes after the hour    0-59
    tm_hour  int   hours since midnight      0-23
    tm_mday  int   day of the month          1-31
    tm_mon   int   months since January      0-11
    tm_year  int   years since 1900
    tm_wday  int   days since Sunday         0-6
    tm_yday  int   days since January 1      0-365
    tm_isdst int   Daylight Saving Time flag
    ==============================================
    */
}
//------------------------------------------------------------------------------------------
//############################################################################################
// ------------------------------------ Messung per ADS1115 ----------------------------------
//############################################################################################
void Messen() {
  // - Kanal 0 messen (single-ended)
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0);
  // - Kanal 1 messen (single-ended)
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1);
  //===============================================
  ads_mv0 = ads_mv0 * 11;
  Spannung2neu = ads_mv0 * 1000;
  if ((Spannung2alt + Hysterese < Spannung2neu) || (Spannung2alt - Hysterese > Spannung2neu)) {
    Reagieren = 1;
  }
  // Veränderte Spannung anzeigen
  Spannungneu = ads_mv0 * 100;
  if (Spannung2alt == Spannungneu) {
  } else {
    if (Batterie == 1) {
    }
  }
}

// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  Messung = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Letzen Messwert schreiben (Protokoll)-------------------------------------------------
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(32104, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit vom letzten Messwert Schreiben (Protokoll)---------------------------------------
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(32108, buffer, 4);
  // Speicherzeiger im FRAM schreiben auf 32100 sichern (Protokoll)------------------------
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Zähler von letzten Eintrag schreiben (Protokoll)--------------------------------------
  memcpy(buffer, (void *)&Zaehler, 4);
  i2ceeprom.write(32112, buffer, 4);
}
//------------------------------ Schreiben Ende ---------------------------------------------
//
//###########################################################################################
//------------------------------ FRAM Auslesen ----------------------------------------------
//###########################################################################################
void SpeicherdatenLesen() {
  // Messwert auslesen-----------------------------------------------------------------------
  Speicher2 = Speicher - 4;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  // Zeit / Datum auslesen-------------------------------------------------------------------
  Speicher2 = Speicher;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
}
//------------------------------ Auslesen Ende ---------------------------------------------
//
//###########################################################################################
//-------------------------- Automatik Logs im FRAM -----------------------------------------
//###########################################################################################
void AutoLogschreiben() {
  //------- Logzeiger auslesen (Protokoll)---------------------------------------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger2, buffer, 4);
  //------- Ist im FRAM noch Platz für Logeinträge ?? ----------------------------------------
  if (LogZeiger2 <= 32690) {
    //------- Schwelle schreiben --------------------------------------------------------------
    memcpy(buffer, (void *)&Hysterese, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    // Log - Zeit & Datum Schreiben------------------------------------------------------------
    time_t now;
    time(&now);
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&now, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&LogZeiger2, 4);
    i2ceeprom.write(32200, buffer, 4);
    //Serial.println(LogZeiger2);
  }
}
//--------------------------- Automatik Logs Ende -------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("########################################"));
  Serial.println(F("### Messprotokoll Übertragung Start  ###"));
  Ausgabezaehler = 0;
  UebertragZeiger = 8;
  for (int i = UebertragZeiger; i <= Speicher; i = i + 4) {
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&f, buffer, 4);
    // Zeit / Datum auslesen-------------------------------------------------------------------
    i = i + 4;
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&Zeitbuffer, buffer, 4);
    time_t t = Zeitbuffer;
    tm tm;
    localtime_r(&t, &tm);
    tm.tm_year += 1900;
    tm.tm_mon += 1;
    Ausgabezaehler++;
    Serial.print(f, 4);
    Serial.print(F(";"));
    Serial.print(tm.tm_mday);
    Serial.print(F("."));
    Serial.print(tm.tm_mon);
    Serial.print(F("."));
    Serial.print(tm.tm_year);
    Serial.print(F(";"));
    Serial.print(tm.tm_hour);
    Serial.print(F(":"));
    Serial.print(tm.tm_min);
    Serial.print(F(":"));
    Serial.print(tm.tm_sec);
    Serial.print(";");
    Serial.println(Ausgabezaehler);
  }
  Serial.println(F("###  Messprotokoll Übertragung Ende  ###"));
  Serial.println(F("########################################"));
  Uebertragmerker = 0;
  //------- Logzeiger auslesen (Protokoll)--------------------
  Serial.println(F("### Messchwellen - Protokoll Ausgabe ###"));
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  if (LogZeiger >= 32204) {
    Ausgabezaehler = 0;
    UebertragZeiger = 32204;
    for (int i = UebertragZeiger; i < LogZeiger; i = i + 4) {
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Hysterese2, buffer, 4);
      // Zeit / Datum auslesen-------------------------------------------------------------------
      i = i + 4;
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Zeitbuffer, buffer, 4);
      time_t t = Zeitbuffer;
      tm tm;
      localtime_r(&t, &tm);
      tm.tm_year += 1900;
      tm.tm_mon += 1;
      Ausgabezaehler++;
      Serial.print(Hysterese2);
      Serial.print(F(";"));
      Serial.print(tm.tm_mday);
      Serial.print(F("."));
      Serial.print(tm.tm_mon);
      Serial.print(F("."));
      Serial.print(tm.tm_year);
      Serial.print(F(";"));
      Serial.print(tm.tm_hour);
      Serial.print(F(":"));
      Serial.print(tm.tm_min);
      Serial.print(F(":"));
      Serial.print(tm.tm_sec);
      Serial.print(";");
      Serial.println(Ausgabezaehler);
    }
  }
  Serial.println(F("# Messchwelle Protokoll - Ausgabe Ende #"));
  Serial.println(F("########################################"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon;
  Serial.print(f, 4);
  Serial.print(F(" Volt ->"));
  Serial.print(&tm, " Datum: %d.%m.%y");
  Serial.print(&tm, " Zeit: %H:%M:%S");
  Serial.print(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
}
//-------------------------------- Testprint Ende ------------------------------------------
//
//##########################################################################################
//--------------------------------- FRAM löschem -------------------------------------------
//##########################################################################################
void FRAM_Loeschen() {
  Serial.println(F("########################################"));
  Serial.print(F("# FRAM wird gelöscht "));
  for (i = 0; i <= 32700; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(i, buffer, 4);
  }
  //------- Speicherzeiger auf Start---------------
  // Speicherzeiger = 4 im FRAM auf 32100 sichern
  Speicher = 4;
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  Kontrollzaehler = 0;
  Zaehler = 0;
  Serial.println(F("FRAM IST gelöscht #"));
  Serial.println(F("########################################"));
  Nextion.print("Startseite.Meldungen.txt=\"FRAM ist geloescht\"");
  Nextion.write(NexT, 3);
  //------ Lockfile Zeiger auf Start 32204 setzen --
  //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
  LogZeiger2 = 32204;
  memcpy(buffer, (void *)&LogZeiger2, 4);
  i2ceeprom.write(32200, buffer, 4);
  //Serial.println(LogZeiger2);
}
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro 60sek. messen
    if ((Kontrollzaehler > 3) && (Hysterese < Hysteresemax) && (SchalterMerker == 0)) {
      Hysterese = Hysterese + 50;
      //Serial.print(F("##### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt erhöht #######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen ob die Schwelle wiede abgesenkt werden kann
  if (Zeitablauf - Sekundenablauf03 >= Pausezeit03) {  // FRAM Aufzeichungen pro Stunde messen
    if ((Kontrollzaehler < 2) && (Hysterese > Hysteresemin) && (SchalterMerker == 0)) {
      Hysterese = Hysterese - 50;
      //Serial.print(F("###### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt runtergesetz ######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen, ob Betriebsspannung des Gerätes zu niedrig
  if (ads_mv1 <= 3) {
    Batterie = 0;
  } else {
    Batterie = 1;
  }
  // Prüfen ob die Zeit wieder vom Server geholt werden muss.
  tm local;
  //00:00:XX = 3600(=1 Std) * std = 0 + min = 0 * 60 = 0 + sec = maximal 59 sec
  uint32_t nbSek = 3600ul * local.tm_hour + local.tm_min * 60ul + local.tm_sec;
  if (nbSek <= 2)  // zwischen 00:00:00 Uhr und 00:00:59 Uhr Zeit vom NTP holen
  {
    NTP_Zeit();
  }
}
//------------------------------- Kontrollen Ende -------------------------------------------
//######################################################################################
//########################## Kommunikation mit dem Nextion #############################
//######################################################################################
//
void ESPzuNEXT() {
  Nextion.print("dim=50");  // Display wird etwas gedimmt
  Nextion.write(NexT, 3);
  //Nextion.print("DatenzumPC.Textfeld1.txt=\"Ein Test\"");
  //Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt1.txt=\"%5.3f\"", Messung);
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt2.txt=\"%5.3f\"", ads_mv0);
  Nextion.write(NexT, 3);
  //Nextion.printf("PasswortAW.t0.txt=\"\""); // Passwort löschen
  //Nextion.write(NexT, 3);
  //Nextion.print("page 0"); // Display auf Seite 0 umschalten
  //Nextion.write(NexT, 3);
  /*
  Nextion.print("cirs 400,373,20,RED");  // z.B. RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,YELLOW");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,GREEN");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,50712");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  */
}
//######################################################################################
//########################### Rückmeldung vom Nextion auswerten ########################
//######################################################################################
//
void NEXTzuESP() {
  static uint8_t bIndex;
  static uint8_t buffer[bufferSize];
  if (Nextion.available()) {
    if (Abfragezaehler == 0) {
      delay(300);
    }
    uint8_t inChar = Nextion.read();
    buffer[bIndex++] = inChar;
    if ((buffer[0] == 101) || (buffer[0] == 80) || (buffer[0] == 35)) {
      Abfragezaehler = 0;
    }

    Serial.print(Abfragezaehler);
    Serial.print(" Buffer = ");
    Serial.println(buffer[0]);
    //----------------------------------- Menüseite wurde aufgerufen -------------
    if ((Abfragezaehler == 0) && (buffer[0] == 35)) {  // page 0 Start
      Serial.println(F("Seite Null wurde aufgerufen"));
      if (MeIO == 1) {
        Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
        Nextion.write(NexT, 3);
      }
    }
    // -----------------------------FRAM löschen Taste + PW Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 80)) {  // P? für Passwort
      PW = PW + 1;
    }
    if ((Abfragezaehler == 1) && (buffer[0] == 51)) {  // 3?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 54)) {  // 6?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (PW == 5)) {
      Serial.println("Passwort ist korrekt");
      Nextion.printf("PasswortAW.t0.txt=\"\"");  // Passwort löschen
      Nextion.write(NexT, 3);
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"FRAM wird geloescht !!\"");
      Nextion.write(NexT, 3);
      PW = 0;
      FRAM_Loeschen();
    }
    if ((Abfragezaehler == 4) && (PW < 5)) {  // Ist es nicht die FRAM - löschne Taste
      PW = 0;
    }
    //----------------------------------------------------------------------------
    // --------------------------------------- Daten zum PC Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 3)) {  // Daten zum PC ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 50)) {  // Taste 2 ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (PC < 3)) {  // Ist es nicht die Daten zum PC Taste
      PC = 0;
    }
    if ((Abfragezaehler == 7) && (PC == 3)) {
      PC = 0;
      Serial.println("Daten zum PC übertragen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Daten wurden zum PC uebertragen\"");
      Nextion.write(NexT, 3);
      DatenzumPC();
    }
    //----------------------------------------------------------------------------
    // ----------------------------------------- Messungen Starten Abfrage -------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 2)) {  // Taste Messungen IO ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 49)) {  // Taste 1 ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (ME < 3)) {  // ist es nicht die ME - Taste
      ME = 0;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 0)) {
      ME = 0;
      Serial.println("Messungen Starten");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestartet\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
      Nextion.write(NexT, 3);
      MeIO = 1;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 1)) {
      ME = 0;
      Serial.println("Messungen Stoppen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestoppt\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Start\"");
      Nextion.write(NexT, 3);
      MeIO = 0;
    }
  }
  //----------------------------------------------------------------------------
  Abfragezaehler++;
  bIndex = 0;
}
Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Heute mache ich mal ein paar Erweiterungen und Änderungen am Display. Hier ist der Momentane Stand des Displays.
Nextion 4.jpg
Nextion 4.jpg (431.03 KiB) 680 mal betrachtet
Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Soooo, fertig ist anders, aber ich bin mit den Punkten, die Probleme machten jetzt zügig weiter gekommen. Es fehlt noch eine Kleinigkeit in der Anzeige auf der Hauptseite. Und noch ein ganzer Menüpunkt. Das "FRAM Inhalt sehen" habe ich noch gar nicht angefangen. Das ist noch ein bischen Arbeit denke ich. Aber so wie die Kiste jetzt ist, könnte man schon damit arbeiten. Hier mal ein Bild vom Fortschritt, im Vergleich zu dem Bild darüber, wo noch einen ganze Menge gefeht hat. :(oo): Ich habe mich jetzt gerade selber überrascht, weil ich da jetzt plötzlich seeeehr schnell die Lösung gefunden habe. :(V):
.
Spannungsüberwachung29.03.26.jpg
Spannungsüberwachung29.03.26.jpg (772.87 KiB) 605 mal betrachtet
Datum und Uhrzeit unten muss ich auch noch ein bischen zurechtrücken, aber nicht mehr heute. Man sieht zumindest schon wo die Reise hingeht. Ich bin heute mal endlich wieder mit mir zufrieden.

Franz :oo:

Code: Alles auswählen

/* 
    Abfrage von analogen Werten mit dem ESP32
    am ADS1115 mit Weitergabe per I2C an den I2C - FRAM, 
    wenn die Spannung deutlich abweicht vom letzten Messwert. 
    Taste zum Übertragen auf den PC, Taste zum Löschen, bei 32000 byte ist Schluss.
    Schalter für Hohe Schwelle, Autmatische Schwelle, Niedrige Schwelle.
    Anzeige im OLED angepasst 06.02.2026
    Logeintrag bei Automatischer Schwellen Änderung.
    Logeinträge beim Übertrag zum PC auch ausgeben.
    Die Hysterese ist jetzt deutlich verbessert. Sie geht jetzt nach +/- 50mV Stufen 
    Umstieg auf Nextion Display Oled Programmteile entfernt !!
    Programm im Moment vom 29.03.2026 / ADC_ADS1115_NodeMCU_ESP32_Nextion_FRAM_2x4Byte_V71
*/
#include <WiFi.h>
//#define NTP_SERVER "de.pool.ntp.org"
#define NTP_SERVER "Fritz.Box"
#define TZ_INFO "WEST-1DWEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  // Western European Time
//--------------------------------------------------------------------------------------------
#include <Adafruit_ADS1X15.h>  // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
//-----------------------------FRAM-----------------------------------------------------------
#include "Adafruit_EEPROM_I2C.h"
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C i2ceeprom;
#define EEPROM_ADDR 0x50  // the default address!
//--------------------------Serial für Nextion Display----------------------------------------
HardwareSerial Nextion(2);
byte NexT[3] = { 255, 255, 255 };  // global deklarieren
/*
Wird dann so benutzt:
Serial2.write(NexT, 3);
*/
const byte bufferSize = 64;
int Abfragezaehler = 0;
byte PW = 0;
byte PC = 0;
byte KF = 0;
byte ME = 0;
byte MeIO = 0;
byte Seite = 0;  // Nextion Startseite einstellen
//------------------------ADS1115 16Bit Analog-Digital Sensor---------------------------------
const float multiplier = 0.125F;  // ADS1115-Multiplikator bei einf. Verstärkung
int A_Value;                      // Messwert per GPIO
int adc0;                         // Messwert an Kanal 0 des ADS1115
int adc1;                         // Messwert an Kanal 1 des ADS1115
int adc2;                         // Messwert an Kanal 2 des ADS1115
int adc3;                         // Messwert an Kanal 3 des ADS1115
float A_mv, ads_mv0, ads_mv1;     // Messwert in Millivolt umgerechnet
//--------------------------------------------------------------------------------------------
//----------------------- Spannungsmessungen Speichern ---------------------------------------
int Spannungneu = 0;
int Spannung2neu = 0;
int Spannung2alt = 0;
byte Batterie = 1;
float Messung = 0;
float f = 0;
int Hysterese = 50;  // Steht für 50mV rauf oder runter
int Hysterese2 = 0;
const int Hysteresemax = 1000;
const int Hysteresemin = 50;
byte SchalterMerker = 0;
//------------------ Zeitdaten FRAM ----------------------------------------
uint8_t buffer[4];  // floats are 4 bytes!
int Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int i = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte Reagieren = 0;
int LogZeiger = 32200;
int LogZeiger2 = 32204;
int Uebertragmerker = 0;
//--------------------Tonausgabe PIN 27---------------------------------
const byte TonPin = 27;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//------------------------- Minutentakt zur Zeit - Ausgabe -----------------------------------
unsigned long Sekundenablauf01 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit01 = 60000;
unsigned long Zeitablauf = 0;
//------------------------ PLatzverbrauch am FRAM pro 60sec. ---------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//------------------------ PLatzverbrauch am FRAM pro 1 Std ----------------------------------
unsigned long Sekundenablauf03 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit03 = (60000 * 60);
//-------------------------------- Zeit Messungen --------------------------------------------
unsigned long Messungstart = 0;
unsigned long Messungende = 0;
unsigned long Laufzeit = 0;

//############################################################################################
// ----------------------------------------------------SETUP----------------------------------
//############################################################################################
void setup() {
  Serial.begin(115200);
  delay(500);
  Nextion.begin(9600, SERIAL_8N1, 16, 17);
  Serial.println("Analog-Spannungsueberwachung mit ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // -------------------FRAM Ereichbar ??----------------------
  if (i2ceeprom.begin(0x50)) {  // Sie können die neue I2C-Adresse hier einfügen, z. B. begin(0x51);
    Serial.println(F("I2C FRAM gefunden"));
  } else {
    Serial.println(F("I2C-FRAM nicht identifiziert ... überprüfen Sie Ihre Verbindungen.?\r\n"));
    while (1) delay(10);
  }
  //-----------------------ADS 1115---------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 50000;
  // Wichtige Startdaten aus dem FRAM holen
  Startdaten_holen();
  Messen();
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();
  ESPzuNEXT();
  NEXTzuESP();
  //-- Wenn der FRAM nicht voll und Betriebsspannung gut --
  if ((Reagieren < 2) && (Batterie == 1) && (MeIO == 1)) {
    if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
      Displayausgabe();
      Sekundenablauf01 = millis();
    }
    Kontrollen();
    Messen();
    if (Reagieren == 1) {
      SpeicherdatenSchreiben();
      Spannung2alt = Spannung2neu;
      tone(TonPin, 1000, 100);  // Piep wenn sich die Spannung ändert.
      Reagieren = 0;
      // Diese beiden Zeilen unten, werden nur gebraucht,
      // wenn eine Ausgabe auf dem PC, nach Speicherung
      // eines Datensatzes, benötigt wird !!
      SpeicherdatenLesen();
      testprint();
    }
  }
  //------------------------------------------------------
  //
  //--------------- Ist der FRAM voll ?? -----------------
  if (Speicher >= 32000) {
    Nextion.print("Startseite.Meldungen.txt=\"FRAM Speicher ist voll !!\"");
    Nextion.write(NexT, 3);
    tone(TonPin, 440, 1000);
    Reagieren = 2;
  }
}  //---------------------------------- LOOP ENDE ---------------------------------------------

//############################################################################################
//-------------------------- WIFI Verbindung und Zeit holen ----------------------------------
//############################################################################################
void NTP_Zeit() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("FRITZ!Box Gastzugang", "GastvonFranzKoehler");
  while (WiFi.status() != WL_CONNECTED)  // Ist WLAN Connect?
  {
    delay(500);
  }
  struct tm local;
  configTzTime(TZ_INFO, NTP_SERVER);  // ESP32 Systemzeit mit NTP Synchronisieren
  getLocalTime(&local, 10000);        // Versuche 10 s zu Synchronisieren
  WiFi.mode(WIFI_OFF);
}
//---------------------------WIFI Verbindung und Zeit Ende -----------------------------------
//
//############################################################################################
//---------------------------- Startdaten aus FRAM holen -------------------------------------
//############################################################################################
void Startdaten_holen() {
  //------- Speicherzeiger auslesen (Protokoll)---------------
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  //--------Letzten Messwert auslesen (Protokoll)-------------
  i2ceeprom.read(32104, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  //--------Letzte Zeit auslesen (Protokoll)------------------
  i2ceeprom.read(32108, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
  time_t t = Zeitbuffer;
  tm tm;
  //--------Ausgabezähler auslesen (Protokoll)----------------
  i2ceeprom.read(32112, buffer, 4);
  memcpy((void *)&Zaehler, buffer, 4);
  //------- Logzeiger auslesen (Protokoll)--------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  //------- Logzeiger1 Eintragen wenn nötig ------------------
  if (LogZeiger < 32204) {
    LogZeiger = 32204;
    memcpy(buffer, (void *)&LogZeiger, 4);
    i2ceeprom.write(32200, buffer, 4);
  }
  Serial.print(F("Aktueller Protokoll Ablagezeiger = "));
  Serial.println(LogZeiger);
  //--------Prokolldaten Ausgeben-----------------------------
  if (Speicher <= 4) {
    Speicher = 4;
    Serial.println(F("########################################"));
    Serial.println(F("# Speicher gelöscht-> Startadresse = 4 #"));
    Serial.println(F("########################################"));
  } else {
    testprint();
  }
}
//-------------------------------- Startdaten holen Ende -------------------------------------
//
//############################################################################################
//---------------------------------- Displayausgabe ------------------------------------------
//############################################################################################
void Displayausgabe() {
  tm local;
  getLocalTime(&local);
  // ------------------------Ausgabe aufs Nesxtion Display----------------------------------
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&local, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&local, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  //----------------------------------------------------------------------------------------
  /*
    struct tm enthält diese Atribute:
    ===============================================
    Member   Type  Meaning                   Range
    tm_sec   int   seconds after the minute  0-60*
    tm_min   int   minutes after the hour    0-59
    tm_hour  int   hours since midnight      0-23
    tm_mday  int   day of the month          1-31
    tm_mon   int   months since January      0-11
    tm_year  int   years since 1900
    tm_wday  int   days since Sunday         0-6
    tm_yday  int   days since January 1      0-365
    tm_isdst int   Daylight Saving Time flag
    ==============================================
    */
}
//------------------------------------------------------------------------------------------
//############################################################################################
// ------------------------------------ Messung per ADS1115 ----------------------------------
//############################################################################################
void Messen() {
  // - Kanal 0 messen (single-ended)
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0);
  // - Kanal 1 messen (single-ended)
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1);
  //===============================================
  ads_mv0 = ads_mv0 * 11;
  Spannung2neu = ads_mv0 * 1000;
  if ((Spannung2alt + Hysterese < Spannung2neu) || (Spannung2alt - Hysterese > Spannung2neu)) {
    Reagieren = 1;
  }
  // Veränderte Spannung anzeigen
  Spannungneu = ads_mv0 * 100;
  if (Spannung2alt == Spannungneu) {
  } else {
    if (Batterie == 1) {
    }
  }
}

// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  Messung = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Letzen Messwert schreiben (Protokoll)-------------------------------------------------
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(32104, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit vom letzten Messwert Schreiben (Protokoll)---------------------------------------
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(32108, buffer, 4);
  // Speicherzeiger im FRAM schreiben auf 32100 sichern (Protokoll)------------------------
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Zähler von letzten Eintrag schreiben (Protokoll)--------------------------------------
  memcpy(buffer, (void *)&Zaehler, 4);
  i2ceeprom.write(32112, buffer, 4);
  //---------------- Letzte Messung aufs Display ------------------------------------------
  Nextion.printf("Startseite.LGM.txt=\"%5.3f\"", Messung);
  Nextion.printf(" Volt");
  Nextion.write(NexT, 3);
}
//------------------------------ Schreiben Ende ---------------------------------------------
//
//###########################################################################################
//------------------------------ FRAM Auslesen ----------------------------------------------
//###########################################################################################
void SpeicherdatenLesen() {
  // Messwert auslesen-----------------------------------------------------------------------
  Speicher2 = Speicher - 4;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  // Zeit / Datum auslesen-------------------------------------------------------------------
  Speicher2 = Speicher;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
}
//------------------------------ Auslesen Ende ---------------------------------------------
//
//###########################################################################################
//-------------------------- Automatik Logs im FRAM -----------------------------------------
//###########################################################################################
void AutoLogschreiben() {
  //------- Logzeiger auslesen (Protokoll)---------------------------------------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger2, buffer, 4);
  //------- Ist im FRAM noch Platz für Logeinträge ?? ----------------------------------------
  if (LogZeiger2 <= 32690) {
    //------- Schwelle schreiben --------------------------------------------------------------
    memcpy(buffer, (void *)&Hysterese, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    // Log - Zeit & Datum Schreiben------------------------------------------------------------
    time_t now;
    time(&now);
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&now, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&LogZeiger2, 4);
    i2ceeprom.write(32200, buffer, 4);
    //Serial.println(LogZeiger2);
  }
}
//--------------------------- Automatik Logs Ende -------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("########################################"));
  Serial.println(F("### Messprotokoll Übertragung Start  ###"));
  Ausgabezaehler = 0;
  UebertragZeiger = 8;
  for (int i = UebertragZeiger; i <= Speicher; i = i + 4) {
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&f, buffer, 4);
    // Zeit / Datum auslesen-------------------------------------------------------------------
    i = i + 4;
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&Zeitbuffer, buffer, 4);
    time_t t = Zeitbuffer;
    tm tm;
    localtime_r(&t, &tm);
    tm.tm_year += 1900;
    tm.tm_mon += 1;
    Ausgabezaehler++;
    Serial.print(f, 4);
    Serial.print(F(";"));
    Serial.print(tm.tm_mday);
    Serial.print(F("."));
    Serial.print(tm.tm_mon);
    Serial.print(F("."));
    Serial.print(tm.tm_year);
    Serial.print(F(";"));
    Serial.print(tm.tm_hour);
    Serial.print(F(":"));
    Serial.print(tm.tm_min);
    Serial.print(F(":"));
    Serial.print(tm.tm_sec);
    Serial.print(";");
    Serial.println(Ausgabezaehler);
  }
  Serial.println(F("###  Messprotokoll Übertragung Ende  ###"));
  Serial.println(F("########################################"));
  Uebertragmerker = 0;
  //------- Logzeiger auslesen (Protokoll)--------------------
  Serial.println(F("### Messchwellen - Protokoll Ausgabe ###"));
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  if (LogZeiger >= 32204) {
    Ausgabezaehler = 0;
    UebertragZeiger = 32204;
    for (int i = UebertragZeiger; i < LogZeiger; i = i + 4) {
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Hysterese2, buffer, 4);
      // Zeit / Datum auslesen-------------------------------------------------------------------
      i = i + 4;
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Zeitbuffer, buffer, 4);
      time_t t = Zeitbuffer;
      tm tm;
      localtime_r(&t, &tm);
      tm.tm_year += 1900;
      tm.tm_mon += 1;
      Ausgabezaehler++;
      Serial.print(Hysterese2);
      Serial.print(F(";"));
      Serial.print(tm.tm_mday);
      Serial.print(F("."));
      Serial.print(tm.tm_mon);
      Serial.print(F("."));
      Serial.print(tm.tm_year);
      Serial.print(F(";"));
      Serial.print(tm.tm_hour);
      Serial.print(F(":"));
      Serial.print(tm.tm_min);
      Serial.print(F(":"));
      Serial.print(tm.tm_sec);
      Serial.print(";");
      Serial.println(Ausgabezaehler);
    }
  }
  Serial.println(F("# Messchwelle Protokoll - Ausgabe Ende #"));
  Serial.println(F("########################################"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon;
  //
  Serial.print(f, 4);
  Serial.print(F(" Volt ->"));
  Serial.print(&tm, " Datum: %d.%m.%y");
  Serial.print(&tm, " Zeit: %H:%M:%S");
  Serial.print(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
  //
  //Nextion.print("Startseite.LGM.txt=\"Volt: \"");
  Nextion.print("Startseite.LGM.txt=\"");
  Nextion.print(f, 4);
  Nextion.print(F(" V"));
  Nextion.print(&tm, " am %d.%m.%y");
  Nextion.print(&tm, " um %H:%M:%S");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&tm, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&tm, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
}
//-------------------------------- Testprint Ende ------------------------------------------
//
//##########################################################################################
//--------------------------------- FRAM löschem -------------------------------------------
//##########################################################################################
void FRAM_Loeschen() {
  Serial.println(F("########################################"));
  Serial.print(F("# FRAM wird gelöscht "));
  for (i = 0; i <= 32700; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(i, buffer, 4);
  }
  //------- Speicherzeiger auf Start---------------
  // Speicherzeiger = 4 im FRAM auf 32100 sichern
  Speicher = 4;
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  Kontrollzaehler = 0;
  Zaehler = 0;
  Serial.println(F("FRAM IST gelöscht #"));
  Serial.println(F("########################################"));
  Nextion.print("Startseite.Meldungen.txt=\"FRAM ist geloescht\"");
  Nextion.write(NexT, 3);
  //------ Lockfile Zeiger auf Start 32204 setzen --
  //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
  LogZeiger2 = 32204;
  memcpy(buffer, (void *)&LogZeiger2, 4);
  i2ceeprom.write(32200, buffer, 4);
  //Serial.println(LogZeiger2);
}
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro 60sek. messen
    if ((Kontrollzaehler > 3) && (Hysterese < Hysteresemax) && (SchalterMerker == 0)) {
      Hysterese = Hysterese + 50;
      //Serial.print(F("##### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt erhöht #######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen ob die Schwelle wiede abgesenkt werden kann
  if (Zeitablauf - Sekundenablauf03 >= Pausezeit03) {  // FRAM Aufzeichungen pro Stunde messen
    if ((Kontrollzaehler < 2) && (Hysterese > Hysteresemin) && (SchalterMerker == 0)) {
      Hysterese = Hysterese - 50;
      //Serial.print(F("###### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt runtergesetz ######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen, ob Betriebsspannung des Gerätes zu niedrig
  if (ads_mv1 <= 3) {
    Batterie = 0;
  } else {
    Batterie = 1;
  }
  // Prüfen ob die Zeit wieder vom Server geholt werden muss.
  tm local;
  //00:00:XX = 3600(=1 Std) * std = 0 + min = 0 * 60 = 0 + sec = maximal 59 sec
  uint32_t nbSek = 3600ul * local.tm_hour + local.tm_min * 60ul + local.tm_sec;
  if (nbSek <= 2)  // zwischen 00:00:00 Uhr und 00:00:59 Uhr Zeit vom NTP holen
  {
    NTP_Zeit();
  }
}
//------------------------------- Kontrollen Ende -------------------------------------------
//######################################################################################
//########################## Kommunikation mit dem Nextion #############################
//######################################################################################
//
void ESPzuNEXT() {
  Nextion.print("dim=50");  // Display wird etwas gedimmt
  Nextion.write(NexT, 3);
  //Nextion.print("DatenzumPC.Textfeld1.txt=\"Ein Test\"");
  //Nextion.write(NexT, 3);
  if (Seite != 0) {
    Nextion.print("page 0");  // Ausgabe Seite ist "page 0"
    Nextion.write(NexT, 3);
    Seite = 0;
  }
  Nextion.print("Startseite.Byte.val=");
  Nextion.print(Speicher);
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt2.txt=\"%5.3f\"", ads_mv0);
  Nextion.write(NexT, 3);
  //Nextion.printf("PasswortAW.t0.txt=\"\""); // Passwort löschen
  //Nextion.write(NexT, 3);
  //Nextion.print("page 0"); // Display auf Seite 0 umschalten
  //Nextion.write(NexT, 3);
  /*
  Nextion.print("cirs 400,373,20,RED");  // z.B. RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,YELLOW");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,GREEN");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,50712");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  */
}
//######################################################################################
//########################### Rückmeldung vom Nextion auswerten ########################
//######################################################################################
//
void NEXTzuESP() {
  static uint8_t bIndex;
  static uint8_t buffer[bufferSize];
  if (Nextion.available()) {
    if (Abfragezaehler == 0) {
      delay(300);
    }
    uint8_t inChar = Nextion.read();
    buffer[bIndex++] = inChar;
    if ((buffer[0] == 101) || (buffer[0] == 80) || (buffer[0] == 35) || (buffer[0] == 26)) {
      Abfragezaehler = 0;
    }

    Serial.print(Abfragezaehler);
    Serial.print(" Buffer = ");
    Serial.println(buffer[0]);
    //----------------------------------- Menüseite wurde aufgerufen -------------
    if ((Abfragezaehler == 0) && (buffer[0] == 35)) {  // page 0 Start
      Serial.println(F("Seite Null wurde aufgerufen"));
      if (MeIO == 1) {
        Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
        Nextion.write(NexT, 3);
      }
    }
    // -----------------------------FRAM löschen Taste + PW Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 80)) {  // P? für Passwort
      PW = PW + 1;
    }
    if ((Abfragezaehler == 1) && (buffer[0] == 51)) {  // 3?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 54)) {  // 6?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (PW == 5)) {
      Serial.println("Passwort ist korrekt");
      Nextion.printf("PasswortAW.t0.txt=\"\"");  // Passwort löschen
      Nextion.write(NexT, 3);
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"FRAM wird geloescht !!\"");
      Nextion.write(NexT, 3);
      PW = 0;
      FRAM_Loeschen();
    }
    if ((Abfragezaehler == 4) && (PW < 5)) {  // Ist es nicht die FRAM - löschne Taste
      PW = 0;
    }
    //----------------------------------------------------------------------------
    // --------------------------------------- Daten zum PC Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 3)) {  // Daten zum PC ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 50)) {  // Taste 2 ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (PC < 3)) {  // Ist es nicht die Daten zum PC Taste
      PC = 0;
    }
    if ((Abfragezaehler == 7) && (PC == 3)) {
      PC = 0;
      Serial.println("Daten zum PC übertragen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Daten wurden zum PC uebertragen\"");
      Nextion.write(NexT, 3);
      DatenzumPC();
    }
    //----------------------------------------------------------------------------
    // ----------------------------------------- Messungen Starten Abfrage -------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 2)) {  // Taste Messungen IO ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 49)) {  // Taste 1 ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (ME < 3)) {  // ist es nicht die ME - Taste
      ME = 0;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 0)) {
      ME = 0;
      Serial.println("Messungen Starten");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestartet\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
      Nextion.write(NexT, 3);
      MeIO = 1;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 1)) {
      ME = 0;
      Serial.println("Messungen Stoppen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestoppt\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Start\"");
      Nextion.write(NexT, 3);
      MeIO = 0;
    }
    //-------------------- Kommunikations Fehler ESP32 -> Nextion --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 26)) {  // Fehler ?
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 255)) {
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (KF == 2)) {
      Serial.println("Kommunikations Fehler");  // Kommunikationsfehler ESP -> Next
      KF = 0;
    }
    if ((Abfragezaehler == 3) && (KF < 2)) {
      KF = 0;
    }
  }
  //----------------------------------------------------------------------------
  Abfragezaehler++;
  bIndex = 0;
}
Das Programm hier ist noch nichts zum Arbeiten mit dem Gerät. Da sind viele Programmteile drin, die nur zum Programm bauen und testen benötigt werden. Ich schmeiße im Moment nur das raus, was sicher für nichts gebraucht wird. Aber im Moment sind viele Serial.print() Zeilen drin, und viele Zeilen mit denen ich die Kommunikation mit dem Nextion Display teste. Das muss alles dann raus, wenn ich damit mal einen Beta - Test machen will. Es macht schon fast das, was ich will, aber sehr viel ist nur zur Info für mich, dass ich beim Testen sehe was in der Kiste abläuft. Das ist auch noch beim Neustart des Gerätes eine Meldung, die nicht sein darf. Also testen ist gut, aber ein vertiges Gerät ist das noch nicht !! Auch die komplette manuelle Hysterese - Einstellung feht noch. Die war ja mit einem drei Stufen Schalter und wird jetzt ersetzt doech +/- Battons auf der erste Seite vom Nextion. Das fehlt auch noch. Die Hysterese Anzeige und die Handsteuerung. Musss ich noch machen. Ist allerdings ein Klacks. In den nächsten Tagen wird da noch einiges daran gemacht. :cool:
Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Bin wieder ein Stück weiter gekommen. Die Hysterese ist wieder drin. Es gibt jetzt zwei Taster, Plus und Minus und ein Hysterese Fenster, das in mV anzeigt, wo der Hysterese Wert gerade steht, mit dem das Gerät arbeitet. Der wird von der Automatik beeinflusst, und man kann aber mit den Tasten auch wieder beeinflussen.

Hier ist das Programm dazu:

Code: Alles auswählen

/* 
    Abfrage von analogen Werten mit dem ESP32
    am ADS1115 mit Weitergabe per I2C an den I2C - FRAM, 
    wenn die Spannung deutlich abweicht vom letzten Messwert. 
    Taste zum Übertragen auf den PC, Taste zum Löschen, bei 32000 byte ist Schluss.
    Schalter für Hohe Schwelle, Autmatische Schwelle, Niedrige Schwelle.
    Anzeige im OLED angepasst 06.02.2026
    Logeintrag bei Automatischer Schwellen Änderung.
    Logeinträge beim Übertrag zum PC auch ausgeben.
    Die Hysterese ist jetzt deutlich verbessert. Sie geht jetzt nach +/- 50mV Stufen 
    Umstieg auf Nextion Display Oled Programmteile entfernt !!
    Programm im Moment vom 30.03.2026 / ADC_ADS1115_NodeMCU_ESP32_Nextion_FRAM_2x4Byte_V72
*/
#include <WiFi.h>
//#define NTP_SERVER "de.pool.ntp.org"
#define NTP_SERVER "Fritz.Box"
#define TZ_INFO "WEST-1DWEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  // Western European Time
//--------------------------------------------------------------------------------------------
#include <Adafruit_ADS1X15.h>  // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
//-----------------------------FRAM-----------------------------------------------------------
#include "Adafruit_EEPROM_I2C.h"
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C i2ceeprom;
#define EEPROM_ADDR 0x50  // the default address!
//--------------------------Serial für Nextion Display----------------------------------------
HardwareSerial Nextion(2);
byte NexT[3] = { 255, 255, 255 };  // global deklarieren
/*
Wird dann so benutzt:
Serial2.write(NexT, 3);
*/
const byte bufferSize = 64;
int Abfragezaehler = 0;
byte PW = 0;
byte PC = 0;
byte KF = 0;
byte ME = 0;
byte MeIO = 0;
byte Seite = 0;  // Nextion Startseite einstellen
//------------------------ADS1115 16Bit Analog-Digital Sensor---------------------------------
const float multiplier = 0.125F;  // ADS1115-Multiplikator bei einf. Verstärkung
int A_Value;                      // Messwert per GPIO
int adc0;                         // Messwert an Kanal 0 des ADS1115
int adc1;                         // Messwert an Kanal 1 des ADS1115
int adc2;                         // Messwert an Kanal 2 des ADS1115
int adc3;                         // Messwert an Kanal 3 des ADS1115
float A_mv, ads_mv0, ads_mv1;     // Messwert in Millivolt umgerechnet
//--------------------------------------------------------------------------------------------
//----------------------- Spannungsmessungen Speichern ---------------------------------------
int Spannungneu = 0;
int Spannung2neu = 0;
int Spannung2alt = 0;
byte Batterie = 1;
float Messung = 0;
float f = 0;
int Hysterese = 50;  // Steht für 50mV rauf oder runter
int Hysterese2 = 0;
const int Hysteresemax = 1000;
const int Hysteresemin = 50;
byte SchalterMerker = 0;
//------------------ Zeitdaten FRAM ----------------------------------------
uint8_t buffer[4];  // floats are 4 bytes!
int Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int i = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte Reagieren = 0;
int LogZeiger = 32200;
int LogZeiger2 = 32204;
int Uebertragmerker = 0;
//--------------------Tonausgabe PIN 27---------------------------------
const byte TonPin = 27;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//------------------------- Minutentakt zur Zeit - Ausgabe -----------------------------------
unsigned long Sekundenablauf01 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit01 = 60000;
unsigned long Zeitablauf = 0;
//------------------------ PLatzverbrauch am FRAM pro 60sec. ---------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//------------------------ PLatzverbrauch am FRAM pro 1 Std ----------------------------------
unsigned long Sekundenablauf03 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit03 = (60000 * 60);
//-------------------------------- Zeit Messungen --------------------------------------------
unsigned long Messungstart = 0;
unsigned long Messungende = 0;
unsigned long Laufzeit = 0;

//############################################################################################
// ----------------------------------------------------SETUP----------------------------------
//############################################################################################
void setup() {
  Serial.begin(115200);
  delay(500);
  Nextion.begin(9600, SERIAL_8N1, 16, 17);
  Serial.println("Analog-Spannungsueberwachung mit ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // -------------------FRAM Ereichbar ??----------------------
  if (i2ceeprom.begin(0x50)) {  // Sie können die neue I2C-Adresse hier einfügen, z. B. begin(0x51);
    Serial.println(F("I2C FRAM gefunden"));
  } else {
    Serial.println(F("I2C-FRAM nicht identifiziert ... überprüfen Sie Ihre Verbindungen.?\r\n"));
    while (1) delay(10);
  }
  //-----------------------ADS 1115---------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 50000;
  // Wichtige Startdaten aus dem FRAM holen
  Startdaten_holen();
  Messen();
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();
  ESPzuNEXT();
  NEXTzuESP();
  //-- Wenn der FRAM nicht voll und Betriebsspannung gut --
  if ((Reagieren < 2) && (Batterie == 1) && (MeIO == 1)) {
    if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
      Displayausgabe();
      Sekundenablauf01 = millis();
    }
    Kontrollen();
    Messen();
    if (Reagieren == 1) {
      SpeicherdatenSchreiben();
      Spannung2alt = Spannung2neu;
      tone(TonPin, 1000, 100);  // Piep wenn sich die Spannung ändert.
      Reagieren = 0;
      // Diese beiden Zeilen unten, werden nur gebraucht,
      // wenn eine Ausgabe auf dem PC, nach Speicherung
      // eines Datensatzes, benötigt wird !!
      SpeicherdatenLesen();
      testprint();
    }
  }
  //------------------------------------------------------
  //
  //--------------- Ist der FRAM voll ?? -----------------
  if (Speicher >= 32000) {
    Nextion.print("Startseite.Meldungen.txt=\"FRAM Speicher ist voll !!\"");
    Nextion.write(NexT, 3);
    tone(TonPin, 440, 1000);
    Reagieren = 2;
  }
}  //---------------------------------- LOOP ENDE ---------------------------------------------

//############################################################################################
//-------------------------- WIFI Verbindung und Zeit holen ----------------------------------
//############################################################################################
void NTP_Zeit() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("FRITZ!Box Gastzugang", "GastvonFranzKoehler");
  while (WiFi.status() != WL_CONNECTED)  // Ist WLAN Connect?
  {
    delay(500);
  }
  struct tm local;
  configTzTime(TZ_INFO, NTP_SERVER);  // ESP32 Systemzeit mit NTP Synchronisieren
  getLocalTime(&local, 10000);        // Versuche 10 s zu Synchronisieren
  WiFi.mode(WIFI_OFF);
}
//---------------------------WIFI Verbindung und Zeit Ende -----------------------------------
//
//############################################################################################
//---------------------------- Startdaten aus FRAM holen -------------------------------------
//############################################################################################
void Startdaten_holen() {
  //------- Speicherzeiger auslesen (Protokoll)---------------
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  //--------Letzten Messwert auslesen (Protokoll)-------------
  i2ceeprom.read(32104, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  //--------Letzte Zeit auslesen (Protokoll)------------------
  i2ceeprom.read(32108, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
  time_t t = Zeitbuffer;
  tm tm;
  //--------Ausgabezähler auslesen (Protokoll)----------------
  i2ceeprom.read(32112, buffer, 4);
  memcpy((void *)&Zaehler, buffer, 4);
  //------- Logzeiger auslesen (Protokoll)--------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  //------- Logzeiger1 Eintragen wenn nötig ------------------
  if (LogZeiger < 32204) {
    LogZeiger = 32204;
    memcpy(buffer, (void *)&LogZeiger, 4);
    i2ceeprom.write(32200, buffer, 4);
  }
  Serial.print(F("Aktueller Protokoll Ablagezeiger = "));
  Serial.println(LogZeiger);
  //--------Prokolldaten Ausgeben-----------------------------
  if (Speicher <= 4) {
    Speicher = 4;
    Serial.println(F("########################################"));
    Serial.println(F("# Speicher gelöscht-> Startadresse = 4 #"));
    Serial.println(F("########################################"));
  } else {
    testprint();
  }
}
//-------------------------------- Startdaten holen Ende -------------------------------------
//
//############################################################################################
//---------------------------------- Displayausgabe ------------------------------------------
//############################################################################################
void Displayausgabe() {
  tm local;
  getLocalTime(&local);
  // ------------------------Ausgabe aufs Nesxtion Display----------------------------------
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&local, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&local, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Hysterese.val=");
  Nextion.print(Hysterese);
  Nextion.write(NexT, 3);
  //----------------------------------------------------------------------------------------
  /*
    struct tm enthält diese Atribute:
    ===============================================
    Member   Type  Meaning                   Range
    tm_sec   int   seconds after the minute  0-60*
    tm_min   int   minutes after the hour    0-59
    tm_hour  int   hours since midnight      0-23
    tm_mday  int   day of the month          1-31
    tm_mon   int   months since January      0-11
    tm_year  int   years since 1900
    tm_wday  int   days since Sunday         0-6
    tm_yday  int   days since January 1      0-365
    tm_isdst int   Daylight Saving Time flag
    ==============================================
    */
}
//------------------------------------------------------------------------------------------
//############################################################################################
// ------------------------------------ Messung per ADS1115 ----------------------------------
//############################################################################################
void Messen() {
  // - Kanal 0 messen (single-ended)
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0);
  // - Kanal 1 messen (single-ended)
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1);
  //===============================================
  ads_mv0 = ads_mv0 * 11;
  Spannung2neu = ads_mv0 * 1000;
  if ((Spannung2alt + Hysterese < Spannung2neu) || (Spannung2alt - Hysterese > Spannung2neu)) {
    Reagieren = 1;
  }
  // Veränderte Spannung anzeigen
  Spannungneu = ads_mv0 * 100;
  if (Spannung2alt == Spannungneu) {
  } else {
    if (Batterie == 1) {
    }
  }
}

// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  Messung = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Letzen Messwert schreiben (Protokoll)-------------------------------------------------
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(32104, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit vom letzten Messwert Schreiben (Protokoll)---------------------------------------
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(32108, buffer, 4);
  // Speicherzeiger im FRAM schreiben auf 32100 sichern (Protokoll)------------------------
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Zähler von letzten Eintrag schreiben (Protokoll)--------------------------------------
  memcpy(buffer, (void *)&Zaehler, 4);
  i2ceeprom.write(32112, buffer, 4);
  //---------------- Letzte Messung aufs Display ------------------------------------------
  Nextion.printf("Startseite.LGM.txt=\"%5.3f\"", Messung);
  Nextion.printf(" Volt");
  Nextion.write(NexT, 3);
}
//------------------------------ Schreiben Ende ---------------------------------------------
//
//###########################################################################################
//------------------------------ FRAM Auslesen ----------------------------------------------
//###########################################################################################
void SpeicherdatenLesen() {
  // Messwert auslesen-----------------------------------------------------------------------
  Speicher2 = Speicher - 4;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  // Zeit / Datum auslesen-------------------------------------------------------------------
  Speicher2 = Speicher;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
}
//------------------------------ Auslesen Ende ---------------------------------------------
//
//###########################################################################################
//-------------------------- Automatik Logs im FRAM -----------------------------------------
//###########################################################################################
void AutoLogschreiben() {
  //------- Logzeiger auslesen (Protokoll)---------------------------------------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger2, buffer, 4);
  //------- Ist im FRAM noch Platz für Logeinträge ?? ----------------------------------------
  if (LogZeiger2 <= 32690) {
    //------- Schwelle schreiben --------------------------------------------------------------
    memcpy(buffer, (void *)&Hysterese, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    // Log - Zeit & Datum Schreiben------------------------------------------------------------
    time_t now;
    time(&now);
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&now, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&LogZeiger2, 4);
    i2ceeprom.write(32200, buffer, 4);
    //Serial.println(LogZeiger2);
  }
}
//--------------------------- Automatik Logs Ende -------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("########################################"));
  Serial.println(F("### Messprotokoll Übertragung Start  ###"));
  Ausgabezaehler = 0;
  UebertragZeiger = 8;
  for (int i = UebertragZeiger; i <= Speicher; i = i + 4) {
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&f, buffer, 4);
    // Zeit / Datum auslesen-------------------------------------------------------------------
    i = i + 4;
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&Zeitbuffer, buffer, 4);
    time_t t = Zeitbuffer;
    tm tm;
    localtime_r(&t, &tm);
    tm.tm_year += 1900;
    tm.tm_mon += 1;
    Ausgabezaehler++;
    Serial.print(f, 4);
    Serial.print(F(";"));
    Serial.print(tm.tm_mday);
    Serial.print(F("."));
    Serial.print(tm.tm_mon);
    Serial.print(F("."));
    Serial.print(tm.tm_year);
    Serial.print(F(";"));
    Serial.print(tm.tm_hour);
    Serial.print(F(":"));
    Serial.print(tm.tm_min);
    Serial.print(F(":"));
    Serial.print(tm.tm_sec);
    Serial.print(";");
    Serial.println(Ausgabezaehler);
  }
  Serial.println(F("###  Messprotokoll Übertragung Ende  ###"));
  Serial.println(F("########################################"));
  Uebertragmerker = 0;
  //------- Logzeiger auslesen (Protokoll)--------------------
  Serial.println(F("### Messchwellen - Protokoll Ausgabe ###"));
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  if (LogZeiger >= 32204) {
    Ausgabezaehler = 0;
    UebertragZeiger = 32204;
    for (int i = UebertragZeiger; i < LogZeiger; i = i + 4) {
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Hysterese2, buffer, 4);
      // Zeit / Datum auslesen-------------------------------------------------------------------
      i = i + 4;
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Zeitbuffer, buffer, 4);
      time_t t = Zeitbuffer;
      tm tm;
      localtime_r(&t, &tm);
      tm.tm_year += 1900;
      tm.tm_mon += 1;
      Ausgabezaehler++;
      Serial.print(Hysterese2);
      Serial.print(F(";"));
      Serial.print(tm.tm_mday);
      Serial.print(F("."));
      Serial.print(tm.tm_mon);
      Serial.print(F("."));
      Serial.print(tm.tm_year);
      Serial.print(F(";"));
      Serial.print(tm.tm_hour);
      Serial.print(F(":"));
      Serial.print(tm.tm_min);
      Serial.print(F(":"));
      Serial.print(tm.tm_sec);
      Serial.print(";");
      Serial.println(Ausgabezaehler);
    }
  }
  Serial.println(F("# Messchwelle Protokoll - Ausgabe Ende #"));
  Serial.println(F("########################################"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon;
  //
  Serial.print(f, 4);
  Serial.print(F(" Volt ->"));
  Serial.print(&tm, " Datum: %d.%m.%y");
  Serial.print(&tm, " Zeit: %H:%M:%S");
  Serial.print(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
  //
  //Nextion.print("Startseite.LGM.txt=\"Volt: \"");
  Nextion.print("Startseite.LGM.txt=\"");
  Nextion.print(f, 4);
  Nextion.print(F(" V"));
  Nextion.print(&tm, " am %d.%m.%y");
  Nextion.print(&tm, " um %H:%M:%S");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&tm, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&tm, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Hysterese.val=");
  Nextion.print(Hysterese);
  Nextion.write(NexT, 3);
}
//-------------------------------- Testprint Ende ------------------------------------------
//
//##########################################################################################
//--------------------------------- FRAM löschem -------------------------------------------
//##########################################################################################
void FRAM_Loeschen() {
  Serial.println(F("########################################"));
  Serial.print(F("# FRAM wird gelöscht "));
  for (i = 0; i <= 32700; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(i, buffer, 4);
  }
  //------- Speicherzeiger auf Start---------------
  // Speicherzeiger = 4 im FRAM auf 32100 sichern
  Speicher = 4;
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  Kontrollzaehler = 0;
  Zaehler = 0;
  Serial.println(F("FRAM IST gelöscht #"));
  Serial.println(F("########################################"));
  Nextion.print("Startseite.Meldungen.txt=\"FRAM ist geloescht\"");
  Nextion.write(NexT, 3);
  //------ Lockfile Zeiger auf Start 32204 setzen --
  //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
  LogZeiger2 = 32204;
  memcpy(buffer, (void *)&LogZeiger2, 4);
  i2ceeprom.write(32200, buffer, 4);
  //Serial.println(LogZeiger2);
}
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro 60sek. messen
    if ((Kontrollzaehler > 3) && (Hysterese < Hysteresemax)) {
      Hysterese = Hysterese + 50;
      Nextion.printf("Startseite.Hysterese.val=");
      Nextion.print(Hysterese);
      Nextion.write(NexT, 3);
      //Serial.print(F("##### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt erhöht #######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen ob die Schwelle wiede abgesenkt werden kann
  if (Zeitablauf - Sekundenablauf03 >= Pausezeit03) {  // FRAM Aufzeichungen pro Stunde messen
    if ((Kontrollzaehler < 2) && (Hysterese > Hysteresemin)) {
      Hysterese = Hysterese - 50;
      Nextion.printf("Startseite.Hysterese.val=");
      Nextion.print(Hysterese);
      Nextion.write(NexT, 3);
      //Serial.print(F("###### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt runtergesetz ######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen, ob Betriebsspannung des Gerätes zu niedrig
  if (ads_mv1 <= 3) {
    Batterie = 0;
  } else {
    Batterie = 1;
  }
  // Prüfen ob die Zeit wieder vom Server geholt werden muss.
  tm local;
  //00:00:XX = 3600(=1 Std) * std = 0 + min = 0 * 60 = 0 + sec = maximal 59 sec
  uint32_t nbSek = 3600ul * local.tm_hour + local.tm_min * 60ul + local.tm_sec;
  if (nbSek <= 2)  // zwischen 00:00:00 Uhr und 00:00:59 Uhr Zeit vom NTP holen
  {
    NTP_Zeit();
  }
}
//------------------------------- Kontrollen Ende -------------------------------------------
//######################################################################################
//########################## Kommunikation mit dem Nextion #############################
//######################################################################################
//
void ESPzuNEXT() {
  Nextion.print("dim=50");  // Display wird etwas gedimmt
  Nextion.write(NexT, 3);
  //Nextion.print("DatenzumPC.Textfeld1.txt=\"Ein Test\"");
  //Nextion.write(NexT, 3);
  if (Seite != 0) {
    Nextion.print("page 0");  // Ausgabe Seite ist "page 0"
    Nextion.write(NexT, 3);
    Seite = 0;
  }
  Nextion.print("Startseite.Byte.val=");
  Nextion.print(Speicher);
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt2.txt=\"%5.3f\"", ads_mv0);
  Nextion.write(NexT, 3);
  //Nextion.printf("PasswortAW.t0.txt=\"\""); // Passwort löschen
  //Nextion.write(NexT, 3);
  //Nextion.print("page 0"); // Display auf Seite 0 umschalten
  //Nextion.write(NexT, 3);
  /*
  Nextion.print("cirs 400,373,20,RED");  // z.B. RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,YELLOW");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,GREEN");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  Nextion.print("cirs 400,373,20,50712");  // RED, GREEN, YELLOW, BLUE, GRAY, = 50712
  Nextion.write(NexT, 3);
  delay(1000);
  */
}
//######################################################################################
//########################### Rückmeldung vom Nextion auswerten ########################
//######################################################################################
//
void NEXTzuESP() {
  static uint8_t bIndex;
  static uint8_t buffer[bufferSize];
  if (Nextion.available()) {
    if (Abfragezaehler == 0) {
      delay(300);
    }
    uint8_t inChar = Nextion.read();
    buffer[bIndex++] = inChar;
    if ((buffer[0] == 101) || (buffer[0] == 80) || (buffer[0] == 35) || (buffer[0] == 26) || (buffer[0] == 45) || (buffer[0] == 43)) {
      Abfragezaehler = 0;
    }

    Serial.print(Abfragezaehler);
    Serial.print(" Buffer = ");
    Serial.println(buffer[0]);
    //----------------------------------- Menüseite wurde aufgerufen -------------
    if ((Abfragezaehler == 0) && (buffer[0] == 35)) {  // page 0 Start
      Serial.println(F("Seite Null wurde aufgerufen"));
      if (MeIO == 1) {
        Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
        Nextion.write(NexT, 3);
      }
    }
    // -------------------------------- Hysterese + Abfragen ---------------------
    if ((Abfragezaehler == 0) && (buffer[0] == 43)) {  // Hysterese plus ?
      if (Hysterese <= 950) {
        Hysterese = Hysterese + 50;
        Nextion.printf("Startseite.Hysterese.val=");
        Nextion.print(Hysterese);
        Nextion.write(NexT, 3);
      }
    }
    // -------------------------------- Hysterese - Abfragen ---------------------
    if ((Abfragezaehler == 0) && (buffer[0] == 45)) {  // Hysterese minus ?
      if (Hysterese >= 100) {
        Hysterese = Hysterese - 50;
        Nextion.printf("Startseite.Hysterese.val=");
        Nextion.print(Hysterese);
        Nextion.write(NexT, 3);
      }
    }
    // -----------------------------FRAM löschen Taste + PW Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 80)) {  // P? für Passwort
      PW = PW + 1;
    }
    if ((Abfragezaehler == 1) && (buffer[0] == 51)) {  // 3?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 54)) {  // 6?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (PW == 5)) {
      Serial.println("Passwort ist korrekt");
      Nextion.printf("PasswortAW.t0.txt=\"\"");  // Passwort löschen
      Nextion.write(NexT, 3);
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"FRAM wird geloescht !!\"");
      Nextion.write(NexT, 3);
      PW = 0;
      FRAM_Loeschen();
    }
    if ((Abfragezaehler == 4) && (PW < 5)) {  // Ist es nicht die FRAM - löschne Taste
      PW = 0;
    }
    //----------------------------------------------------------------------------
    // --------------------------------------- Daten zum PC Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 3)) {  // Daten zum PC ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 50)) {  // Taste 2 ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (PC < 3)) {  // Ist es nicht die Daten zum PC Taste
      PC = 0;
    }
    if ((Abfragezaehler == 7) && (PC == 3)) {
      PC = 0;
      Serial.println("Daten zum PC übertragen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Daten wurden zum PC uebertragen\"");
      Nextion.write(NexT, 3);
      DatenzumPC();
    }
    //----------------------------------------------------------------------------
    // ----------------------------------------- Messungen Starten Abfrage -------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 2)) {  // Taste Messungen IO ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 49)) {  // Taste 1 ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (ME < 3)) {  // ist es nicht die ME - Taste
      ME = 0;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 0)) {
      ME = 0;
      Serial.println("Messungen Starten");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestartet\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
      Nextion.write(NexT, 3);
      MeIO = 1;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 1)) {
      ME = 0;
      Serial.println("Messungen Stoppen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestoppt\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Start\"");
      Nextion.write(NexT, 3);
      MeIO = 0;
    }
    //-------------------- Kommunikations Fehler ESP32 -> Nextion --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 26)) {  // Fehler ?
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 255)) {
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (KF == 2)) {
      Serial.println("Kommunikations Fehler");  // Kommunikationsfehler ESP -> Next
      KF = 0;
    }
    if ((Abfragezaehler == 3) && (KF < 2)) {
      KF = 0;
    }
  }
  //----------------------------------------------------------------------------
  Abfragezaehler++;
  bIndex = 0;
}
Habe auch ein bischen zurechtgerückt, dass es optisch wieder bischen besser passt. Und die manuelle Hysterese eingebaut. Mit +/- Taste und einem Anzeigefenser für den aktuellen Wert, mit dem das Gerät gerade Arbeitet.
.
Spannungsüberwachung30.03.26.jpg
Spannungsüberwachung30.03.26.jpg (467.62 KiB) 406 mal betrachtet
Was jetzt noch fehlt, das ist der Menüpunkt "FRAM Inhalt sehen". Das ist noch eine Aufgabe, die ich nicht in nem Stündchen erledigen kann. Das muss ich mir auch noch bischen überlegen, nach welchen Kriterien ich die Aufzeichnungen dann sehen will. Aber kommt in den nächsten Tagen.
Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Ich habe jetzt mal ein paar Speicherungen ausgelöst, also die Spannung schön rauf und runter gekurbelt, dass mal viele Datensätze enstehen und auch viele automatische Hysterese - Anpassungen laufen. Und es geht alles wunderbar. Ich habe auch dazwischen immer mal wieder die Hysterese manuell verändert und das spielt alles wunderbar mit. Ich überlege noch ob ich die Automatik mit einem Button ein/aus schalten können sollte. Wäre vielleicht ganz gut, wenn man die Messschwelle nach oben zieht, wird ja trotzdem Automatisch wenn keine Hysterese - Überschreitungen kommen, die Grenze wieder sehr langsam jede Stunde um 50mV, runtergefahren. Kann aber auch sein dass man das nicht will. Dann wäre der Button "Automatik aus" eine gute Sache. Platz habe ich ja noch rechts oben, neben dem Männchen.

Hier ist mal ein Serial.print von den Vorgängen beim Test. Diese Serial.prints sind natürlich dann, wenn das Gerät fertig ist, raus. Aber jetzt zum sehen ob alles läuft wie es soll, ist das schon seeeehr schön. Das einzige was bleibt sind die Serial.print Übertragungen der daten aus dem FRAM, dass man am Ende sieht, was alles los war, werend man weg war. Das waren jetzt 266 Messungs - Aufzeichungen, die den 2132 Byte im FRAM belegen. Und dann noch die 15 Protokoll - Aufzeichnungen, wo der Hysterese Wert Automatisch angepasst wurde. Das waren auch noch 120 Byte. Die Manuellen Anpassungen dess Hysterese Wertes werden nicht aufgezeichnet. Da sieht man nur die Plötzliche Sprünge der Werte um mehr als 50mV. Einmal von 150mV hoch auf 800mV, dann wieder Runter auf 100mV.

Code: Alles auswählen

4.6778 Volt -> Datum: 30.03.26 Zeit: 22:30:53 ADR = 1972 # 246
4.8854 Volt -> Datum: 30.03.26 Zeit: 22:30:56 ADR = 1980 # 247
5.0848 Volt -> Datum: 30.03.26 Zeit: 22:30:59 ADR = 1988 # 248
5.2676 Volt -> Datum: 30.03.26 Zeit: 22:31:02 ADR = 1996 # 249
5.4753 Volt -> Datum: 30.03.26 Zeit: 22:31:19 ADR = 2004 # 250
5.6746 Volt -> Datum: 30.03.26 Zeit: 22:31:27 ADR = 2012 # 251
5.8548 Volt -> Datum: 30.03.26 Zeit: 22:31:34 ADR = 2020 # 252
6.0761 Volt -> Datum: 30.03.26 Zeit: 22:31:37 ADR = 2028 # 253
6.2686 Volt -> Datum: 30.03.26 Zeit: 22:31:39 ADR = 2036 # 254
6.4763 Volt -> Datum: 30.03.26 Zeit: 22:31:41 ADR = 2044 # 255
7.4470 Volt -> Datum: 30.03.26 Zeit: 22:31:42 ADR = 2052 # 256
8.3971 Volt -> Datum: 30.03.26 Zeit: 22:31:43 ADR = 2060 # 257
8.6584 Volt -> Datum: 30.03.26 Zeit: 22:31:44 ADR = 2068 # 258
9.4628 Volt -> Datum: 30.03.26 Zeit: 22:31:44 ADR = 2076 # 259
10.4500 Volt -> Datum: 30.03.26 Zeit: 22:31:46 ADR = 2084 # 260
10.1668 Volt -> Datum: 30.03.26 Zeit: 22:31:54 ADR = 2092 # 261
9.9633 Volt -> Datum: 30.03.26 Zeit: 22:31:57 ADR = 2100 # 262
10.2575 Volt -> Datum: 30.03.26 Zeit: 22:32:15 ADR = 2108 # 263
10.5531 Volt -> Datum: 30.03.26 Zeit: 22:32:25 ADR = 2116 # 264
0 Buffer = 101
1 Buffer = 0
2 Buffer = 3
3 Buffer = 0
4 Buffer = 255
5 Buffer = 255
6 Buffer = 255
7 Buffer = 50
Daten zum PC übertragen
########################################
### Messprotokoll Übertragung Start  ###
36.4540;30.3.2026;10:17:51;1
36.4554;30.3.2026;11:10:30;2
36.4526;30.3.2026;11:11:18;3
36.4554;30.3.2026;11:14:28;4
36.4540;30.3.2026;11:15:15;5
36.4526;30.3.2026;11:18:9;6
36.4513;30.3.2026;11:26:13;7
36.4513;30.3.2026;12:0:15;8
36.4513;30.3.2026;12:22:58;9
36.4499;30.3.2026;12:25:7;10
36.4568;30.3.2026;12:32:19;11
36.4238;30.3.2026;15:37:37;12
36.4623;30.3.2026;15:43:40;13
36.4636;30.3.2026;15:52:0;14
36.4650;30.3.2026;15:59:29;15
36.4581;30.3.2026;16:25:31;16
36.4609;30.3.2026;18:44:54;17
36.4623;30.3.2026;18:46:56;18
36.4636;30.3.2026;18:52:46;19
36.4636;30.3.2026;19:0:8;20
36.4678;30.3.2026;19:14:59;21
36.4678;30.3.2026;19:17:59;22
36.4691;30.3.2026;19:20:9;23
36.1914;30.3.2026;19:26:39;24
31.8189;30.3.2026;19:26:48;25
25.2739;30.3.2026;19:26:48;26
19.3160;30.3.2026;19:26:50;27
14.3701;30.3.2026;19:26:50;28
25.2711;30.3.2026;19:27:3;29
31.0984;30.3.2026;19:27:5;30
36.1570;30.3.2026;19:27:5;31
36.2093;30.3.2026;19:27:19;32
36.1584;30.3.2026;19:27:25;33
34.8343;30.3.2026;19:27:52;34
25.2863;30.3.2026;19:27:52;35
22.1980;30.3.2026;19:27:54;36
15.5375;30.3.2026;19:27:54;37
14.4059;30.3.2026;19:27:54;38
19.7931;30.3.2026;19:27:55;39
25.2450;30.3.2026;19:27:55;40
36.0443;30.3.2026;19:27:56;41
36.1886;30.3.2026;19:27:56;42
28.9108;30.3.2026;19:27:57;43
25.2725;30.3.2026;19:27:57;44
24.3031;30.3.2026;19:27:58;45
17.1353;30.3.2026;19:27:58;46
14.3880;30.3.2026;19:27:59;47
14.2656;30.3.2026;19:28:0;48
6.4735;30.3.2026;19:28:0;49
3.4334;30.3.2026;19:28:0;50
14.3880;30.3.2026;19:28:3;51
15.5609;30.3.2026;19:28:4;52
25.2643;30.3.2026;19:28:5;53
31.6140;30.3.2026;19:28:32;54
36.1845;30.3.2026;19:28:33;55
28.6935;30.3.2026;19:28:34;56
25.2752;30.3.2026;19:28:34;57
21.3799;30.3.2026;19:28:35;58
14.9091;30.3.2026;19:28:36;59
14.3564;30.3.2026;19:28:36;60
13.4076;30.3.2026;19:29:13;61
8.7271;30.3.2026;19:29:13;62
3.3798;30.3.2026;19:29:14;63
14.3220;30.3.2026;19:29:16;64
25.1268;30.3.2026;19:29:17;65
25.2780;30.3.2026;19:29:17;66
35.1656;30.3.2026;19:29:19;67
36.1625;30.3.2026;19:29:19;68
33.6655;30.3.2026;19:29:20;69
25.3481;30.3.2026;19:29:20;70
24.9975;30.3.2026;19:29:22;71
14.3701;30.3.2026;19:29:22;72
12.9814;30.3.2026;19:29:23;73
8.4260;30.3.2026;19:29:23;74
3.3839;30.3.2026;19:29:23;75
14.3564;30.3.2026;19:29:24;76
24.8366;30.3.2026;19:29:25;77
25.2670;30.3.2026;19:29:25;78
26.6241;30.3.2026;19:29:26;79
36.1969;30.3.2026;19:29:26;80
33.0839;30.3.2026;19:29:28;81
25.2752;30.3.2026;19:29:29;82
20.9633;30.3.2026;19:29:29;83
14.6548;30.3.2026;19:29:29;84
14.4004;30.3.2026;19:29:30;85
13.7390;30.3.2026;19:29:30;86
6.1600;30.3.2026;19:29:31;87
3.3743;30.3.2026;19:29:31;88
4.3711;30.3.2026;19:30:45;89
14.3564;30.3.2026;19:30:45;90
25.2656;30.3.2026;19:30:46;91
35.5011;30.3.2026;19:30:47;92
36.1584;30.3.2026;19:30:47;93
29.4140;30.3.2026;19:30:48;94
25.2904;30.3.2026;19:30:48;95
24.3334;30.3.2026;19:30:49;96
14.3605;30.3.2026;19:30:49;97
12.6252;30.3.2026;19:30:50;98
8.1551;30.3.2026;19:30:50;99
3.3921;30.3.2026;19:30:50;100
13.7376;30.3.2026;19:30:52;101
14.3550;30.3.2026;19:30:52;102
25.2849;30.3.2026;19:30:53;103
32.8364;30.3.2026;19:30:54;104
36.1680;30.3.2026;19:30:54;105
28.8833;30.3.2026;19:30:55;106
25.2849;30.3.2026;19:30:55;107
24.7775;30.3.2026;19:30:56;108
14.3632;30.3.2026;19:30:56;109
12.4905;30.3.2026;19:30:57;110
8.0534;30.3.2026;19:30:57;111
3.3866;30.3.2026;19:30:57;112
11.1183;30.3.2026;19:31:26;113
14.3990;30.3.2026;19:31:27;114
25.1653;30.3.2026;19:31:27;115
33.6023;30.3.2026;19:31:29;116
36.1969;30.3.2026;19:31:29;117
27.9703;30.3.2026;19:31:30;118
25.2423;30.3.2026;19:31:30;119
24.6084;30.3.2026;19:31:31;120
14.4086;30.3.2026;19:31:31;121
13.5589;30.3.2026;19:31:31;122
6.0679;30.3.2026;19:31:32;123
3.3591;30.3.2026;19:31:32;124
14.3646;30.3.2026;19:32:52;125
25.0319;30.3.2026;19:32:53;126
29.3026;30.3.2026;19:32:54;127
36.1666;30.3.2026;19:32:55;128
35.1753;30.3.2026;19:33:8;129
25.2615;30.3.2026;19:33:8;130
19.6928;30.3.2026;19:33:9;131
14.4169;30.3.2026;19:33:9;132
12.2292;30.3.2026;19:33:11;133
7.8554;30.3.2026;19:33:11;134
3.3468;30.3.2026;19:33:11;135
14.3798;30.3.2026;19:33:13;136
21.3139;30.3.2026;19:33:15;137
25.2876;30.3.2026;19:33:15;138
35.9425;30.3.2026;19:33:16;139
34.4520;30.3.2026;19:33:18;140
25.4114;30.3.2026;19:33:19;141
21.9230;30.3.2026;19:33:19;142
15.3436;30.3.2026;19:33:19;143
14.3880;30.3.2026;19:33:20;144
12.6266;30.3.2026;19:33:20;145
8.1703;30.3.2026;19:33:20;146
3.3660;30.3.2026;19:33:20;147
3.3908;30.3.2026;19:36:25;148
3.3399;30.3.2026;19:36:39;149
3.3921;30.3.2026;19:36:40;150
3.3413;30.3.2026;19:36:50;151
3.3921;30.3.2026;19:36:52;152
3.3399;30.3.2026;19:36:53;153
3.3908;30.3.2026;19:36:55;154
3.3399;30.3.2026;19:38:9;155
3.3908;30.3.2026;19:38:10;156
4.4976;30.3.2026;19:38:49;157
5.3048;30.3.2026;19:38:53;158
5.6059;30.3.2026;19:38:53;159
6.6715;30.3.2026;19:38:55;160
7.7729;30.3.2026;19:38:57;161
8.9196;30.3.2026;19:39:0;162
9.9853;30.3.2026;19:39:2;163
10.3895;30.3.2026;19:39:4;164
11.0798;30.3.2026;19:39:5;165
11.6435;30.3.2026;19:39:13;166
12.0890;30.3.2026;19:39:13;167
13.1670;30.3.2026;19:39:15;168
14.3798;30.3.2026;19:39:17;169
15.4055;30.3.2026;19:39:19;170
15.7671;30.3.2026;19:39:20;171
16.5578;30.3.2026;19:39:21;172
17.6660;30.3.2026;19:39:22;173
18.5680;30.3.2026;19:39:24;174
18.6918;30.3.2026;19:39:24;175
19.8248;30.3.2026;19:39:27;176
20.9179;30.3.2026;19:39:29;177
19.8564;30.3.2026;19:39:35;178
18.7055;30.3.2026;19:39:37;179
18.1019;30.3.2026;19:39:41;180
17.6880;30.3.2026;19:39:42;181
17.1504;30.3.2026;19:39:43;182
16.5303;30.3.2026;19:39:43;183
15.4413;30.3.2026;19:39:45;184
14.7221;30.3.2026;19:39:47;185
14.3811;30.3.2026;19:39:47;186
14.2491;30.3.2026;19:39:48;187
13.2413;30.3.2026;19:39:48;188
12.5620;30.3.2026;19:39:50;189
12.1371;30.3.2026;19:39:50;190
11.0866;30.3.2026;19:39:53;191
9.9729;30.3.2026;19:39:54;192
9.6099;30.3.2026;19:39:57;193
8.9279;30.3.2026;19:39:58;194
9.9688;30.3.2026;19:40:16;195
11.0756;30.3.2026;19:40:18;196
12.1330;30.3.2026;19:40:19;197
12.6651;30.3.2026;19:40:21;198
13.2454;30.3.2026;19:40:21;199
14.1116;30.3.2026;19:40:23;200
14.3591;30.3.2026;19:40:23;201
15.1374;30.3.2026;19:40:29;202
15.4220;30.3.2026;19:40:29;203
16.3460;30.3.2026;19:40:31;204
16.5688;30.3.2026;19:40:31;205
17.7004;30.3.2026;19:40:35;206
18.6464;30.3.2026;19:41:4;207
19.6969;30.3.2026;19:41:5;208
20.5260;30.3.2026;19:41:7;209
21.6384;30.3.2026;19:41:8;210
19.9870;30.3.2026;19:41:26;211
11.1045;30.3.2026;19:41:26;212
9.0764;30.3.2026;19:41:27;213
5.4340;30.3.2026;19:41:27;214
0.9597;30.3.2026;19:41:27;215
0.1348;30.3.2026;19:41:27;216
1.1798;30.3.2026;19:41:37;217
2.2935;30.3.2026;19:41:39;218
3.2973;30.3.2026;19:41:41;219
4.4275;30.3.2026;19:41:42;220
5.6045;30.3.2026;19:41:44;221
6.6853;30.3.2026;19:41:46;222
7.7715;30.3.2026;19:41:48;223
8.9196;30.3.2026;19:41:50;224
6.7691;30.3.2026;19:43:9;225
3.6438;30.3.2026;19:43:9;226
0.2338;30.3.2026;19:43:10;227
-1.4905;30.3.2026;19:43:13;228
-3.1405;30.3.2026;19:43:13;229
-1.1371;30.3.2026;19:43:13;230
-3.2010;30.3.2026;19:43:14;231
-2.2000;30.3.2026;19:43:14;232
2.7885;30.3.2026;22:29:20;233
2.8875;30.3.2026;22:29:34;234
2.9948;30.3.2026;22:29:36;235
3.0896;30.3.2026;22:29:39;236
3.1927;30.3.2026;22:30:0;237
3.3866;30.3.2026;22:30:4;238
3.4939;30.3.2026;22:30:5;239
3.6878;30.3.2026;22:30:8;240
3.7881;30.3.2026;22:30:10;241
3.9889;30.3.2026;22:30:13;242
4.0893;30.3.2026;22:30:17;243
4.2873;30.3.2026;22:30:19;244
4.4852;30.3.2026;22:30:23;245
4.6778;30.3.2026;22:30:53;246
4.8854;30.3.2026;22:30:56;247
5.0848;30.3.2026;22:30:59;248
5.2676;30.3.2026;22:31:2;249
5.4753;30.3.2026;22:31:19;250
5.6746;30.3.2026;22:31:27;251
5.8548;30.3.2026;22:31:34;252
6.0761;30.3.2026;22:31:37;253
6.2686;30.3.2026;22:31:39;254
6.4763;30.3.2026;22:31:41;255
7.4470;30.3.2026;22:31:42;256
8.3971;30.3.2026;22:31:43;257
8.6584;30.3.2026;22:31:44;258
9.4628;30.3.2026;22:31:44;259
10.4500;30.3.2026;22:31:46;260
10.1668;30.3.2026;22:31:54;261
9.9633;30.3.2026;22:31:57;262
10.2575;30.3.2026;22:32:15;263
10.5531;30.3.2026;22:32:25;264
###  Messprotokoll Übertragung Ende  ###
########################################
### Messchwellen - Protokoll Ausgabe ###
100;30.3.2026;19:27:26;1
150;30.3.2026;19:28:26;2
200;30.3.2026;19:29:26;3
250;30.3.2026;19:30:26;4
300;30.3.2026;19:31:26;5
350;30.3.2026;19:32:26;6
400;30.3.2026;19:33:27;7
100;30.3.2026;19:37:10;8
100;30.3.2026;19:39:10;9
150;30.3.2026;19:40:10;10
800;30.3.2026;19:41:10;11
100;30.3.2026;22:29:50;12
150;30.3.2026;22:30:50;13
200;30.3.2026;22:31:50;14
250;30.3.2026;22:32:51;15
# Messchwelle Protokoll - Ausgabe Ende #
########################################
0 Buffer = 35
Seite Null wurde aufgerufen
10.2726 Volt -> Datum: 30.03.26 Zeit: 22:34:00 ADR = 2124 # 265
9.9591 Volt -> Datum: 30.03.26 Zeit: 22:34:05 ADR = 2132 # 266

Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Hier habe ich das Messprotokoll nochmal um einiges verlänger. Das sind jetzt 3252 Byte Messprotokoll, für 406 Messungen und 192 Byte Hysterese Protokoll 24 Einträge. Ich bin seeeehr zufrieden damit.

Code: Alles auswählen

0 Buffer = 101
1 Buffer = 0
2 Buffer = 3
3 Buffer = 0
4 Buffer = 255
5 Buffer = 255
6 Buffer = 255
7 Buffer = 50
Daten zum PC übertragen
########################################
### Messprotokoll Übertragung Start  ###
36.4540;30.3.2026;10:17:51;1
36.4554;30.3.2026;11:10:30;2
36.4526;30.3.2026;11:11:18;3
36.4554;30.3.2026;11:14:28;4
36.4540;30.3.2026;11:15:15;5
36.4526;30.3.2026;11:18:9;6
36.4513;30.3.2026;11:26:13;7
36.4513;30.3.2026;12:0:15;8
36.4513;30.3.2026;12:22:58;9
36.4499;30.3.2026;12:25:7;10
36.4568;30.3.2026;12:32:19;11
36.4238;30.3.2026;15:37:37;12
36.4623;30.3.2026;15:43:40;13
36.4636;30.3.2026;15:52:0;14
36.4650;30.3.2026;15:59:29;15
36.4581;30.3.2026;16:25:31;16
36.4609;30.3.2026;18:44:54;17
36.4623;30.3.2026;18:46:56;18
36.4636;30.3.2026;18:52:46;19
36.4636;30.3.2026;19:0:8;20
36.4678;30.3.2026;19:14:59;21
36.4678;30.3.2026;19:17:59;22
36.4691;30.3.2026;19:20:9;23
36.1914;30.3.2026;19:26:39;24
31.8189;30.3.2026;19:26:48;25
25.2739;30.3.2026;19:26:48;26
19.3160;30.3.2026;19:26:50;27
14.3701;30.3.2026;19:26:50;28
25.2711;30.3.2026;19:27:3;29
31.0984;30.3.2026;19:27:5;30
36.1570;30.3.2026;19:27:5;31
36.2093;30.3.2026;19:27:19;32
36.1584;30.3.2026;19:27:25;33
34.8343;30.3.2026;19:27:52;34
25.2863;30.3.2026;19:27:52;35
22.1980;30.3.2026;19:27:54;36
15.5375;30.3.2026;19:27:54;37
14.4059;30.3.2026;19:27:54;38
19.7931;30.3.2026;19:27:55;39
25.2450;30.3.2026;19:27:55;40
36.0443;30.3.2026;19:27:56;41
36.1886;30.3.2026;19:27:56;42
28.9108;30.3.2026;19:27:57;43
25.2725;30.3.2026;19:27:57;44
24.3031;30.3.2026;19:27:58;45
17.1353;30.3.2026;19:27:58;46
14.3880;30.3.2026;19:27:59;47
14.2656;30.3.2026;19:28:0;48
6.4735;30.3.2026;19:28:0;49
3.4334;30.3.2026;19:28:0;50
14.3880;30.3.2026;19:28:3;51
15.5609;30.3.2026;19:28:4;52
25.2643;30.3.2026;19:28:5;53
31.6140;30.3.2026;19:28:32;54
36.1845;30.3.2026;19:28:33;55
28.6935;30.3.2026;19:28:34;56
25.2752;30.3.2026;19:28:34;57
21.3799;30.3.2026;19:28:35;58
14.9091;30.3.2026;19:28:36;59
14.3564;30.3.2026;19:28:36;60
13.4076;30.3.2026;19:29:13;61
8.7271;30.3.2026;19:29:13;62
3.3798;30.3.2026;19:29:14;63
14.3220;30.3.2026;19:29:16;64
25.1268;30.3.2026;19:29:17;65
25.2780;30.3.2026;19:29:17;66
35.1656;30.3.2026;19:29:19;67
36.1625;30.3.2026;19:29:19;68
33.6655;30.3.2026;19:29:20;69
25.3481;30.3.2026;19:29:20;70
24.9975;30.3.2026;19:29:22;71
14.3701;30.3.2026;19:29:22;72
12.9814;30.3.2026;19:29:23;73
8.4260;30.3.2026;19:29:23;74
3.3839;30.3.2026;19:29:23;75
14.3564;30.3.2026;19:29:24;76
24.8366;30.3.2026;19:29:25;77
25.2670;30.3.2026;19:29:25;78
26.6241;30.3.2026;19:29:26;79
36.1969;30.3.2026;19:29:26;80
33.0839;30.3.2026;19:29:28;81
25.2752;30.3.2026;19:29:29;82
20.9633;30.3.2026;19:29:29;83
14.6548;30.3.2026;19:29:29;84
14.4004;30.3.2026;19:29:30;85
13.7390;30.3.2026;19:29:30;86
6.1600;30.3.2026;19:29:31;87
3.3743;30.3.2026;19:29:31;88
4.3711;30.3.2026;19:30:45;89
14.3564;30.3.2026;19:30:45;90
25.2656;30.3.2026;19:30:46;91
35.5011;30.3.2026;19:30:47;92
36.1584;30.3.2026;19:30:47;93
29.4140;30.3.2026;19:30:48;94
25.2904;30.3.2026;19:30:48;95
24.3334;30.3.2026;19:30:49;96
14.3605;30.3.2026;19:30:49;97
12.6252;30.3.2026;19:30:50;98
8.1551;30.3.2026;19:30:50;99
3.3921;30.3.2026;19:30:50;100
13.7376;30.3.2026;19:30:52;101
14.3550;30.3.2026;19:30:52;102
25.2849;30.3.2026;19:30:53;103
32.8364;30.3.2026;19:30:54;104
36.1680;30.3.2026;19:30:54;105
28.8833;30.3.2026;19:30:55;106
25.2849;30.3.2026;19:30:55;107
24.7775;30.3.2026;19:30:56;108
14.3632;30.3.2026;19:30:56;109
12.4905;30.3.2026;19:30:57;110
8.0534;30.3.2026;19:30:57;111
3.3866;30.3.2026;19:30:57;112
11.1183;30.3.2026;19:31:26;113
14.3990;30.3.2026;19:31:27;114
25.1653;30.3.2026;19:31:27;115
33.6023;30.3.2026;19:31:29;116
36.1969;30.3.2026;19:31:29;117
27.9703;30.3.2026;19:31:30;118
25.2423;30.3.2026;19:31:30;119
24.6084;30.3.2026;19:31:31;120
14.4086;30.3.2026;19:31:31;121
13.5589;30.3.2026;19:31:31;122
6.0679;30.3.2026;19:31:32;123
3.3591;30.3.2026;19:31:32;124
14.3646;30.3.2026;19:32:52;125
25.0319;30.3.2026;19:32:53;126
29.3026;30.3.2026;19:32:54;127
36.1666;30.3.2026;19:32:55;128
35.1753;30.3.2026;19:33:8;129
25.2615;30.3.2026;19:33:8;130
19.6928;30.3.2026;19:33:9;131
14.4169;30.3.2026;19:33:9;132
12.2292;30.3.2026;19:33:11;133
7.8554;30.3.2026;19:33:11;134
3.3468;30.3.2026;19:33:11;135
14.3798;30.3.2026;19:33:13;136
21.3139;30.3.2026;19:33:15;137
25.2876;30.3.2026;19:33:15;138
35.9425;30.3.2026;19:33:16;139
34.4520;30.3.2026;19:33:18;140
25.4114;30.3.2026;19:33:19;141
21.9230;30.3.2026;19:33:19;142
15.3436;30.3.2026;19:33:19;143
14.3880;30.3.2026;19:33:20;144
12.6266;30.3.2026;19:33:20;145
8.1703;30.3.2026;19:33:20;146
3.3660;30.3.2026;19:33:20;147
3.3908;30.3.2026;19:36:25;148
3.3399;30.3.2026;19:36:39;149
3.3921;30.3.2026;19:36:40;150
3.3413;30.3.2026;19:36:50;151
3.3921;30.3.2026;19:36:52;152
3.3399;30.3.2026;19:36:53;153
3.3908;30.3.2026;19:36:55;154
3.3399;30.3.2026;19:38:9;155
3.3908;30.3.2026;19:38:10;156
4.4976;30.3.2026;19:38:49;157
5.3048;30.3.2026;19:38:53;158
5.6059;30.3.2026;19:38:53;159
6.6715;30.3.2026;19:38:55;160
7.7729;30.3.2026;19:38:57;161
8.9196;30.3.2026;19:39:0;162
9.9853;30.3.2026;19:39:2;163
10.3895;30.3.2026;19:39:4;164
11.0798;30.3.2026;19:39:5;165
11.6435;30.3.2026;19:39:13;166
12.0890;30.3.2026;19:39:13;167
13.1670;30.3.2026;19:39:15;168
14.3798;30.3.2026;19:39:17;169
15.4055;30.3.2026;19:39:19;170
15.7671;30.3.2026;19:39:20;171
16.5578;30.3.2026;19:39:21;172
17.6660;30.3.2026;19:39:22;173
18.5680;30.3.2026;19:39:24;174
18.6918;30.3.2026;19:39:24;175
19.8248;30.3.2026;19:39:27;176
20.9179;30.3.2026;19:39:29;177
19.8564;30.3.2026;19:39:35;178
18.7055;30.3.2026;19:39:37;179
18.1019;30.3.2026;19:39:41;180
17.6880;30.3.2026;19:39:42;181
17.1504;30.3.2026;19:39:43;182
16.5303;30.3.2026;19:39:43;183
15.4413;30.3.2026;19:39:45;184
14.7221;30.3.2026;19:39:47;185
14.3811;30.3.2026;19:39:47;186
14.2491;30.3.2026;19:39:48;187
13.2413;30.3.2026;19:39:48;188
12.5620;30.3.2026;19:39:50;189
12.1371;30.3.2026;19:39:50;190
11.0866;30.3.2026;19:39:53;191
9.9729;30.3.2026;19:39:54;192
9.6099;30.3.2026;19:39:57;193
8.9279;30.3.2026;19:39:58;194
9.9688;30.3.2026;19:40:16;195
11.0756;30.3.2026;19:40:18;196
12.1330;30.3.2026;19:40:19;197
12.6651;30.3.2026;19:40:21;198
13.2454;30.3.2026;19:40:21;199
14.1116;30.3.2026;19:40:23;200
14.3591;30.3.2026;19:40:23;201
15.1374;30.3.2026;19:40:29;202
15.4220;30.3.2026;19:40:29;203
16.3460;30.3.2026;19:40:31;204
16.5688;30.3.2026;19:40:31;205
17.7004;30.3.2026;19:40:35;206
18.6464;30.3.2026;19:41:4;207
19.6969;30.3.2026;19:41:5;208
20.5260;30.3.2026;19:41:7;209
21.6384;30.3.2026;19:41:8;210
19.9870;30.3.2026;19:41:26;211
11.1045;30.3.2026;19:41:26;212
9.0764;30.3.2026;19:41:27;213
5.4340;30.3.2026;19:41:27;214
0.9597;30.3.2026;19:41:27;215
0.1348;30.3.2026;19:41:27;216
1.1798;30.3.2026;19:41:37;217
2.2935;30.3.2026;19:41:39;218
3.2973;30.3.2026;19:41:41;219
4.4275;30.3.2026;19:41:42;220
5.6045;30.3.2026;19:41:44;221
6.6853;30.3.2026;19:41:46;222
7.7715;30.3.2026;19:41:48;223
8.9196;30.3.2026;19:41:50;224
6.7691;30.3.2026;19:43:9;225
3.6438;30.3.2026;19:43:9;226
0.2338;30.3.2026;19:43:10;227
-1.4905;30.3.2026;19:43:13;228
-3.1405;30.3.2026;19:43:13;229
-1.1371;30.3.2026;19:43:13;230
-3.2010;30.3.2026;19:43:14;231
-2.2000;30.3.2026;19:43:14;232
2.7885;30.3.2026;22:29:20;233
2.8875;30.3.2026;22:29:34;234
2.9948;30.3.2026;22:29:36;235
3.0896;30.3.2026;22:29:39;236
3.1927;30.3.2026;22:30:0;237
3.3866;30.3.2026;22:30:4;238
3.4939;30.3.2026;22:30:5;239
3.6878;30.3.2026;22:30:8;240
3.7881;30.3.2026;22:30:10;241
3.9889;30.3.2026;22:30:13;242
4.0893;30.3.2026;22:30:17;243
4.2873;30.3.2026;22:30:19;244
4.4852;30.3.2026;22:30:23;245
4.6778;30.3.2026;22:30:53;246
4.8854;30.3.2026;22:30:56;247
5.0848;30.3.2026;22:30:59;248
5.2676;30.3.2026;22:31:2;249
5.4753;30.3.2026;22:31:19;250
5.6746;30.3.2026;22:31:27;251
5.8548;30.3.2026;22:31:34;252
6.0761;30.3.2026;22:31:37;253
6.2686;30.3.2026;22:31:39;254
6.4763;30.3.2026;22:31:41;255
7.4470;30.3.2026;22:31:42;256
8.3971;30.3.2026;22:31:43;257
8.6584;30.3.2026;22:31:44;258
9.4628;30.3.2026;22:31:44;259
10.4500;30.3.2026;22:31:46;260
10.1668;30.3.2026;22:31:54;261
9.9633;30.3.2026;22:31:57;262
10.2575;30.3.2026;22:32:15;263
10.5531;30.3.2026;22:32:25;264
10.2726;30.3.2026;22:34:0;265
9.9591;30.3.2026;22:34:5;266
9.9509;30.3.2026;23:36:58;267
10.9436;30.3.2026;23:39:40;268
11.9405;30.3.2026;23:39:40;269
12.9319;30.3.2026;23:39:41;270
13.9205;30.3.2026;23:39:41;271
14.5049;30.3.2026;23:39:41;272
14.9476;30.3.2026;23:39:42;273
15.9074;30.3.2026;23:39:42;274
16.8561;30.3.2026;23:39:42;275
17.8860;30.3.2026;23:39:43;276
18.7564;30.3.2026;23:39:44;277
18.8815;30.3.2026;23:39:44;278
19.8248;30.3.2026;23:39:45;279
19.8798;30.3.2026;23:39:45;280
20.8766;30.3.2026;23:39:46;281
21.8666;30.3.2026;23:39:46;282
23.8535;30.3.2026;23:39:46;283
25.8445;30.3.2026;23:39:47;284
26.8331;30.3.2026;23:39:47;285
28.8159;30.3.2026;23:39:47;286
29.8073;30.3.2026;23:39:47;287
30.8000;30.3.2026;23:39:47;288
29.8224;30.3.2026;23:39:57;289
28.8200;30.3.2026;23:40:23;290
28.3676;30.3.2026;23:40:24;291
27.0298;30.3.2026;23:40:24;292
25.5118;30.3.2026;23:40:25;293
24.1051;30.3.2026;23:40:25;294
22.6064;30.3.2026;23:40:25;295
21.2121;30.3.2026;23:40:25;296
19.6900;30.3.2026;23:40:26;297
17.8970;30.3.2026;23:40:26;298
16.7901;30.3.2026;23:40:26;299
14.9201;30.3.2026;23:40:26;300
13.8174;30.3.2026;23:40:26;301
11.9433;30.3.2026;23:40:27;302
10.8845;30.3.2026;23:40:27;303
8.9595;30.3.2026;23:40:27;304
6.9740;30.3.2026;23:40:27;305
5.9813;30.3.2026;23:40:28;306
5.7076;30.3.2026;23:40:28;307
4.8744;30.3.2026;23:40:28;308
3.9834;30.3.2026;23:40:29;309
3.0058;30.3.2026;23:40:29;310
2.2399;30.3.2026;23:40:29;311
2.0006;30.3.2026;23:40:29;312
1.4616;30.3.2026;23:40:30;313
1.0148;30.3.2026;23:40:30;314
1.4300;30.3.2026;23:40:49;315
2.0006;30.3.2026;23:40:49;316
2.9590;30.3.2026;23:40:50;317
3.9792;30.3.2026;23:40:50;318
4.9761;30.3.2026;23:40:50;319
5.9744;30.3.2026;23:44:58;320
6.8145;30.3.2026;23:44:59;321
8.4906;30.3.2026;23:44:59;322
9.9495;30.3.2026;23:44:59;323
11.4029;30.3.2026;23:44:59;324
12.9305;30.3.2026;23:45:0;325
14.3179;30.3.2026;23:45:0;326
15.9101;30.3.2026;23:45:0;327
17.2219;30.3.2026;23:45:0;328
18.8829;30.3.2026;23:45:1;329
20.8725;30.3.2026;23:45:1;330
21.8652;30.3.2026;23:45:1;331
23.8576;30.3.2026;23:45:1;332
24.8490;30.3.2026;23:45:1;333
24.5575;30.3.2026;23:46:30;334
16.9235;30.3.2026;23:46:30;335
14.0415;30.3.2026;23:46:30;336
10.1668;30.3.2026;23:46:31;337
8.4714;30.3.2026;23:46:31;338
6.1600;30.3.2026;23:46:31;339
5.1466;30.3.2026;23:46:31;340
3.7634;30.3.2026;23:46:31;341
2.7582;30.3.2026;23:46:32;342
2.3471;30.3.2026;23:46:32;343
2.0611;30.3.2026;23:46:32;344
1.7971;30.3.2026;23:46:32;345
1.4245;30.3.2026;23:46:33;346
1.0285;30.3.2026;23:46:33;347
0.7728;30.3.2026;23:46:33;348
0.5184;30.3.2026;23:46:34;349
0.2654;30.3.2026;23:46:35;350
0.3121;30.3.2026;23:54:41;351
0.0839;30.3.2026;23:54:41;352
0.0138;30.3.2026;23:54:41;353
24.6414;30.3.2026;23:54:42;354
24.8504;30.3.2026;23:54:42;355
20.5315;30.3.2026;23:55:4;356
16.8506;30.3.2026;23:55:5;357
12.1619;30.3.2026;23:55:5;358
10.1228;30.3.2026;23:55:5;359
7.3453;30.3.2026;23:55:5;360
6.1284;30.3.2026;23:55:6;361
4.4660;30.3.2026;23:55:6;362
3.2601;30.3.2026;23:55:6;363
2.7308;30.3.2026;23:55:6;364
2.2371;30.3.2026;23:55:7;365
2.0749;30.3.2026;23:55:7;366
1.8301;30.3.2026;23:55:7;367
1.5799;30.3.2026;23:55:7;368
1.1564;30.3.2026;23:55:7;369
0.9831;30.3.2026;23:55:8;370
0.7535;30.3.2026;23:55:8;371
0.5885;30.3.2026;23:55:8;372
0.4661;30.3.2026;23:55:8;373
0.3410;30.3.2026;23:55:9;374
0.2365;30.3.2026;23:55:10;375
0.1320;30.3.2026;23:55:13;376
0.0316;30.3.2026;23:55:17;377
###  Messprotokoll Übertragung Ende  ###
########################################
### Messchwellen - Protokoll Ausgabe ###
100;30.3.2026;19:27:26;1
150;30.3.2026;19:28:26;2
200;30.3.2026;19:29:26;3
250;30.3.2026;19:30:26;4
300;30.3.2026;19:31:26;5
350;30.3.2026;19:32:26;6
400;30.3.2026;19:33:27;7
100;30.3.2026;19:37:10;8
100;30.3.2026;19:39:10;9
150;30.3.2026;19:40:10;10
800;30.3.2026;19:41:10;11
100;30.3.2026;22:29:50;12
150;30.3.2026;22:30:50;13
200;30.3.2026;22:31:50;14
250;30.3.2026;22:32:51;15
200;30.3.2026;23:28:50;16
100;30.3.2026;23:39:47;17
150;30.3.2026;23:40:47;18
200;30.3.2026;23:41:47;19
250;30.3.2026;23:45:47;20
300;30.3.2026;23:46:47;21
100;30.3.2026;23:55:1;22
# Messchwelle Protokoll - Ausgabe Ende #
########################################
0 Buffer = 35
Seite Null wurde aufgerufen
Analog-Spannungsueberwachung mit ESP32
NTP Server Abfrage
I2C FRAM gefunden
Aktueller Protokoll Ablagezeiger = 32388
0.0316 Volt -> Datum: 30.03.26 Zeit: 23:55:17 ADR = 3020 # 377
0 Buffer = 101
1 Buffer = 0
2 Buffer = 2
3 Buffer = 0
4 Buffer = 255
5 Buffer = 255
6 Buffer = 255
7 Buffer = 49
Messungen Starten
0 Buffer = 35
Seite Null wurde aufgerufen
4.1965 Volt -> Datum: 30.03.26 Zeit: 23:58:13 ADR = 3028 # 378
24.8476 Volt -> Datum: 30.03.26 Zeit: 23:58:13 ADR = 3036 # 379
24.6758 Volt -> Datum: 30.03.26 Zeit: 23:59:47 ADR = 3044 # 380
16.9964 Volt -> Datum: 30.03.26 Zeit: 23:59:48 ADR = 3052 # 381
14.1006 Volt -> Datum: 30.03.26 Zeit: 23:59:48 ADR = 3060 # 382
10.2108 Volt -> Datum: 30.03.26 Zeit: 23:59:48 ADR = 3068 # 383
7.4154 Volt -> Datum: 30.03.26 Zeit: 23:59:48 ADR = 3076 # 384
6.1889 Volt -> Datum: 30.03.26 Zeit: 23:59:48 ADR = 3084 # 385
4.5155 Volt -> Datum: 30.03.26 Zeit: 23:59:49 ADR = 3092 # 386
3.7744 Volt -> Datum: 30.03.26 Zeit: 23:59:49 ADR = 3100 # 387
2.7665 Volt -> Datum: 30.03.26 Zeit: 23:59:49 ADR = 3108 # 388
2.3843 Volt -> Datum: 30.03.26 Zeit: 23:59:49 ADR = 3116 # 389
2.0859 Volt -> Datum: 30.03.26 Zeit: 23:59:50 ADR = 3124 # 390
1.9429 Volt -> Datum: 30.03.26 Zeit: 23:59:50 ADR = 3132 # 391
1.6390 Volt -> Datum: 30.03.26 Zeit: 23:59:50 ADR = 3140 # 392
1.3695 Volt -> Datum: 30.03.26 Zeit: 23:59:50 ADR = 3148 # 393
1.0175 Volt -> Datum: 30.03.26 Zeit: 23:59:50 ADR = 3156 # 394
0.8731 Volt -> Datum: 30.03.26 Zeit: 23:59:51 ADR = 3164 # 395
0.6765 Volt -> Datum: 30.03.26 Zeit: 23:59:51 ADR = 3172 # 396
0.5376 Volt -> Datum: 30.03.26 Zeit: 23:59:51 ADR = 3180 # 397
0.4771 Volt -> Datum: 30.03.26 Zeit: 23:59:51 ADR = 3188 # 398
0.3933 Volt -> Datum: 30.03.26 Zeit: 23:59:52 ADR = 3196 # 399
0.3300 Volt -> Datum: 30.03.26 Zeit: 23:59:52 ADR = 3204 # 400
0.2640 Volt -> Datum: 30.03.26 Zeit: 23:59:52 ADR = 3212 # 401
0.2131 Volt -> Datum: 30.03.26 Zeit: 23:59:53 ADR = 3220 # 402
0.1623 Volt -> Datum: 30.03.26 Zeit: 23:59:55 ADR = 3228 # 403
0.1073 Volt -> Datum: 30.03.26 Zeit: 23:59:57 ADR = 3236 # 404
0.0564 Volt -> Datum: 30.03.26 Zeit: 23:59:58 ADR = 3244 # 405
0.0055 Volt -> Datum: 31.03.26 Zeit: 00:00:22 ADR = 3252 # 406
0 Buffer = 101
1 Buffer = 0
2 Buffer = 3
3 Buffer = 0
4 Buffer = 255
5 Buffer = 255
6 Buffer = 255
7 Buffer = 50
Daten zum PC übertragen
########################################
### Messprotokoll Übertragung Start  ###
36.4540;30.3.2026;10:17:51;1
36.4554;30.3.2026;11:10:30;2
36.4526;30.3.2026;11:11:18;3
36.4554;30.3.2026;11:14:28;4
36.4540;30.3.2026;11:15:15;5
36.4526;30.3.2026;11:18:9;6
36.4513;30.3.2026;11:26:13;7
36.4513;30.3.2026;12:0:15;8
36.4513;30.3.2026;12:22:58;9
36.4499;30.3.2026;12:25:7;10
36.4568;30.3.2026;12:32:19;11
36.4238;30.3.2026;15:37:37;12
36.4623;30.3.2026;15:43:40;13
36.4636;30.3.2026;15:52:0;14
36.4650;30.3.2026;15:59:29;15
36.4581;30.3.2026;16:25:31;16
36.4609;30.3.2026;18:44:54;17
36.4623;30.3.2026;18:46:56;18
36.4636;30.3.2026;18:52:46;19
36.4636;30.3.2026;19:0:8;20
36.4678;30.3.2026;19:14:59;21
36.4678;30.3.2026;19:17:59;22
36.4691;30.3.2026;19:20:9;23
36.1914;30.3.2026;19:26:39;24
31.8189;30.3.2026;19:26:48;25
25.2739;30.3.2026;19:26:48;26
19.3160;30.3.2026;19:26:50;27
14.3701;30.3.2026;19:26:50;28
25.2711;30.3.2026;19:27:3;29
31.0984;30.3.2026;19:27:5;30
36.1570;30.3.2026;19:27:5;31
36.2093;30.3.2026;19:27:19;32
36.1584;30.3.2026;19:27:25;33
34.8343;30.3.2026;19:27:52;34
25.2863;30.3.2026;19:27:52;35
22.1980;30.3.2026;19:27:54;36
15.5375;30.3.2026;19:27:54;37
14.4059;30.3.2026;19:27:54;38
19.7931;30.3.2026;19:27:55;39
25.2450;30.3.2026;19:27:55;40
36.0443;30.3.2026;19:27:56;41
36.1886;30.3.2026;19:27:56;42
28.9108;30.3.2026;19:27:57;43
25.2725;30.3.2026;19:27:57;44
24.3031;30.3.2026;19:27:58;45
17.1353;30.3.2026;19:27:58;46
14.3880;30.3.2026;19:27:59;47
14.2656;30.3.2026;19:28:0;48
6.4735;30.3.2026;19:28:0;49
3.4334;30.3.2026;19:28:0;50
14.3880;30.3.2026;19:28:3;51
15.5609;30.3.2026;19:28:4;52
25.2643;30.3.2026;19:28:5;53
31.6140;30.3.2026;19:28:32;54
36.1845;30.3.2026;19:28:33;55
28.6935;30.3.2026;19:28:34;56
25.2752;30.3.2026;19:28:34;57
21.3799;30.3.2026;19:28:35;58
14.9091;30.3.2026;19:28:36;59
14.3564;30.3.2026;19:28:36;60
13.4076;30.3.2026;19:29:13;61
8.7271;30.3.2026;19:29:13;62
3.3798;30.3.2026;19:29:14;63
14.3220;30.3.2026;19:29:16;64
25.1268;30.3.2026;19:29:17;65
25.2780;30.3.2026;19:29:17;66
35.1656;30.3.2026;19:29:19;67
36.1625;30.3.2026;19:29:19;68
33.6655;30.3.2026;19:29:20;69
25.3481;30.3.2026;19:29:20;70
24.9975;30.3.2026;19:29:22;71
14.3701;30.3.2026;19:29:22;72
12.9814;30.3.2026;19:29:23;73
8.4260;30.3.2026;19:29:23;74
3.3839;30.3.2026;19:29:23;75
14.3564;30.3.2026;19:29:24;76
24.8366;30.3.2026;19:29:25;77
25.2670;30.3.2026;19:29:25;78
26.6241;30.3.2026;19:29:26;79
36.1969;30.3.2026;19:29:26;80
33.0839;30.3.2026;19:29:28;81
25.2752;30.3.2026;19:29:29;82
20.9633;30.3.2026;19:29:29;83
14.6548;30.3.2026;19:29:29;84
14.4004;30.3.2026;19:29:30;85
13.7390;30.3.2026;19:29:30;86
6.1600;30.3.2026;19:29:31;87
3.3743;30.3.2026;19:29:31;88
4.3711;30.3.2026;19:30:45;89
14.3564;30.3.2026;19:30:45;90
25.2656;30.3.2026;19:30:46;91
35.5011;30.3.2026;19:30:47;92
36.1584;30.3.2026;19:30:47;93
29.4140;30.3.2026;19:30:48;94
25.2904;30.3.2026;19:30:48;95
24.3334;30.3.2026;19:30:49;96
14.3605;30.3.2026;19:30:49;97
12.6252;30.3.2026;19:30:50;98
8.1551;30.3.2026;19:30:50;99
3.3921;30.3.2026;19:30:50;100
13.7376;30.3.2026;19:30:52;101
14.3550;30.3.2026;19:30:52;102
25.2849;30.3.2026;19:30:53;103
32.8364;30.3.2026;19:30:54;104
36.1680;30.3.2026;19:30:54;105
28.8833;30.3.2026;19:30:55;106
25.2849;30.3.2026;19:30:55;107
24.7775;30.3.2026;19:30:56;108
14.3632;30.3.2026;19:30:56;109
12.4905;30.3.2026;19:30:57;110
8.0534;30.3.2026;19:30:57;111
3.3866;30.3.2026;19:30:57;112
11.1183;30.3.2026;19:31:26;113
14.3990;30.3.2026;19:31:27;114
25.1653;30.3.2026;19:31:27;115
33.6023;30.3.2026;19:31:29;116
36.1969;30.3.2026;19:31:29;117
27.9703;30.3.2026;19:31:30;118
25.2423;30.3.2026;19:31:30;119
24.6084;30.3.2026;19:31:31;120
14.4086;30.3.2026;19:31:31;121
13.5589;30.3.2026;19:31:31;122
6.0679;30.3.2026;19:31:32;123
3.3591;30.3.2026;19:31:32;124
14.3646;30.3.2026;19:32:52;125
25.0319;30.3.2026;19:32:53;126
29.3026;30.3.2026;19:32:54;127
36.1666;30.3.2026;19:32:55;128
35.1753;30.3.2026;19:33:8;129
25.2615;30.3.2026;19:33:8;130
19.6928;30.3.2026;19:33:9;131
14.4169;30.3.2026;19:33:9;132
12.2292;30.3.2026;19:33:11;133
7.8554;30.3.2026;19:33:11;134
3.3468;30.3.2026;19:33:11;135
14.3798;30.3.2026;19:33:13;136
21.3139;30.3.2026;19:33:15;137
25.2876;30.3.2026;19:33:15;138
35.9425;30.3.2026;19:33:16;139
34.4520;30.3.2026;19:33:18;140
25.4114;30.3.2026;19:33:19;141
21.9230;30.3.2026;19:33:19;142
15.3436;30.3.2026;19:33:19;143
14.3880;30.3.2026;19:33:20;144
12.6266;30.3.2026;19:33:20;145
8.1703;30.3.2026;19:33:20;146
3.3660;30.3.2026;19:33:20;147
3.3908;30.3.2026;19:36:25;148
3.3399;30.3.2026;19:36:39;149
3.3921;30.3.2026;19:36:40;150
3.3413;30.3.2026;19:36:50;151
3.3921;30.3.2026;19:36:52;152
3.3399;30.3.2026;19:36:53;153
3.3908;30.3.2026;19:36:55;154
3.3399;30.3.2026;19:38:9;155
3.3908;30.3.2026;19:38:10;156
4.4976;30.3.2026;19:38:49;157
5.3048;30.3.2026;19:38:53;158
5.6059;30.3.2026;19:38:53;159
6.6715;30.3.2026;19:38:55;160
7.7729;30.3.2026;19:38:57;161
8.9196;30.3.2026;19:39:0;162
9.9853;30.3.2026;19:39:2;163
10.3895;30.3.2026;19:39:4;164
11.0798;30.3.2026;19:39:5;165
11.6435;30.3.2026;19:39:13;166
12.0890;30.3.2026;19:39:13;167
13.1670;30.3.2026;19:39:15;168
14.3798;30.3.2026;19:39:17;169
15.4055;30.3.2026;19:39:19;170
15.7671;30.3.2026;19:39:20;171
16.5578;30.3.2026;19:39:21;172
17.6660;30.3.2026;19:39:22;173
18.5680;30.3.2026;19:39:24;174
18.6918;30.3.2026;19:39:24;175
19.8248;30.3.2026;19:39:27;176
20.9179;30.3.2026;19:39:29;177
19.8564;30.3.2026;19:39:35;178
18.7055;30.3.2026;19:39:37;179
18.1019;30.3.2026;19:39:41;180
17.6880;30.3.2026;19:39:42;181
17.1504;30.3.2026;19:39:43;182
16.5303;30.3.2026;19:39:43;183
15.4413;30.3.2026;19:39:45;184
14.7221;30.3.2026;19:39:47;185
14.3811;30.3.2026;19:39:47;186
14.2491;30.3.2026;19:39:48;187
13.2413;30.3.2026;19:39:48;188
12.5620;30.3.2026;19:39:50;189
12.1371;30.3.2026;19:39:50;190
11.0866;30.3.2026;19:39:53;191
9.9729;30.3.2026;19:39:54;192
9.6099;30.3.2026;19:39:57;193
8.9279;30.3.2026;19:39:58;194
9.9688;30.3.2026;19:40:16;195
11.0756;30.3.2026;19:40:18;196
12.1330;30.3.2026;19:40:19;197
12.6651;30.3.2026;19:40:21;198
13.2454;30.3.2026;19:40:21;199
14.1116;30.3.2026;19:40:23;200
14.3591;30.3.2026;19:40:23;201
15.1374;30.3.2026;19:40:29;202
15.4220;30.3.2026;19:40:29;203
16.3460;30.3.2026;19:40:31;204
16.5688;30.3.2026;19:40:31;205
17.7004;30.3.2026;19:40:35;206
18.6464;30.3.2026;19:41:4;207
19.6969;30.3.2026;19:41:5;208
20.5260;30.3.2026;19:41:7;209
21.6384;30.3.2026;19:41:8;210
19.9870;30.3.2026;19:41:26;211
11.1045;30.3.2026;19:41:26;212
9.0764;30.3.2026;19:41:27;213
5.4340;30.3.2026;19:41:27;214
0.9597;30.3.2026;19:41:27;215
0.1348;30.3.2026;19:41:27;216
1.1798;30.3.2026;19:41:37;217
2.2935;30.3.2026;19:41:39;218
3.2973;30.3.2026;19:41:41;219
4.4275;30.3.2026;19:41:42;220
5.6045;30.3.2026;19:41:44;221
6.6853;30.3.2026;19:41:46;222
7.7715;30.3.2026;19:41:48;223
8.9196;30.3.2026;19:41:50;224
6.7691;30.3.2026;19:43:9;225
3.6438;30.3.2026;19:43:9;226
0.2338;30.3.2026;19:43:10;227
-1.4905;30.3.2026;19:43:13;228
-3.1405;30.3.2026;19:43:13;229
-1.1371;30.3.2026;19:43:13;230
-3.2010;30.3.2026;19:43:14;231
-2.2000;30.3.2026;19:43:14;232
2.7885;30.3.2026;22:29:20;233
2.8875;30.3.2026;22:29:34;234
2.9948;30.3.2026;22:29:36;235
3.0896;30.3.2026;22:29:39;236
3.1927;30.3.2026;22:30:0;237
3.3866;30.3.2026;22:30:4;238
3.4939;30.3.2026;22:30:5;239
3.6878;30.3.2026;22:30:8;240
3.7881;30.3.2026;22:30:10;241
3.9889;30.3.2026;22:30:13;242
4.0893;30.3.2026;22:30:17;243
4.2873;30.3.2026;22:30:19;244
4.4852;30.3.2026;22:30:23;245
4.6778;30.3.2026;22:30:53;246
4.8854;30.3.2026;22:30:56;247
5.0848;30.3.2026;22:30:59;248
5.2676;30.3.2026;22:31:2;249
5.4753;30.3.2026;22:31:19;250
5.6746;30.3.2026;22:31:27;251
5.8548;30.3.2026;22:31:34;252
6.0761;30.3.2026;22:31:37;253
6.2686;30.3.2026;22:31:39;254
6.4763;30.3.2026;22:31:41;255
7.4470;30.3.2026;22:31:42;256
8.3971;30.3.2026;22:31:43;257
8.6584;30.3.2026;22:31:44;258
9.4628;30.3.2026;22:31:44;259
10.4500;30.3.2026;22:31:46;260
10.1668;30.3.2026;22:31:54;261
9.9633;30.3.2026;22:31:57;262
10.2575;30.3.2026;22:32:15;263
10.5531;30.3.2026;22:32:25;264
10.2726;30.3.2026;22:34:0;265
9.9591;30.3.2026;22:34:5;266
9.9509;30.3.2026;23:36:58;267
10.9436;30.3.2026;23:39:40;268
11.9405;30.3.2026;23:39:40;269
12.9319;30.3.2026;23:39:41;270
13.9205;30.3.2026;23:39:41;271
14.5049;30.3.2026;23:39:41;272
14.9476;30.3.2026;23:39:42;273
15.9074;30.3.2026;23:39:42;274
16.8561;30.3.2026;23:39:42;275
17.8860;30.3.2026;23:39:43;276
18.7564;30.3.2026;23:39:44;277
18.8815;30.3.2026;23:39:44;278
19.8248;30.3.2026;23:39:45;279
19.8798;30.3.2026;23:39:45;280
20.8766;30.3.2026;23:39:46;281
21.8666;30.3.2026;23:39:46;282
23.8535;30.3.2026;23:39:46;283
25.8445;30.3.2026;23:39:47;284
26.8331;30.3.2026;23:39:47;285
28.8159;30.3.2026;23:39:47;286
29.8073;30.3.2026;23:39:47;287
30.8000;30.3.2026;23:39:47;288
29.8224;30.3.2026;23:39:57;289
28.8200;30.3.2026;23:40:23;290
28.3676;30.3.2026;23:40:24;291
27.0298;30.3.2026;23:40:24;292
25.5118;30.3.2026;23:40:25;293
24.1051;30.3.2026;23:40:25;294
22.6064;30.3.2026;23:40:25;295
21.2121;30.3.2026;23:40:25;296
19.6900;30.3.2026;23:40:26;297
17.8970;30.3.2026;23:40:26;298
16.7901;30.3.2026;23:40:26;299
14.9201;30.3.2026;23:40:26;300
13.8174;30.3.2026;23:40:26;301
11.9433;30.3.2026;23:40:27;302
10.8845;30.3.2026;23:40:27;303
8.9595;30.3.2026;23:40:27;304
6.9740;30.3.2026;23:40:27;305
5.9813;30.3.2026;23:40:28;306
5.7076;30.3.2026;23:40:28;307
4.8744;30.3.2026;23:40:28;308
3.9834;30.3.2026;23:40:29;309
3.0058;30.3.2026;23:40:29;310
2.2399;30.3.2026;23:40:29;311
2.0006;30.3.2026;23:40:29;312
1.4616;30.3.2026;23:40:30;313
1.0148;30.3.2026;23:40:30;314
1.4300;30.3.2026;23:40:49;315
2.0006;30.3.2026;23:40:49;316
2.9590;30.3.2026;23:40:50;317
3.9792;30.3.2026;23:40:50;318
4.9761;30.3.2026;23:40:50;319
5.9744;30.3.2026;23:44:58;320
6.8145;30.3.2026;23:44:59;321
8.4906;30.3.2026;23:44:59;322
9.9495;30.3.2026;23:44:59;323
11.4029;30.3.2026;23:44:59;324
12.9305;30.3.2026;23:45:0;325
14.3179;30.3.2026;23:45:0;326
15.9101;30.3.2026;23:45:0;327
17.2219;30.3.2026;23:45:0;328
18.8829;30.3.2026;23:45:1;329
20.8725;30.3.2026;23:45:1;330
21.8652;30.3.2026;23:45:1;331
23.8576;30.3.2026;23:45:1;332
24.8490;30.3.2026;23:45:1;333
24.5575;30.3.2026;23:46:30;334
16.9235;30.3.2026;23:46:30;335
14.0415;30.3.2026;23:46:30;336
10.1668;30.3.2026;23:46:31;337
8.4714;30.3.2026;23:46:31;338
6.1600;30.3.2026;23:46:31;339
5.1466;30.3.2026;23:46:31;340
3.7634;30.3.2026;23:46:31;341
2.7582;30.3.2026;23:46:32;342
2.3471;30.3.2026;23:46:32;343
2.0611;30.3.2026;23:46:32;344
1.7971;30.3.2026;23:46:32;345
1.4245;30.3.2026;23:46:33;346
1.0285;30.3.2026;23:46:33;347
0.7728;30.3.2026;23:46:33;348
0.5184;30.3.2026;23:46:34;349
0.2654;30.3.2026;23:46:35;350
0.3121;30.3.2026;23:54:41;351
0.0839;30.3.2026;23:54:41;352
0.0138;30.3.2026;23:54:41;353
24.6414;30.3.2026;23:54:42;354
24.8504;30.3.2026;23:54:42;355
20.5315;30.3.2026;23:55:4;356
16.8506;30.3.2026;23:55:5;357
12.1619;30.3.2026;23:55:5;358
10.1228;30.3.2026;23:55:5;359
7.3453;30.3.2026;23:55:5;360
6.1284;30.3.2026;23:55:6;361
4.4660;30.3.2026;23:55:6;362
3.2601;30.3.2026;23:55:6;363
2.7308;30.3.2026;23:55:6;364
2.2371;30.3.2026;23:55:7;365
2.0749;30.3.2026;23:55:7;366
1.8301;30.3.2026;23:55:7;367
1.5799;30.3.2026;23:55:7;368
1.1564;30.3.2026;23:55:7;369
0.9831;30.3.2026;23:55:8;370
0.7535;30.3.2026;23:55:8;371
0.5885;30.3.2026;23:55:8;372
0.4661;30.3.2026;23:55:8;373
0.3410;30.3.2026;23:55:9;374
0.2365;30.3.2026;23:55:10;375
0.1320;30.3.2026;23:55:13;376
0.0316;30.3.2026;23:55:17;377
4.1965;30.3.2026;23:58:13;378
24.8476;30.3.2026;23:58:13;379
24.6758;30.3.2026;23:59:47;380
16.9964;30.3.2026;23:59:48;381
14.1006;30.3.2026;23:59:48;382
10.2108;30.3.2026;23:59:48;383
7.4154;30.3.2026;23:59:48;384
6.1889;30.3.2026;23:59:48;385
4.5155;30.3.2026;23:59:49;386
3.7744;30.3.2026;23:59:49;387
2.7665;30.3.2026;23:59:49;388
2.3843;30.3.2026;23:59:49;389
2.0859;30.3.2026;23:59:50;390
1.9429;30.3.2026;23:59:50;391
1.6390;30.3.2026;23:59:50;392
1.3695;30.3.2026;23:59:50;393
1.0175;30.3.2026;23:59:50;394
0.8731;30.3.2026;23:59:51;395
0.6765;30.3.2026;23:59:51;396
0.5376;30.3.2026;23:59:51;397
0.4771;30.3.2026;23:59:51;398
0.3933;30.3.2026;23:59:52;399
0.3300;30.3.2026;23:59:52;400
0.2640;30.3.2026;23:59:52;401
0.2131;30.3.2026;23:59:53;402
0.1623;30.3.2026;23:59:55;403
0.1073;30.3.2026;23:59:57;404
0.0564;30.3.2026;23:59:58;405
0.0055;31.3.2026;0:0:22;406
###  Messprotokoll Übertragung Ende  ###
########################################
### Messchwellen - Protokoll Ausgabe ###
100;30.3.2026;19:27:26;1
150;30.3.2026;19:28:26;2
200;30.3.2026;19:29:26;3
250;30.3.2026;19:30:26;4
300;30.3.2026;19:31:26;5
350;30.3.2026;19:32:26;6
400;30.3.2026;19:33:27;7
100;30.3.2026;19:37:10;8
100;30.3.2026;19:39:10;9
150;30.3.2026;19:40:10;10
800;30.3.2026;19:41:10;11
100;30.3.2026;22:29:50;12
150;30.3.2026;22:30:50;13
200;30.3.2026;22:31:50;14
250;30.3.2026;22:32:51;15
200;30.3.2026;23:28:50;16
100;30.3.2026;23:39:47;17
150;30.3.2026;23:40:47;18
200;30.3.2026;23:41:47;19
250;30.3.2026;23:45:47;20
300;30.3.2026;23:46:47;21
100;30.3.2026;23:55:1;22
150;30.3.2026;23:56:1;23
100;31.3.2026;0:0:43;24
# Messchwelle Protokoll - Ausgabe Ende #
########################################
0 Buffer = 35
Seite Null wurde aufgerufen

Benutzeravatar
Admin
Administrator
Beiträge: 1326
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Langzeit Messgerät mit Protokollierung der Spannung bei Fehlerbedingten Spannungsänderungen

Beitrag von Admin »

Habe noch ein paar Änderungen gemacht, denen ich keine neue Versionsnummer gegeben habe. Also hier das Aktuelle Programm.

Code: Alles auswählen

/* 
    Abfrage von analogen Werten mit dem ESP32
    am ADS1115 mit Weitergabe per I2C an den I2C - FRAM, 
    wenn die Spannung deutlich abweicht vom letzten Messwert. 
    Taste zum Übertragen auf den PC, Taste zum Löschen, bei 32000 byte ist Schluss.
    Schalter für Hohe Schwelle, Autmatische Schwelle, Niedrige Schwelle.
    Anzeige im OLED angepasst 06.02.2026
    Logeintrag bei Automatischer Schwellen Änderung.
    Logeinträge beim Übertrag zum PC auch ausgeben.
    Die Hysterese ist jetzt deutlich verbessert. Sie geht jetzt nach +/- 50mV Stufen 
    Umstieg auf Nextion Display Oled Programmteile entfernt !!
    Programm im Moment vom 31.03.2026 / ADC_ADS1115_NodeMCU_ESP32_Nextion_FRAM_2x4Byte_V72
*/
#include <WiFi.h>
//#define NTP_SERVER "de.pool.ntp.org"
#define NTP_SERVER "Fritz.Box"
#define TZ_INFO "WEST-1DWEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  // Western European Time
//--------------------------------------------------------------------------------------------
#include <Adafruit_ADS1X15.h>  // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
//-----------------------------FRAM-----------------------------------------------------------
#include "Adafruit_EEPROM_I2C.h"
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C i2ceeprom;
#define EEPROM_ADDR 0x50  // the default address!
//--------------------------Serial für Nextion Display----------------------------------------
HardwareSerial Nextion(2);
byte NexT[3] = { 255, 255, 255 };  // global deklarieren
/*
Wird dann so benutzt:
Serial2.write(NexT, 3);
*/
const byte bufferSize = 64;
int Abfragezaehler = 0;
byte PW = 0;
byte PC = 0;
byte KF = 0;
byte ME = 0;
byte MeIO = 0;
byte Seite = 0;  // Nextion Startseite einstellen
//------------------------ADS1115 16Bit Analog-Digital Sensor---------------------------------
const float multiplier = 0.125F;  // ADS1115-Multiplikator bei einf. Verstärkung
int A_Value;                      // Messwert per GPIO
int adc0;                         // Messwert an Kanal 0 des ADS1115
int adc1;                         // Messwert an Kanal 1 des ADS1115
int adc2;                         // Messwert an Kanal 2 des ADS1115
int adc3;                         // Messwert an Kanal 3 des ADS1115
float A_mv, ads_mv0, ads_mv1;     // Messwert in Millivolt umgerechnet
//--------------------------------------------------------------------------------------------
//----------------------- Spannungsmessungen Speichern ---------------------------------------
int Spannungneu = 0;
int Spannung2neu = 0;
int Spannung2alt = 0;
byte Batterie = 1;
float Messung = 0;
float f = 0;
int Hysterese = 50;  // Steht für 50mV rauf oder runter
int Hysterese2 = 0;
const int Hysteresemax = 1000;
const int Hysteresemin = 50;
//------------------ Zeitdaten FRAM ----------------------------------------
uint8_t buffer[4];  // floats are 4 bytes!
int Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int i = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte Reagieren = 0;
int LogZeiger = 32200;
int LogZeiger2 = 32204;
int Uebertragmerker = 0;
//--------------------Tonausgabe PIN 27---------------------------------
const byte TonPin = 27;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//------------------------- Minutentakt zur Zeit - Ausgabe -----------------------------------
unsigned long Sekundenablauf01 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit01 = 60000;
unsigned long Zeitablauf = 0;
//------------------------ PLatzverbrauch am FRAM pro 60sec. ---------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//------------------------ PLatzverbrauch am FRAM pro 1 Std ----------------------------------
unsigned long Sekundenablauf03 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit03 = (60000 * 60);
//-------------------------------- Zeit Messungen --------------------------------------------
unsigned long Messungstart = 0;
unsigned long Messungende = 0;
unsigned long Laufzeit = 0;

//############################################################################################
// ----------------------------------------------------SETUP----------------------------------
//############################################################################################
void setup() {
  Serial.begin(115200);
  delay(500);
  Nextion.begin(9600, SERIAL_8N1, 16, 17);
  Serial.println("Analog-Spannungsueberwachung mit ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // -------------------FRAM Ereichbar ??----------------------
  if (i2ceeprom.begin(0x50)) {  // Sie können die neue I2C-Adresse hier einfügen, z. B. begin(0x51);
    Serial.println(F("I2C FRAM gefunden"));
  } else {
    Serial.println(F("I2C-FRAM nicht identifiziert ... überprüfen Sie Ihre Verbindungen.?\r\n"));
    while (1) delay(10);
  }
  //-----------------------ADS 1115---------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 50000;
  // Wichtige Startdaten aus dem FRAM holen
  Startdaten_holen();
  Messen();
  Serial.println("Messungen Starten");
  Nextion.print("page 0");
  Nextion.write(NexT, 3);
  Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestartet\"");
  Nextion.write(NexT, 3);
  Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
  Nextion.write(NexT, 3);
  MeIO = 1;
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();
  ESPzuNEXT();
  NEXTzuESP();
  //-- Wenn der FRAM nicht voll und Betriebsspannung gut --
  if ((Reagieren < 2) && (Batterie == 1) && (MeIO == 1)) {
    if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
      Displayausgabe();
      Sekundenablauf01 = millis();
    }
    Kontrollen();
    Messen();
    if (Reagieren == 1) {
      SpeicherdatenSchreiben();
      Spannung2alt = Spannung2neu;
      tone(TonPin, 1000, 100);  // Piep wenn sich die Spannung ändert.
      Reagieren = 0;
      // Diese beiden Zeilen unten, werden nur gebraucht,
      // wenn eine Ausgabe auf dem PC, nach Speicherung
      // eines Datensatzes, benötigt wird !!
      SpeicherdatenLesen();
      testprint();
    }
  }
  //------------------------------------------------------
  //
  //--------------- Ist der FRAM voll ?? -----------------
  if (Speicher >= 32000) {
    Nextion.print("Startseite.Meldungen.txt=\"FRAM Speicher ist voll !!\"");
    Nextion.write(NexT, 3);
    tone(TonPin, 440, 1000);
    Reagieren = 2;
  }
}  //---------------------------------- LOOP ENDE --------------------------------------------

//############################################################################################
//-------------------------- WIFI Verbindung und Zeit holen ----------------------------------
//############################################################################################
void NTP_Zeit() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("FRITZ!Box Gastzugang", "GastvonFranzKoehler");
  while (WiFi.status() != WL_CONNECTED)  // Ist WLAN Connect?
  {
    delay(500);
  }
  struct tm local;
  configTzTime(TZ_INFO, NTP_SERVER);  // ESP32 Systemzeit mit NTP Synchronisieren
  getLocalTime(&local, 10000);        // Versuche 10 s zu Synchronisieren
  WiFi.mode(WIFI_OFF);
}
//---------------------------WIFI Verbindung und Zeit Ende -----------------------------------
//
//############################################################################################
//---------------------------- Startdaten aus FRAM holen -------------------------------------
//############################################################################################
void Startdaten_holen() {
  //------- Speicherzeiger auslesen (Protokoll)---------------
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  //--------Letzten Messwert auslesen (Protokoll)-------------
  i2ceeprom.read(32104, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  //--------Letzte Zeit auslesen (Protokoll)------------------
  i2ceeprom.read(32108, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
  time_t t = Zeitbuffer;
  tm tm;
  //--------Ausgabezähler auslesen (Protokoll)----------------
  i2ceeprom.read(32112, buffer, 4);
  memcpy((void *)&Zaehler, buffer, 4);
  //------- Logzeiger auslesen (Protokoll)--------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  //------- Logzeiger1 Eintragen wenn nötig ------------------
  if (LogZeiger < 32204) {
    LogZeiger = 32204;
    memcpy(buffer, (void *)&LogZeiger, 4);
    i2ceeprom.write(32200, buffer, 4);
  }
  Serial.print(F("Aktueller Protokoll Ablagezeiger = "));
  Serial.println(LogZeiger);
  //--------Prokolldaten Ausgeben-----------------------------
  if (Speicher <= 4) {
    Speicher = 4;
    Serial.println(F("########################################"));
    Serial.println(F("# Speicher gelöscht-> Startadresse = 4 #"));
    Serial.println(F("########################################"));
  } else {
    testprint();
  }
}
//-------------------------------- Startdaten holen Ende -------------------------------------
//
//############################################################################################
//---------------------------------- Displayausgabe ------------------------------------------
//############################################################################################
void Displayausgabe() {
  tm local;
  getLocalTime(&local);
  // ------------------------Ausgabe aufs Nesxtion Display------------------------------------
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&local, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&local, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Hysterese.val=");
  Nextion.print(Hysterese);
  Nextion.write(NexT, 3);
  //------------------------------------------------------------------------------------------
  /*
    struct tm enthält diese Atribute:
    ===============================================
    Member   Type  Meaning                   Range
    tm_sec   int   seconds after the minute  0-60*
    tm_min   int   minutes after the hour    0-59
    tm_hour  int   hours since midnight      0-23
    tm_mday  int   day of the month          1-31
    tm_mon   int   months since January      0-11
    tm_year  int   years since 1900
    tm_wday  int   days since Sunday         0-6
    tm_yday  int   days since January 1      0-365
    tm_isdst int   Daylight Saving Time flag
    ==============================================
    */
}
//--------------------------------------------------------------------------------------------
//############################################################################################
// ------------------------------------ Messung per ADS1115 ----------------------------------
//############################################################################################
void Messen() {
  // - Kanal 0 messen (single-ended)
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0);
  // - Kanal 1 messen (single-ended)
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1);
  //===============================================
  ads_mv0 = ads_mv0 * 11;
  Spannung2neu = ads_mv0 * 1000;
  if ((Spannung2alt + Hysterese < Spannung2neu) || (Spannung2alt - Hysterese > Spannung2neu)) {
    Reagieren = 1;
  }
  // Veränderte Spannung anzeigen
  Spannungneu = ads_mv0 * 100;
  if (Spannung2alt == Spannungneu) {
  } else {
    if (Batterie == 1) {
    }
  }
}

// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben---------------------------------------------------------------------
  f = ads_mv0;
  Messung = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Letzen Messwert schreiben (Protokoll)--------------------------------------------------
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(32104, buffer, 4);
  // Zeit & Datum Schreiben-----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit vom letzten Messwert Schreiben (Protokoll)----------------------------------------
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(32108, buffer, 4);
  // Speicherzeiger im FRAM schreiben auf 32100 sichern (Protokoll)-------------------------
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Zähler von letzten Eintrag schreiben (Protokoll)---------------------------------------
  memcpy(buffer, (void *)&Zaehler, 4);
  i2ceeprom.write(32112, buffer, 4);
  //---------------- Letzte Messung aufs Display -------------------------------------------
}
//------------------------------ Schreiben Ende --------------------------------------------
//
//##########################################################################################
//------------------------------ FRAM Auslesen ---------------------------------------------
//##########################################################################################
void SpeicherdatenLesen() {
  // Messwert auslesen----------------------------------------------------------------------
  Speicher2 = Speicher - 4;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&f, buffer, 4);
  // Zeit / Datum auslesen------------------------------------------------------------------
  Speicher2 = Speicher;
  i2ceeprom.read(Speicher2, buffer, 4);
  memcpy((void *)&Zeitbuffer, buffer, 4);
}
//------------------------------ Auslesen Ende --------------------------------------------
//
//#########################################################################################
//-------------------------- Automatik Logs im FRAM ---------------------------------------
//#########################################################################################
void AutoLogschreiben() {
  //------- Logzeiger auslesen (Protokoll)-------------------------------------------------
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger2, buffer, 4);
  //------- Ist im FRAM noch Platz für Logeinträge ?? -------------------------------------
  if (LogZeiger2 <= 32690) {
    //------- Schwelle schreiben ----------------------------------------------------------
    memcpy(buffer, (void *)&Hysterese, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    // Log - Zeit & Datum Schreiben--------------------------------------------------------
    time_t now;
    time(&now);
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&now, 4);
    i2ceeprom.write(LogZeiger2, buffer, 4);
    //Neuen Logzeiger in FRAM schreiben ----------------------------------------------------
    LogZeiger2 = LogZeiger2 + 4;
    memcpy(buffer, (void *)&LogZeiger2, 4);
    i2ceeprom.write(32200, buffer, 4);
    //Serial.println(LogZeiger2);
  }
}
//--------------------------- Automatik Logs Ende ------------------------------------------
//
//##########################################################################################
//-------------------------- FRAM zum PC Übertragen ----------------------------------------
//##########################################################################################
void DatenzumPC() {
  // Messwert auslesen----------------------------------------------------------------------
  Serial.println(F("########################################"));
  Serial.println(F("### Messprotokoll Übertragung Start  ###"));
  Ausgabezaehler = 0;
  UebertragZeiger = 8;
  for (int i = UebertragZeiger; i <= Speicher; i = i + 4) {
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&f, buffer, 4);
    // Zeit / Datum auslesen----------------------------------------------------------------
    i = i + 4;
    i2ceeprom.read(i, buffer, 4);
    memcpy((void *)&Zeitbuffer, buffer, 4);
    time_t t = Zeitbuffer;
    tm tm;
    localtime_r(&t, &tm);
    tm.tm_year += 1900;
    tm.tm_mon += 1;
    Ausgabezaehler++;
    Serial.print(f, 4);
    Serial.print(F(";"));
    Serial.print(tm.tm_mday);
    Serial.print(F("."));
    Serial.print(tm.tm_mon);
    Serial.print(F("."));
    Serial.print(tm.tm_year);
    Serial.print(F(";"));
    Serial.print(tm.tm_hour);
    Serial.print(F(":"));
    Serial.print(tm.tm_min);
    Serial.print(F(":"));
    Serial.print(tm.tm_sec);
    Serial.print(";");
    Serial.println(Ausgabezaehler);
  }
  Serial.println(F("###  Messprotokoll Übertragung Ende  ###"));
  Serial.println(F("########################################"));
  Uebertragmerker = 0;
  //------- Logzeiger auslesen (Protokoll)--------------------
  Serial.println(F("### Messchwellen - Protokoll Ausgabe ###"));
  i2ceeprom.read(32200, buffer, 4);
  memcpy((void *)&LogZeiger, buffer, 4);
  if (LogZeiger >= 32204) {
    Ausgabezaehler = 0;
    UebertragZeiger = 32204;
    for (int i = UebertragZeiger; i < LogZeiger; i = i + 4) {
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Hysterese2, buffer, 4);
      // Zeit / Datum auslesen---------------------------------------------------------------
      i = i + 4;
      i2ceeprom.read(i, buffer, 4);
      memcpy((void *)&Zeitbuffer, buffer, 4);
      time_t t = Zeitbuffer;
      tm tm;
      localtime_r(&t, &tm);
      tm.tm_year += 1900;
      tm.tm_mon += 1;
      Ausgabezaehler++;
      Serial.print(Hysterese2);
      Serial.print(F(";"));
      Serial.print(tm.tm_mday);
      Serial.print(F("."));
      Serial.print(tm.tm_mon);
      Serial.print(F("."));
      Serial.print(tm.tm_year);
      Serial.print(F(";"));
      Serial.print(tm.tm_hour);
      Serial.print(F(":"));
      Serial.print(tm.tm_min);
      Serial.print(F(":"));
      Serial.print(tm.tm_sec);
      Serial.print(";");
      Serial.println(Ausgabezaehler);
    }
  }
  Serial.println(F("# Messchwelle Protokoll - Ausgabe Ende #"));
  Serial.println(F("########################################"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon;
  /*
  Serial.print(f, 4);
  Serial.print(F(" Volt ->"));
  Serial.print(&tm, " Datum: %d.%m.%y");
  Serial.print(&tm, " Zeit: %H:%M:%S");
  Serial.print(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
  */
  Nextion.print("Startseite.LGM.txt=\"");
  Nextion.print(f, 2);
  Nextion.print(F(" V"));
  Nextion.print(&tm, " am %d.%m.%y");
  Nextion.print(&tm, " um %H:%M:%S");
  Nextion.print(" # ");
  Nextion.print(Zaehler);
  Nextion.write('"');
  Nextion.write(NexT, 3);
  //
  Nextion.print("Startseite.Datum.txt=\"");
  Nextion.print(&tm, "%d.%m.%y");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  //
  Nextion.printf("Startseite.Zeit.txt=\"");
  Nextion.print(&tm, "%H:%M");
  Nextion.write('"');
  Nextion.write(NexT, 3);
  //
  Nextion.printf("Startseite.Hysterese.val=");
  Nextion.print(Hysterese);
  Nextion.write(NexT, 3);
}
//-------------------------------- Testprint Ende ------------------------------------------
//
//##########################################################################################
//--------------------------------- FRAM löschem -------------------------------------------
//##########################################################################################
void FRAM_Loeschen() {
  Serial.println(F("########################################"));
  Serial.print(F("# FRAM wird gelöscht "));
  for (i = 0; i <= 32700; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(i, buffer, 4);
  }
  //------- Speicherzeiger auf Start---------------
  // Speicherzeiger = 4 im FRAM auf 32100 sichern
  Speicher = 4;
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  Kontrollzaehler = 0;
  Zaehler = 0;
  Serial.println(F("FRAM IST gelöscht #"));
  Serial.println(F("########################################"));
  Nextion.print("Startseite.Meldungen.txt=\"FRAM ist geloescht\"");
  Nextion.write(NexT, 3);
  //------ Lockfile Zeiger auf Start 32204 setzen --
  //Neuen Logzeiger in FRAM schreiben -------------------------------------------------------
  LogZeiger2 = 32204;
  memcpy(buffer, (void *)&LogZeiger2, 4);
  i2ceeprom.write(32200, buffer, 4);
  //Serial.println(LogZeiger2);
}
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro 60sek. messen
    if ((Kontrollzaehler > 3) && (Hysterese < Hysteresemax)) {
      Hysterese = Hysterese + 50;
      Nextion.printf("Startseite.Hysterese.val=");
      Nextion.print(Hysterese);
      Nextion.write(NexT, 3);
      //Serial.print(F("##### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt erhöht #######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen ob die Schwelle wiede abgesenkt werden kann
  if (Zeitablauf - Sekundenablauf03 >= Pausezeit03) {  // FRAM Aufzeichungen pro Stunde messen
    if ((Kontrollzaehler < 2) && (Hysterese > Hysteresemin)) {
      Hysterese = Hysterese - 50;
      Nextion.printf("Startseite.Hysterese.val=");
      Nextion.print(Hysterese);
      Nextion.write(NexT, 3);
      //Serial.print(F("###### Hysterese Automatisch auf -> "));
      //Serial.print(Hysterese);
      //Serial.println(F(" mVolt runtergesetz ######"));
      Kontrollzaehler = 0;
      AutoLogschreiben();
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  // Prüfen, ob Betriebsspannung des Gerätes zu niedrig
  if (ads_mv1 <= 3) {
    Batterie = 0;
  } else {
    Batterie = 1;
  }
  // Prüfen ob die Zeit wieder vom Server geholt werden muss.
  tm local;
  //00:00:XX = 3600(=1 Std) * std = 0 + min = 0 * 60 = 0 + sec = maximal 59 sec
  uint32_t nbSek = 3600ul * local.tm_hour + local.tm_min * 60ul + local.tm_sec;
  if (nbSek <= 2)  // zwischen 00:00:00 Uhr und 00:00:59 Uhr Zeit vom NTP holen
  {
    NTP_Zeit();
  }
}
//------------------------------- Kontrollen Ende -----------------------------------------
//#########################################################################################
//########################## Kommunikation mit dem Nextion ################################
//#########################################################################################
//
void ESPzuNEXT() {
  Nextion.print("dim=50");  // Display wird etwas gedimmt
  Nextion.write(NexT, 3);
  if (Seite != 0) {
    Nextion.print("page 0");  // Ausgabe Seite ist "page 0"
    Nextion.write(NexT, 3);
    Seite = 0;
  }
  Nextion.print("Startseite.Byte.val=");
  Nextion.print(Speicher);
  Nextion.write(NexT, 3);
  Nextion.printf("Startseite.Volt2.txt=\"%5.3f\"", ads_mv0);
  Nextion.write(NexT, 3);
}
//######################################################################################
//########################### Rückmeldung vom Nextion auswerten ########################
//######################################################################################
//
void NEXTzuESP() {
  static uint8_t bIndex;
  static uint8_t buffer[bufferSize];
  if (Nextion.available()) {
    if (Abfragezaehler == 0) {
      delay(300);
    }
    uint8_t inChar = Nextion.read();
    buffer[bIndex++] = inChar;
    if ((buffer[0] == 101) || (buffer[0] == 80) || (buffer[0] == 35) || (buffer[0] == 26) || (buffer[0] == 45) || (buffer[0] == 43)) {
      Abfragezaehler = 0;
    }

    Serial.print(Abfragezaehler);
    Serial.print(" Buffer = ");
    Serial.println(buffer[0]);
    //----------------------------------- Menüseite wurde aufgerufen -------------
    if ((Abfragezaehler == 0) && (buffer[0] == 35)) {  // page 0 Start
      Serial.println(F("Seite Null wurde aufgerufen"));
      if (MeIO == 1) {
        Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
        Nextion.write(NexT, 3);
      }
    }
    // -------------------------------- Hysterese + Abfragen ---------------------
    if ((Abfragezaehler == 0) && (buffer[0] == 43)) {  // Hysterese plus ?
      if (Hysterese < Hysteresemax) {
        Hysterese = Hysterese + 50;
        Nextion.printf("Startseite.Hysterese.val=");
        Nextion.print(Hysterese);
        Nextion.write(NexT, 3);
      }
    }
    // -------------------------------- Hysterese - Abfragen ---------------------
    if ((Abfragezaehler == 0) && (buffer[0] == 45)) {  // Hysterese minus ?
      if (Hysterese > Hysteresemin) {
        Hysterese = Hysterese - 50;
        Nextion.printf("Startseite.Hysterese.val=");
        Nextion.print(Hysterese);
        Nextion.write(NexT, 3);
      }
    }
    // -----------------------------FRAM löschen Taste + PW Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 80)) {  // P? für Passwort
      PW = PW + 1;
    }
    if ((Abfragezaehler == 1) && (buffer[0] == 51)) {  // 3?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 54)) {  // 6?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (buffer[0] == 57)) {  // 9?
      PW = PW + 1;
    }
    if ((Abfragezaehler == 4) && (PW == 5)) {
      Serial.println("Passwort ist korrekt");
      Nextion.printf("PasswortAW.t0.txt=\"\"");  // Passwort löschen
      Nextion.write(NexT, 3);
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"FRAM wird geloescht !!\"");
      Nextion.write(NexT, 3);
      PW = 0;
      FRAM_Loeschen();
    }
    if ((Abfragezaehler == 4) && (PW < 5)) {  // Ist es nicht die FRAM - löschne Taste
      PW = 0;
    }
    //----------------------------------------------------------------------------
    // --------------------------------------- Daten zum PC Abfrage --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 3)) {  // Daten zum PC ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 50)) {  // Taste 2 ?
      PC = PC + 1;
    }
    if ((Abfragezaehler == 7) && (PC < 3)) {  // Ist es nicht die Daten zum PC Taste
      PC = 0;
    }
    if ((Abfragezaehler == 7) && (PC == 3)) {
      PC = 0;
      Serial.println("Daten zum PC übertragen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Daten wurden zum PC uebertragen\"");
      Nextion.write(NexT, 3);
      DatenzumPC();
    }
    //----------------------------------------------------------------------------
    // ----------------------------------------- Messungen Starten Abfrage -------
    if ((Abfragezaehler == 0) && (buffer[0] == 101)) {  // Tasten Event ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 2) && (buffer[0] == 2)) {  // Taste Messungen IO ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (buffer[0] == 49)) {  // Taste 1 ?
      ME = ME + 1;
    }
    if ((Abfragezaehler == 7) && (ME < 3)) {  // ist es nicht die ME - Taste
      ME = 0;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 0)) {
      ME = 0;
      Serial.println("Messungen Starten");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestartet\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Stopp\"");
      Nextion.write(NexT, 3);
      MeIO = 1;
    }
    if ((Abfragezaehler == 7) && (ME == 3) && (MeIO == 1)) {
      ME = 0;
      Serial.println("Messungen Stoppen");
      Nextion.print("page 0");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.Meldungen.txt=\"Messungen wurden gestoppt\"");
      Nextion.write(NexT, 3);
      Nextion.print("Startseite.MessungStart.txt=\"Messungen Start\"");
      Nextion.write(NexT, 3);
      MeIO = 0;
    }
    //-------------------- Kommunikations Fehler ESP32 -> Nextion --------------
    if ((Abfragezaehler == 0) && (buffer[0] == 26)) {  // Fehler ?
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (buffer[0] == 255)) {
      KF = KF + 1;
    }
    if ((Abfragezaehler == 3) && (KF == 2)) {
      Serial.println("Kommunikations Fehler");  // Kommunikationsfehler ESP -> Next
      KF = 0;
    }
    if ((Abfragezaehler == 3) && (KF < 2)) {
      KF = 0;
    }
  }
  //----------------------------------------------------------------------------
  Abfragezaehler++;
  bIndex = 0;
}
Übrigens speichert das Gerät bei jedem Neustart gleich die erste Messung ab. denn es startet ja mit einem Spannung Alt Wert von 0,00 Volt, vergleicht mit dem aktuell anliegenden Wert und da der in der Regel nicht Null ist, kommt beim Vergleich der Messung Alt, mit Messung Neu, natürlich eine Spannungsänderung zustande. So gibt es bei Betriebsbeginn immer gleich eine Erste Spannung im Speicher.

Hier ist noch das HMI File vom Nextion Editor. Mit dem aktuellen Stand passend zum Programm.
Antworten

Zurück zu „Hardware / Schaltungstechnik“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste