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

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

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

Beitrag von Admin »

Wärend den Tests mit den FRAM Bausteinen bin ich jetzt auf ein Gerät gekommen das ich mir bauen möchte. Ein Gerät zum Aufzeichenen einer Spannungsversorgung über Stunden, Tage, Wochen. Ich habe in meiner Arbeitszeit oft ein Gerät vermisst, mit dem ich eine Versorgungsspannung für ein Gerät überwachen möchte, weil ich glaube es fällt manchmal aus, weil sein Netzteil manchmal kurzzeitig die Gretsche macht. Ein Gerät das über lange Zeit die Spannung überwacht, indem es jede Zentel Sekunde über sehr lange Zeiten im Speicher notiert, wenn die Kontrollierte Spannung sich verändert. Es notiert dann, sobald sich die Spannung verändert, die Spannung, die Uhrzeit und das Datum dess Vorfalles. Also immer, wenn sich die Spannung nach unten oder oben, auch nur geringfügig ändert, wird das genau festgehalten.

Ja, das mache ich mir jetzt als Messgerät für mich. Und bringe es dann natürlich hier auch wieder unter fertige Geräte, mit Schaltplan, Programm, Beschreibung und Bildern.

Hier ist mal das Bild der Schaltung wie ich es jetzt fürs erste mal zum Testen verwende. Das 10k Poti am A1 ist später der Messeingang. Im Moment kann ich über das Poti die Eingangsspannung für die Tests verändern. Mit dem Schalter möchte ich die Empfindlichkeit des Gerätes, also die Schwelle auf die das Gerät reagiert dann ändern können. Also im Moment schwebt mir vor, Stellung eins Spannungsänderung vor dem Komma, Stellung zwei, Spannungsänderung, erste Nachkommastelle, Stellung drei, Spannungsänderung, zweite Nachkommastelle. ISt aber alles noch nicht Fertig - Gedacht in der Birne.
.
Spannungsüberwachung mit FRAM.JPG
Spannungsüberwachung mit FRAM.JPG (225.07 KiB) 1261 mal betrachtet
Testaubau_Langzeitmessung.jpg
Testaubau_Langzeitmessung.jpg (343.59 KiB) 1260 mal betrachtet
Hier ist das Programm, das jetzt schon in diese Richtung geht, wo ich hin möchte. Da muss ich noch ein paar Dinge dazu schreiben, dann wird es brauchbar, für ein Gerät, das man mal da, mal da, ganz gut gebrauchen kann. Hier mal das Programm:

Code: Alles auswählen

/*
Langzeitmessungen mit ESP32 D1 Mini, I2C-ADS1115, I2C-OLED, I2C-FRAM 32KB.S
Version V2.1 vom 05.01.2026 
*/

Ich habe das Programm nochmal rausgenommen. Ich habe mich zu früh gefreut. Aber ich bleibe dran !!

}
Das Programm macht jetzt alle 18ms eine Messung. Wenn diese Messung sich mindestens an der zweiten Stelle hinterm Komma verändert, zeichnet es Datum, Uhrzeit, Spannung auf. Das sind 8 Byte. Also bei 32000 Byte 4000 Aufzeichungen, dann ist der Speicher voll. Wohlgemerkt nur, wenn sich die Spannung in einem Bereich ändert, wo es nicht sein darf. Wenn die Speicherstelle 20000 erreicht ist, das sind 2500 Aufzeichnungen, wird nur noch auf Veränderungen bis zur ersten Stelle hinterm Komma aufgezeichnet. Wenn 25000 Speicherstellen voll sind, also bei 3125 Aufzeichnungen, wird nur nur noch auf Änderungen vor dem Komma reagiert, also aufgezeichnet. So ist jedenfalls jetzt der Stand dess Programmes. Bei 32000 Speicherstellen, also 4000 Aufzeichungen, wird die Aufzeichung beendet !! Da ändert sich aber sicher noch eine ganze Menge.

Jetzt muss ich noch bei jeder Adresserhöhung, also bei jeder Aufzeichnung, an der Speicherstelle 0 die Adresse für die nächste Aufzeichnung eintragen, so dass das Gerät nach einem Spannungsausfall diesen Zeiger nicht verliert. So kann es beim zurückkommen der Betriebsspannung, erst schauen, ob auf Adresse "0" etwas größer als Null steht, und wenn ja, an dem Punkte weitermachen, wo es aufgehört hat. Ich möchte aber auch noch einen Akku einbauen, dass es eigentlich nicht ausfallen kann. Dann muss ich auch noch einen Programmteil haben, bei dem ich die Daten aus dem Speicher so oft auf einen PC über USB übertragen kann wie ich will. Und wenn ich die Daten nicht mehr brauche, auch löschen kann.
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 Stress mit meinem Programm. Aber ich bleibe dran. Das sind neue Dinge, die nicht soooo einfach sind, wie ein paar Sensoren abfragen und danach irgendwas zu steuern. Aber es kommt.
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 beschäftige mich mit dem Format der UTC Zeit. Da werden Datum und Uhrzeit in eine Zahl gerechnet, die Sekunden seit 1970 beinhaltet. Das sieht dann z.B. so aus:
Zeitberechnung.jpg
Zeitberechnung.jpg (93.76 KiB) 451 mal betrachtet
Hier gehe ich von dem UTC Wert "1.769.353.173 Sek." aus, der zum Zeitpunkt, "25.01.2026 / 15:59:33" mit einem erhobenen Messwert in den FRAM geschrieben wurde. Minus 3600 Sekunden (eine Std.) fallen in unserer Zeitzone in der Winterzeit an. Im Sommer stehen da 7200 Sekunden zuviel, weil wir im Sommer 2 Std. unter der UTC liegen.

In der Grafik hier sieht man wie aus aktuell Datum & Uhrzeit der Wert wird, indem die ganze Invormation gespeichert ist. Also vergangene Sekunden seit 1970.
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 jetzt habe ich ein Grundprogramm, auf das ich aufbauen kann. Ich hatte Probleme damit, Datum und Uhrzeitim FRAM zu speichern und aus dem FRAM wieder auszugeben. Da hatte ich heute gute Unterstützen im ArduinoCC Forum. Es geht noch viel weiter, aber die Funktion die ich zu Beginn wollte, ist erreicht. Inzwischen sind die Vorstellungen, was das können soll, stück für Stück gewachsen. Aber das ist ja gut. Es ist ein Hobby mit dem ich immer bischen vordere.

Hier ist mal 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. 
    Programm im Moment vom 03.02.2026 / ADC_ADS1115_ESP32_Mini_OLE_FRAM_2x4Byte_V10
*/
#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 Spannung2neu = 0;
int Spannung2alt = 0;
float f = 0;
uint8_t buffer[4];  // floats are 4 bytes!
uint32_t Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int Kontrollzaehler = 0;
byte LSpin = 27;
byte Messtiefe = 100;
byte Reagieren = 0;
//------------------------- Minuten Tackt zur 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 1 Min ----------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//-------------------------------- 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-Test ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // ------------------EPROM 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);
  //----------------------- Oled Display ---------------------
  oled.begin();
  oled.clearBuffer();  // Textspeicher löschen
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 60000;
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();

  if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
    Displayausgabe();
    Sekundenablauf01 = millis();
  }
  Kontrollen();
  Messen();
  if (Reagieren == 1) {
    SpeicherdatenSchreiben();
    Spannung2alt = Spannung2neu;
    SpeicherdatenLesen();
    testprint();
    Reagieren = 0;
  }
  /*
  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);
}
//############################################################################################
//---------------------------------- 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");
  // Hier das Problem. Die Zeitausgabe
  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.println(F("ADR "));
  oled.print(Speicher);
  //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.
  // -----------------------------------------------------------------------------------------
  Spannung2neu = ads_mv0 * Messtiefe;
  if (Spannung2alt == Spannung2neu) {
  } else {
    // Messung auf das Display ausgeben
    oled.setFont(u8g2_font_10x20_mf);
    //ADS Kanal 0 anzeigen
    oled.setCursor(20, (2 * 20));
    oled.println(F("ADR "));
    oled.print(Speicher + 4);
    //ADS Kanal 1 anzeigen
    oled.setCursor(20, (3 * 20));
    oled.print(ads_mv0);
    oled.print(F(" Volt "));
    oled.sendBuffer();
    Reagieren = 1;
    tone(LSpin, 1000, 100);  // Piep wenn sich die Spannung ändert.
  }
}
// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Display aktualisieren-----------------------------------------------------------------
  oled.setCursor(20, (2 * 20));
  oled.println(F("ADR "));
  oled.print(Speicher);
  //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 ---------------------------------------------
//
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon += 1;
  Serial.print(f, 8);
  Serial.print(F(" Volt ->"));
  //Serial.print(F(" ZeitBuffer = "));
  //Serial.print(Zeitbuffer);
  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(F(" ADR = "));
  Serial.print(Speicher);
  Serial.print(F(" # "));
  Serial.println(Zaehler);
}
//-------------------------------- Testprint Ende ------------------------------------------
//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro Minute messen
    if ((Kontrollzaehler >= 10) && (Messtiefe > 1)) {
      Messtiefe = Messtiefe / 10;
      Serial.print(F("###### Messtiefe Automatisch auf -> "));
      Serial.print(Messtiefe);
      Serial.println(F(" <- verringert #########"));
      Kontrollzaehler = 0;
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  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 -------------------------------------------
Hier ist ein erster Serial Print von den Messungen des Gerätes. Die Werte werden erst am FRAM gespeichert, dann aus dem FRAM Rückgelesen und Serial ausgegeben. Das ganze ist natürlich erst mal eine Testversion. Macht noch keinen Sinn, damit was zu bauen. Da ist noch keine Speicherkontrolle, kein Löschen des Speichers, bei Beginn einer neuen Spannungs Überwachung. Aber das ist keine große Aktion. Auch möchte ich noch einen zweiten Überwachnugnskanal einrichten. Und wenn zu viele Aufzeichnungen in zu kurzer Zeit kommen, wird die Reaktions - Schwelle automatisch angehoben. Ich möchte das Gerät auch mit einem fetten Akku versorgen, dass es auch ein Paar Tage Autark versorgt ist. Das ist der Plan.

Code: Alles auswählen

Rücklesen: 3.29400015 Zeitbuffer = 1770051895 Datum: 2.2.2026 Zeit: 18:4:55 ->  Zeiger = 20 ->  Einträge = 2
 Rücklesen: 3.19475007 Zeitbuffer = 1770051896 Datum: 2.2.2026 Zeit: 18:4:56 ->  Zeiger = 28 ->  Einträge = 3
 Rücklesen: 3.09475017 Zeitbuffer = 1770051896 Datum: 2.2.2026 Zeit: 18:4:56 ->  Zeiger = 36 ->  Einträge = 4
 Rücklesen: 3.10262513 Zeitbuffer = 1770051896 Datum: 2.2.2026 Zeit: 18:4:56 ->  Zeiger = 44 ->  Einträge = 5
 Rücklesen: 3.21737504 Zeitbuffer = 1770051896 Datum: 2.2.2026 Zeit: 18:4:56 ->  Zeiger = 52 ->  Einträge = 6
 Rücklesen: 3.30175018 Zeitbuffer = 1770051896 Datum: 2.2.2026 Zeit: 18:4:56 ->  Zeiger = 60 ->  Einträge = 7
 Rücklesen: 3.29912519 Zeitbuffer = 1770051912 Datum: 2.2.2026 Zeit: 18:5:12 ->  Zeiger = 68 ->  Einträge = 8
 Rücklesen: 3.19987512 Zeitbuffer = 1770051914 Datum: 2.2.2026 Zeit: 18:5:14 ->  Zeiger = 76 ->  Einträge = 9
 Rücklesen: 3.09750009 Zeitbuffer = 1770051916 Datum: 2.2.2026 Zeit: 18:5:16 ->  Zeiger = 84 ->  Einträge = 10
 Rücklesen: 2.99825025 Zeitbuffer = 1770051917 Datum: 2.2.2026 Zeit: 18:5:17 ->  Zeiger = 92 ->  Einträge = 11
 Rücklesen: 2.89975023 Zeitbuffer = 1770051918 Datum: 2.2.2026 Zeit: 18:5:18 ->  Zeiger = 100 ->  Einträge = 12
 Rücklesen: 2.90012503 Zeitbuffer = 1770051919 Datum: 2.2.2026 Zeit: 18:5:19 ->  Zeiger = 108 ->  Einträge = 13
 Rücklesen: 3.00262523 Zeitbuffer = 1770051920 Datum: 2.2.2026 Zeit: 18:5:20 ->  Zeiger = 116 ->  Einträge = 14
 Rücklesen: 3.10075021 Zeitbuffer = 1770051921 Datum: 2.2.2026 Zeit: 18:5:21 ->  Zeiger = 124 ->  Einträge = 15
 Rücklesen: 3.20037508 Zeitbuffer = 1770051923 Datum: 2.2.2026 Zeit: 18:5:23 ->  Zeiger = 132 ->  Einträge = 16
 Rücklesen: 3.30100012 Zeitbuffer = 1770051923 Datum: 2.2.2026 Zeit: 18:5:23 ->  Zeiger = 140 ->  Einträge = 17
Der zuletzt gespeicherte Messwert wie mit dem Zeiger auf die Aktuellen Adresszeiger im FRAM in Display angezeigt.
.
Spannungsüberwachnung 01.jpg
Spannungsüberwachnung 01.jpg (548.09 KiB) 231 mal betrachtet
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 »

Jetzt habe ich mal zwei weitere Funktionen im Programm. Speicher auf PC Übertragen und Speicher bis 0 - 32000 löschen. Also es ruft das Löschen als erstes schon im Setup auf, und wenn im Programm gleich/mehr als 50 Einträge in FRAM geschrieben wurden, ruft er aus dem LOOP die Funktion Übertagung zum PC auf. Da wird übertragen bis zum aktuellen Speicherstand. Dann schreibt er wieder da weiter wo er war. Ist alles nur Test, aber läuft. Als nächstes muss ich jetzt mal den SpeicherZeiger im FRAM sichern, immer wenn er erhöht wird. Den Zeiger werde ich oberhalb 32000 schreiben, diese 768 Byte da oben, bleiben für "verschiedenes". Es kann sein, dass ich für Protokolle noch 2000 Byte über 30000 verwenden werde. Das ist noch nicht so endgültig ausgegoren, in meiner Matschbirne. :(o): Da wird dann drinstehen, wenn das Programm die Reaktionsschwelle Automatisch hochgesetzt hat, weil es zu viele Spannungsschwankungen in der niedrigeren Schwelle gegen hat. Dann stetzt das Programm die Schwelle hoch, weil dieses Gerät ja nicht für eine Spannungsüberwachung von ein paar Minunten und Stunden gedacht ist, sondern über Tage, Wochen, Monate. Da sind 4000 Einträge schnell mal zu wenig. Also muss mal nur diese Schwankungen aufzeichnen, die zu Ausfällen des überwachten Gerätes führen können. Diese Schwankungen finden in der Regel vor dem Komma einer Spannungsmessung statt. Deshalb fange ich zwei Stellen hinterm Komma an, dann wird die Schwelle, wenn nötig, auf die erste Stelle hinterm Komma hochgezogen. Und wenn das noch nicht reicht, wird nur noch auf Veränderungen vor dem Komma geschaut.

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. 
    Programm im Moment vom 04.02.2026 / ADC_ADS1115_ESP32_Mini_OLE_FRAM_2x4Byte_V11
*/
#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 Spannung2neu = 0;
int Spannung2alt = 0;
float f = 0;
uint8_t buffer[4];  // floats are 4 bytes!
uint32_t Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte LSpin = 27;
byte Messtiefe = 100;
byte Reagieren = 0;
//------------------------- Minuten Tackt zur 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 1 Min ----------------------------------
unsigned long Sekundenablauf02 = 0;  // Zeit für die Ausgabe Aufs Display & Serial
const unsigned long Pausezeit02 = 60000;
//-------------------------------- 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-Test ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // ------------------EPROM 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);
  //----------------------- Oled Display ---------------------
  oled.begin();
  oled.clearBuffer();  // Textspeicher löschen
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 60000;
  FRAM_Loeschen();
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();

  if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
    Displayausgabe();
    Sekundenablauf01 = millis();
  }
  Kontrollen();
  Messen();
  if (Reagieren == 1) {
    SpeicherdatenSchreiben();
    Spannung2alt = Spannung2neu;
    SpeicherdatenLesen();
    testprint();
    Reagieren = 0;
  }
  if ((Zaehler >= 50) && (DzPja == 0)) {
    DatenzumPC();
    DzPja = 1;
  }
  /*
  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);
}
//############################################################################################
//---------------------------------- 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");
  // Hier das Problem. Die Zeitausgabe
  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.println(F("ADR "));
  oled.print(Speicher);
  //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.
  // -----------------------------------------------------------------------------------------
  Spannung2neu = ads_mv0 * Messtiefe;
  if (Spannung2alt == Spannung2neu) {
  } else {
    // Messung auf das Display ausgeben
    oled.setFont(u8g2_font_10x20_mf);
    //ADS Kanal 0 anzeigen
    oled.setCursor(20, (2 * 20));
    oled.println(F("ADR "));
    oled.print(Speicher + 4);
    //ADS Kanal 1 anzeigen
    oled.setCursor(20, (3 * 20));
    oled.print(ads_mv0);
    oled.print(F(" Volt "));
    oled.sendBuffer();
    Reagieren = 1;
    tone(LSpin, 1000, 100);  // Piep wenn sich die Spannung ändert.
  }
}
// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Display aktualisieren-----------------------------------------------------------------
  oled.setCursor(20, (2 * 20));
  oled.println(F("ADR "));
  oled.print(Speicher);
  //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 ---------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("####  Daten zum PC Übertragen  ####"));
  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("####  Daten wurden Übertragen  ####"));
}
//------------------------------ Auslesen Ende ---------------------------------------------
//##########################################################################################
//-------------------------------- Testprint -----------------------------------------------
//##########################################################################################
void testprint() {
  time_t t = Zeitbuffer;
  tm tm;
  localtime_r(&t, &tm);
  tm.tm_year += 1900;
  tm.tm_mon += 1;
  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.print("FRAM wird gelöscht -> ");
  for (int i = 0; i <= 32000; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(Speicher, buffer, 4);
  }
  Serial.println("FRAM IST gelöscht");
}

//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro Minute messen
    if ((Kontrollzaehler >= 10) && (Messtiefe > 1)) {
      Messtiefe = Messtiefe / 10;
      Serial.print(F("###### Messtiefe Automatisch auf -> "));
      Serial.print(Messtiefe);
      Serial.println(F(" <- verringert #########"));
      Kontrollzaehler = 0;
    }
    Sekundenablauf02 = millis();
    Kontrollzaehler = 0;
  }
  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 -------------------------------------------
Und hier ist jetzt die Serial.print() Ausgabe dieses Programmes am PC. Nach 50 Ausgaben der Spannungsabweichungen, kommt Automatisch das Auslesen der 50 Speicherungen aus dem FRAM. Dann geht wieder weiter mit der normalen Serial.print() Ausgabe, bis 63 und dann ist eine Minute um, und das Programm sieht, dass die Alarm - Schwelle zu nieder ist. Also wird die Messtiefe verringert. Und die Augaben gehen weiter bis 71. Natürlich muss ich kräftig am Poti drehen, dass so viele und große Abweichungen in der "überwachten" Spannung entstehen. Ist eben nur ein Test.

Code: Alles auswählen

ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4980
load:0x40078000,len:16612
load:0x40080400,len:3500
entry 0x400805b4
Analog-Test ESP32
NTP Server Abfrage
I2C FRAM gefunden
FRAM wird gelöscht -> FRAM IST gelöscht
3.3049 Volt -> Datum: 04.03.26 Zeit: 16:30:52 ADR = 12 # 1
3.2981 Volt -> Datum: 04.03.26 Zeit: 16:30:59 ADR = 20 # 2
3.2805 Volt -> Datum: 04.03.26 Zeit: 16:30:59 ADR = 28 # 3
3.2780 Volt -> Datum: 04.03.26 Zeit: 16:30:59 ADR = 36 # 4
3.2675 Volt -> Datum: 04.03.26 Zeit: 16:30:59 ADR = 44 # 5
3.2494 Volt -> Datum: 04.03.26 Zeit: 16:30:59 ADR = 52 # 6
3.2398 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 60 # 7
3.2256 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 68 # 8
3.2171 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 76 # 9
3.1984 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 84 # 10
3.1831 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 92 # 11
3.1784 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 100 # 12
3.1685 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 108 # 13
3.1543 Volt -> Datum: 04.03.26 Zeit: 16:31:00 ADR = 116 # 14
3.1476 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 124 # 15
3.1378 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 132 # 16
3.1208 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 140 # 17
3.1043 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 148 # 18
3.0971 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 156 # 19
3.0846 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 164 # 20
3.0784 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 172 # 21
3.0696 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 180 # 22
3.0541 Volt -> Datum: 04.03.26 Zeit: 16:31:01 ADR = 188 # 23
3.0493 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 196 # 24
3.0399 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 204 # 25
3.0299 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 212 # 26
3.0175 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 220 # 27
2.9984 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 228 # 28
2.9888 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 236 # 29
2.9711 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 244 # 30
2.9533 Volt -> Datum: 04.03.26 Zeit: 16:31:02 ADR = 252 # 31
2.9496 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 260 # 32
2.9395 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 268 # 33
2.9299 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 276 # 34
2.9189 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 284 # 35
2.9084 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 292 # 36
2.8996 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 300 # 37
2.8871 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 308 # 38
2.8719 Volt -> Datum: 04.03.26 Zeit: 16:31:03 ADR = 316 # 39
2.8616 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 324 # 40
2.8570 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 332 # 41
2.8475 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 340 # 42
2.8363 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 348 # 43
2.8200 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 356 # 44
2.8116 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 364 # 45
2.8098 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 372 # 46
2.7999 Volt -> Datum: 04.03.26 Zeit: 16:31:04 ADR = 380 # 47
2.7891 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 388 # 48
2.7925 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 396 # 49
2.8241 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 404 # 50
####  Daten zum PC Übertragen  ####
3.3049 # 4.2.2026 # 16:30:52 # 1
3.2981 # 4.2.2026 # 16:30:59 # 2
3.2805 # 4.2.2026 # 16:30:59 # 3
3.2780 # 4.2.2026 # 16:30:59 # 4
3.2675 # 4.2.2026 # 16:30:59 # 5
3.2494 # 4.2.2026 # 16:30:59 # 6
3.2398 # 4.2.2026 # 16:31:0 # 7
3.2256 # 4.2.2026 # 16:31:0 # 8
3.2171 # 4.2.2026 # 16:31:0 # 9
3.1984 # 4.2.2026 # 16:31:0 # 10
3.1831 # 4.2.2026 # 16:31:0 # 11
3.1784 # 4.2.2026 # 16:31:0 # 12
3.1685 # 4.2.2026 # 16:31:0 # 13
3.1543 # 4.2.2026 # 16:31:0 # 14
3.1476 # 4.2.2026 # 16:31:1 # 15
3.1378 # 4.2.2026 # 16:31:1 # 16
3.1208 # 4.2.2026 # 16:31:1 # 17
3.1043 # 4.2.2026 # 16:31:1 # 18
3.0971 # 4.2.2026 # 16:31:1 # 19
3.0846 # 4.2.2026 # 16:31:1 # 20
3.0784 # 4.2.2026 # 16:31:1 # 21
3.0696 # 4.2.2026 # 16:31:1 # 22
3.0541 # 4.2.2026 # 16:31:1 # 23
3.0493 # 4.2.2026 # 16:31:2 # 24
3.0399 # 4.2.2026 # 16:31:2 # 25
3.0299 # 4.2.2026 # 16:31:2 # 26
3.0175 # 4.2.2026 # 16:31:2 # 27
2.9984 # 4.2.2026 # 16:31:2 # 28
2.9888 # 4.2.2026 # 16:31:2 # 29
2.9711 # 4.2.2026 # 16:31:2 # 30
2.9533 # 4.2.2026 # 16:31:2 # 31
2.9496 # 4.2.2026 # 16:31:3 # 32
2.9395 # 4.2.2026 # 16:31:3 # 33
2.9299 # 4.2.2026 # 16:31:3 # 34
2.9189 # 4.2.2026 # 16:31:3 # 35
2.9084 # 4.2.2026 # 16:31:3 # 36
2.8996 # 4.2.2026 # 16:31:3 # 37
2.8871 # 4.2.2026 # 16:31:3 # 38
2.8719 # 4.2.2026 # 16:31:3 # 39
2.8616 # 4.2.2026 # 16:31:4 # 40
2.8570 # 4.2.2026 # 16:31:4 # 41
2.8475 # 4.2.2026 # 16:31:4 # 42
2.8363 # 4.2.2026 # 16:31:4 # 43
2.8200 # 4.2.2026 # 16:31:4 # 44
2.8116 # 4.2.2026 # 16:31:4 # 45
2.8098 # 4.2.2026 # 16:31:4 # 46
2.7999 # 4.2.2026 # 16:31:4 # 47
2.7891 # 4.2.2026 # 16:31:5 # 48
2.7925 # 4.2.2026 # 16:31:5 # 49
2.8241 # 4.2.2026 # 16:31:5 # 50
####  Daten wurden Übertragen  ####
2.9545 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 412 # 51
2.9758 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 420 # 52
2.9890 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 428 # 53
2.9929 Volt -> Datum: 04.03.26 Zeit: 16:31:05 ADR = 436 # 54
3.0029 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 444 # 55
3.0243 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 452 # 56
3.0569 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 460 # 57
3.1160 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 468 # 58
3.1499 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 476 # 59
3.1876 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 484 # 60
3.2441 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 492 # 61
3.2753 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 500 # 62
3.3040 Volt -> Datum: 04.03.26 Zeit: 16:31:06 ADR = 508 # 63
###### Messtiefe Automatisch auf -> 10 <- verringert #########
3.3046 Volt -> Datum: 04.03.26 Zeit: 16:31:34 ADR = 516 # 64
3.2985 Volt -> Datum: 04.03.26 Zeit: 16:31:38 ADR = 524 # 65
3.1963 Volt -> Datum: 04.03.26 Zeit: 16:31:38 ADR = 532 # 66
3.0984 Volt -> Datum: 04.03.26 Zeit: 16:31:38 ADR = 540 # 67
2.9984 Volt -> Datum: 04.03.26 Zeit: 16:31:39 ADR = 548 # 68
2.8985 Volt -> Datum: 04.03.26 Zeit: 16:31:39 ADR = 556 # 69
2.7996 Volt -> Datum: 04.03.26 Zeit: 16:31:40 ADR = 564 # 70
2.6986 Volt -> Datum: 04.03.26 Zeit: 16:31:41 ADR = 572 # 71

Ich muss mal wieder darauf hinweisen, dass ich kein SuuuupaDuuuupa Programm nach kriterien eines Suuuuper Programmierers mache, kann ich nicht, will ich nicht !! Sondern ich mache mir ein Programm, das def. das macht was ich will !! Wer also hier die Glanzleistungen eines suuuuper C++ Programmieres sucht, ist hier falsch. Wer ein für Anfänger verständliches, leicht bekömmliches Programm sucht, das macht was er will und das er auch rel. leicht verstehen kann, warum es das macht, was es macht, ist hier richtig !!

Franz
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 ist nochmal eine Serial.print() Ausgabe. Die zeigt, wie die Reaktionsschwelle erst hochgezogen wurde, weil viele starke Änderungen der überwachten Spannung waren. Und dann wieder eine Std. keine Änderung mehr, da wurde die Schwelle wieder runtergesetz. Das finde ich ganz praktisch. Natürlich muss ich diese Automatischen Anpassungen der Reraktionsschwelle protokollieren, dass man sieht, wann die Rekationsschwelle verändert wurde. Aber das nächste ist jetzt erst mal, die letzte Änderung des Datenzeigers immer sofort ins FRAM zu schreiben, das das Gerät nach einem Ausfall seine Arbeit wieder bei der letzten Speicherung weiterführen kann. Wenn es nach einem Stromausfall wieder neu startet holt es den Datenzeiger dess letzen Eintrages und kann da dann weiter machen. Auch wenn das wohl nicht passieren wird. weil ich dem Geräte einen dicken Akku spendiere.

Code: Alles auswählen

ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4980
load:0x40078000,len:16612
load:0x40080400,len:3500
entry 0x400805b4
Analog-Test ESP32
NTP Server Abfrage
E (605) phy_comm: gpio[0] number: 2 is reserved

I2C FRAM gefunden
FRAM wird gelöscht -> FRAM IST gelöscht
3.3046 Volt -> Datum: 04.03-1.26 Zeit: 20:00:56 ADR = 12 # 1
3.2920 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 20 # 2
3.2469 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 28 # 3
3.1864 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 36 # 4
3.1301 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 44 # 5
3.0756 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 52 # 6
3.0348 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 60 # 7
2.9904 Volt -> Datum: 04.03-1.26 Zeit: 20:02:33 ADR = 68 # 8
2.9446 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 76 # 9
2.9015 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 84 # 10
2.8686 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 92 # 11
2.8266 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 100 # 12
2.7608 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 108 # 13
2.7071 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 116 # 14
2.6201 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 124 # 15
2.5500 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 132 # 16
2.4945 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 140 # 17
2.4435 Volt -> Datum: 04.03-1.26 Zeit: 20:02:34 ADR = 148 # 18
2.4141 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 156 # 19
2.3661 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 164 # 20
2.3594 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 172 # 21
2.4483 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 180 # 22
2.5808 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 188 # 23
2.7655 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 196 # 24
2.9425 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 204 # 25
3.1046 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 212 # 26
3.2748 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 220 # 27
3.3040 Volt -> Datum: 04.03-1.26 Zeit: 20:02:35 ADR = 228 # 28
3.2959 Volt -> Datum: 04.03-1.26 Zeit: 20:02:36 ADR = 236 # 29
3.0469 Volt -> Datum: 04.03-1.26 Zeit: 20:02:36 ADR = 244 # 30
2.9114 Volt -> Datum: 04.03-1.26 Zeit: 20:02:36 ADR = 252 # 31
2.8103 Volt -> Datum: 04.03-1.26 Zeit: 20:02:36 ADR = 260 # 32
2.7216 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 268 # 33
2.6435 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 276 # 34
2.5774 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 284 # 35
2.5930 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 292 # 36
2.8509 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 300 # 37
3.0869 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 308 # 38
3.2739 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 316 # 39
3.3041 Volt -> Datum: 04.03-1.26 Zeit: 20:02:37 ADR = 324 # 40
3.2688 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 332 # 41
2.9933 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 340 # 42
2.8098 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 348 # 43
2.7291 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 356 # 44
2.5420 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 364 # 45
2.4470 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 372 # 46
2.4334 Volt -> Datum: 04.03-1.26 Zeit: 20:02:38 ADR = 380 # 47
2.4418 Volt -> Datum: 04.03-1.26 Zeit: 20:02:39 ADR = 388 # 48
2.5816 Volt -> Datum: 04.03-1.26 Zeit: 20:02:39 ADR = 396 # 49
2.7805 Volt -> Datum: 04.03-1.26 Zeit: 20:02:39 ADR = 404 # 50
####  Daten zum PC Übertragen  ####
3.3046 # 4.2.2026 # 20:0:56 # 1
3.2920 # 4.2.2026 # 20:2:33 # 2
3.2469 # 4.2.2026 # 20:2:33 # 3
3.1864 # 4.2.2026 # 20:2:33 # 4
3.1301 # 4.2.2026 # 20:2:33 # 5
3.0756 # 4.2.2026 # 20:2:33 # 6
3.0348 # 4.2.2026 # 20:2:33 # 7
2.9904 # 4.2.2026 # 20:2:33 # 8
2.9446 # 4.2.2026 # 20:2:34 # 9
2.9015 # 4.2.2026 # 20:2:34 # 10
2.8686 # 4.2.2026 # 20:2:34 # 11
2.8266 # 4.2.2026 # 20:2:34 # 12
2.7608 # 4.2.2026 # 20:2:34 # 13
2.7071 # 4.2.2026 # 20:2:34 # 14
2.6201 # 4.2.2026 # 20:2:34 # 15
2.5500 # 4.2.2026 # 20:2:34 # 16
2.4945 # 4.2.2026 # 20:2:34 # 17
2.4435 # 4.2.2026 # 20:2:34 # 18
2.4141 # 4.2.2026 # 20:2:35 # 19
2.3661 # 4.2.2026 # 20:2:35 # 20
2.3594 # 4.2.2026 # 20:2:35 # 21
2.4483 # 4.2.2026 # 20:2:35 # 22
2.5808 # 4.2.2026 # 20:2:35 # 23
2.7655 # 4.2.2026 # 20:2:35 # 24
2.9425 # 4.2.2026 # 20:2:35 # 25
3.1046 # 4.2.2026 # 20:2:35 # 26
3.2748 # 4.2.2026 # 20:2:35 # 27
3.3040 # 4.2.2026 # 20:2:35 # 28
3.2959 # 4.2.2026 # 20:2:36 # 29
3.0469 # 4.2.2026 # 20:2:36 # 30
2.9114 # 4.2.2026 # 20:2:36 # 31
2.8103 # 4.2.2026 # 20:2:36 # 32
2.7216 # 4.2.2026 # 20:2:37 # 33
2.6435 # 4.2.2026 # 20:2:37 # 34
2.5774 # 4.2.2026 # 20:2:37 # 35
2.5930 # 4.2.2026 # 20:2:37 # 36
2.8509 # 4.2.2026 # 20:2:37 # 37
3.0869 # 4.2.2026 # 20:2:37 # 38
3.2739 # 4.2.2026 # 20:2:37 # 39
3.3041 # 4.2.2026 # 20:2:37 # 40
3.2688 # 4.2.2026 # 20:2:38 # 41
2.9933 # 4.2.2026 # 20:2:38 # 42
2.8098 # 4.2.2026 # 20:2:38 # 43
2.7291 # 4.2.2026 # 20:2:38 # 44
2.5420 # 4.2.2026 # 20:2:38 # 45
2.4470 # 4.2.2026 # 20:2:38 # 46
2.4334 # 4.2.2026 # 20:2:38 # 47
2.4418 # 4.2.2026 # 20:2:39 # 48
2.5816 # 4.2.2026 # 20:2:39 # 49
2.7805 # 4.2.2026 # 20:2:39 # 50
50 Datensätze wurden Übertragen
3.3036 Volt -> Datum: 04.03-1.26 Zeit: 20:02:39 ADR = 412 # 51
###### Messtiefe Automatisch auf -> 10 <- verringert #########
3.3043 Volt -> Datum: 04.03-1.26 Zeit: 20:02:41 ADR = 420 # 52
####### Messtiefe Automatisch auf -> 100 <- erhöht ########
3.3048 Volt -> Datum: 04.03-1.26 Zeit: 21:00:41 ADR = 428 # 53
Benutzeravatar
Admin
Administrator
Beiträge: 1294
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 »

Der Speicherzeiger ist eingebaut. Auf der Adresse 32100 ist er abgelegt. Ist er gelöscht, wird der Startwert "4" eingesetzt.

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. 
    Programm im Moment vom 04.02.2026 / ADC_ADS1115_ESP32_Mini_OLE_FRAM_2x4Byte_V20
*/
#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 Spannung2neu = 0;
int Spannung2alt = 0;
float f = 0;
uint8_t buffer[4];  // floats are 4 bytes!
uint32_t Zeitbuffer = 0;
int Speicher = 4;
int Speicher2 = 0;
int Zaehler = 0;
int UebertragZeiger = 4;
byte DzPja = 0;
int Ausgabezaehler = 0;
int Kontrollzaehler = 0;
byte LSpin = 27;
byte Messtiefe = 100;
byte Reagieren = 0;
//------------------------- Minuten Tackt zur 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 1 Min ----------------------------------
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-Test ESP32");
  //-----------------------------------------------------------
  Serial.println(F("NTP Server Abfrage"));
  NTP_Zeit();

  // ------------------EPROM 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);
  //----------------------- Oled Display ---------------------
  oled.begin();
  oled.clearBuffer();  // Textspeicher löschen
  //------- Erste Displayausgabe gleich nach dem Start -------
  Sekundenablauf01 = 60000;
  i2ceeprom.read(32100, buffer, 4);
  memcpy((void *)&Speicher, buffer, 4);
  if (Speicher < 4) {
    Speicher = 4;
  }
  Serial.print("Speicherzeiger = ");
  Serial.println(Speicher);
}
//############################################################################################
// ----------------------------------------------------LOOP-----------------------------------
//############################################################################################
void loop() {
  Messungstart = millis();
  Zeitablauf = millis();

  if (Zeitablauf - Sekundenablauf01 >= Pausezeit01) {  // Eine Minute abgelaufen?
    Displayausgabe();
    Sekundenablauf01 = millis();
  }
  Kontrollen();
  Messen();
  if (Reagieren == 1) {
    SpeicherdatenSchreiben();
    Spannung2alt = Spannung2neu;
    SpeicherdatenLesen();
    testprint();
    Reagieren = 0;
  }
  /*
  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);
}
//############################################################################################
//---------------------------------- 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");
  // Hier das Problem. Die Zeitausgabe
  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.println(F("ADR "));
  oled.print(Speicher);
  //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.
  // -----------------------------------------------------------------------------------------
  Spannung2neu = ads_mv0 * Messtiefe;
  if (Spannung2alt == Spannung2neu) {
  } else {
    // Messung auf das Display ausgeben
    oled.setFont(u8g2_font_10x20_mf);
    //ADS Kanal 0 anzeigen
    oled.setCursor(20, (2 * 20));
    oled.println(F("ADR "));
    oled.print(Speicher + 4);
    //ADS Kanal 1 anzeigen
    oled.setCursor(20, (3 * 20));
    oled.print(ads_mv0);
    oled.print(F(" Volt "));
    oled.sendBuffer();
    Reagieren = 1;
    tone(LSpin, 1000, 100);  // Piep wenn sich die Spannung ändert.
  }
}
// ------------------------------- Messen Ende ---------------------------------------------

//##########################################################################################
//------------------------------ FRAM Schreiben --------------------------------------------
//##########################################################################################
void SpeicherdatenSchreiben() {
  Speicher = Speicher + 4;
  Zaehler = Zaehler + 1;
  Kontrollzaehler = Kontrollzaehler + 1;
  // Messwert Schreiben--------------------------------------------------------------------
  f = ads_mv0;
  memcpy(buffer, (void *)&f, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Zeit & Datum Schreiben----------------------------------------------------------------
  time_t now;
  time(&now);
  Speicher = Speicher + 4;
  memcpy(buffer, (void *)&now, 4);
  i2ceeprom.write(Speicher, buffer, 4);
  // Speicherzeiger im FRAM auf 32100 sichern
  memcpy(buffer, (void *)&Speicher, 4);
  i2ceeprom.write(32100, buffer, 4);
  // Display aktualisieren-----------------------------------------------------------------
  oled.setCursor(20, (2 * 20));
  oled.println(F("ADR "));
  oled.print(Speicher);
  //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 ---------------------------------------------
//
//###########################################################################################
//-------------------------- FRAM zum PC Übertragen -----------------------------------------
//###########################################################################################
void DatenzumPC() {
  // Messwert auslesen-----------------------------------------------------------------------
  Serial.println(F("####  Daten zum PC Übertragen  ####"));
  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.print(Ausgabezaehler);
  Serial.println(F(" Datensätze wurden Übertragen"));
}
//------------------------------ 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.print("FRAM wird gelöscht -> ");
  for (int i = 0; i <= 32000; i = i + 4) {
    f = 0;
    memcpy(buffer, (void *)&f, 4);
    i2ceeprom.write(Speicher, buffer, 4);
  }
  Serial.println("FRAM IST gelöscht");
}

//##########################################################################################
//-------------------------- Wichtige Kontrollen -------------------------------------------
//##########################################################################################
void Kontrollen() {
  // Prüfen ob die Schwelle zu niedrig ist
  if (Zeitablauf - Sekundenablauf02 >= Pausezeit02) {  // FRAM Aufzeichungen pro Minute messen
    if ((Kontrollzaehler >= 10) && (Messtiefe > 1)) {
      Messtiefe = Messtiefe / 10;
      Serial.print(F("###### Messtiefe Automatisch auf -> "));
      Serial.print(Messtiefe);
      Serial.println(F(" <- verringert #########"));
      Kontrollzaehler = 0;
    }
    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) && (Messtiefe < 100)) {
      Messtiefe = Messtiefe * 10;
      Serial.print(F("######### Messtiefe Automatisch auf -> "));
      Serial.print(Messtiefe);
      Serial.println(F(" <- erhöht #########"));
      Kontrollzaehler = 0;
    }
    Sekundenablauf03 = millis();
    Kontrollzaehler = 0;
  }
  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 -------------------------------------------
Antworten

Zurück zu „Hardware / Schaltungstechnik“

Wer ist online?

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