Verständnisfrage EEPROOM --> LIB

Calibriersketch zu pH Meter

#include <AnalogPHMeter.h>                     // Pos 1
#include <EEPROM.h>                            // Pos 2
AnalogPHMeter pHSensor(A10);                   // Pos 3
unsigned int pHCalibrationValueAddress = 0;    // Pos 4
void setup(void) {
  Serial.begin(9600);
  struct PHCalibrationValue pHCalibrationValue;               // Pos 5
  EEPROM.get(pHCalibrationValueAddress, pHCalibrationValue);  // Pos 6
  pHSensor.initialize(pHCalibrationValue);                    // Pos 7
  Serial.println("Analog PH Meter Calibration");
  Serial.println("The value will be saved on EEPROM");
  Serial.println("Procedure:");
  Serial.println(" - Put pH on pH 7 solution");
  Serial.println(" - Wait until stable");
  Serial.println(" - Press 'm' to calibrate");
  Serial.println(" - Same process for pH 4 and/or pH 10,");
  Serial.println("   except press 'l' for pH 4, and 'h' for pH 10");
  Serial.println();
  Serial.println("All calibration value will be reset after restart.");
  Serial.println("In this example, press 's' to save the value to EEPROM");
  Serial.println("You can freely change the storage.");
  Serial.println("It is not limited to EEPROM only");
  Serial.println();
  Serial.println("*to clear calibration value press 'c'");
  delay(3000);
}
void loop(void) {
  static unsigned long t = millis();
  if (millis() - t > 1000) {
    Serial.println(pHSensor.singleReading().getpH());   // Pos 8
    t = millis();
  }
  if (Serial.available()) {
    char c = Serial.read();                             // Pos 9
    if (c == 'm') {                 
      pHSensor.calibrationMid(6.860f);
    } else if (c == 'l') {                              // Pos 10
      pHSensor.calibrationLow(4.000f);
    } else if (c == 'h') {                              // Pos 11
      pHSensor.calibrationHigh(10.000f);
    } else if (c == 'c') {                              // Pos 12
      pHSensor.calibrationClear();
    } else if (c == 's') {
      EEPROM.put(pHCalibrationValueAddress, pHSensor.getCalibrationValue());    // Pos 13
    }
  }
}

Dazugehörig AnalogPHMeter.h

#ifndef __ANALOG_PH_METER_H__
#define __ANALOG_PH_METER_H__

struct PHCalibrationValue {                       // Pos 14
  char point;
  float value[2];
  int adc[2];
  float slope;
  int adcOffset;
};

class AnalogPHMeter {                             // Pos 15
 private:
  struct PHCalibrationValue calibrationValue;

  unsigned int pin;
  float pH;                                             // Pos 16
  float temperature;
  bool debug;

  bool stable;
  unsigned char stableCount;
  float precision;
  unsigned char index;
  float valueBefore, deltaValue, sumOfDeltaValue;
  float deltaValueBuffer[10];

  float defaultSlope;
  int defaultAdcAt7;

  int readADC(int oversampling = 64);
  void inputValue(float value);

 public:
  AnalogPHMeter(unsigned int pin, float defaultSlope = 0.01f, int defaultAdcAt7 = 410);   // Pos 17

  AnalogPHMeter &initialize(struct PHCalibrationValue = (struct PHCalibrationValue){});   // Pos 18

  AnalogPHMeter &singleReading(void);                                         // Pos 19
  AnalogPHMeter &temperatureCompensation(float temperature);
  AnalogPHMeter &calibration(void);                                             // Pos 20
  AnalogPHMeter &calibrationClear(void);                                      // Pos 21
  AnalogPHMeter &calibrationMid(float mid);                                  // Pos 22
  AnalogPHMeter &calibrationLow(float low);                                 // Pos 23
  AnalogPHMeter &calibrationHigh(float high);                               // Pos 24
  AnalogPHMeter &factoryReset(void);

  float getpH(void) { return this->pH; };                                     
  float getTemperature(void) { return this->temperature; };
  float getCalibrationPoint(void) { return this->calibrationValue.point; };
  struct PHCalibrationValue getCalibrationValue(void) {                  // Pos 25
    return calibrationValue;
  };
  unsigned char getpHStableCount(void) { return this->stableCount; };
  float getSumOfDeltaValue(void) { return this->sumOfDeltaValue; };
  float getDeltaValue(void) { return this->deltaValue; };
  float getPrecision(void) { return this->precision; };
  float getDefaultSlope(void) { return this->defaultSlope; };
  float getDefaultAdcAt7(void) { return this->defaultAdcAt7; };

  bool ispHStable(void) { return this->stable; };
  AnalogPHMeter & setpHPrecision(float precision) { this->precision = precision; return *this; };
  AnalogPHMeter & setDefaultSlope(float slope) { this->defaultSlope = slope; return *this; };
  AnalogPHMeter & setDefaultAdcAt7(int adc) { this->defaultAdcAt7 = defaultAdcAt7; return *this; };
};

#endif

Pos 1 + Pos 2 sind die LIBs, die eingebunden werden
Pos 3 setzt sich aus Pos 14, einer frei wählbaren Bezeichnung und dem Eingang zusammen
Pos 4 frei wählbare Bezeichnung und Startadresse EEPROM
Pos 5 struct erstellen aus structname und Datenelement (beides frei wählbar)
Pos 6 einlesen aus EEPROM aus Startadresse Pos 4 + Datenelement Pos 5
Pos 7 Bezeichnung (vorzugsweise aus Pos 3) . Pos 18 + Datenelement Pos 5
Pos 8 Bezeichnung (vorzugsweise aus Pos 3) + Pos 19 + Pos 20
Pos 9 / 10 / 11 /12 Kalibrierung Pos 21 / 22 / 23 / 24
Pos 13 schreiben auf Startadresse Pos 4, Bezeichnung (vorzugsweise aus Pos 3) . Pos 25

In AnalogPHMeter.h sind einige Dinge unter private und daher nicht einsehbar.

Ich habe das EEPROM ausgelesen. Insgesamt sind etwa 20 bytes beschrieben worden.
Gibt es eine Möglichkeit herauszubekommen, wie sich pHSensor.getCalibrationValue() zusammensetzt ??

Ja, ok und wie war jetzt gleich deine Frage ?

Wenn das die Frage war, dann ist die Antwort: 42

Noch nicht fertig... Geduld

Bin auf die falsche Taste gekommen

Kleiner Tip: Texte hier im Forum (ich mach das sogar generell in ALLEN Foren) immer offline schreiben: Notepad o.ä. und anschließen hier einfügen (Codetags kann man auch mit der Hand hinzufügen).
Das Forum bringt gerne mal nen Fehler beim Absenden, dann ist alles weg...

Moko:
Kleiner Tip: Texte hier im Forum (ich mach das sogar generell in ALLEN Foren) immer offline schreiben: Notepad o.ä. und anschließen hier einfügen (Codetags kann man auch mit der Hand hinzufügen).
Das Forum bringt gerne mal nen Fehler beim Absenden, dann ist alles weg...

Danke für den Hinweis...
So fertig.

Wirf einen Blick in die Headerdatei.

Gruß Tommy

Hallo,

was willst Du denn jetzt wissen ? Wie die methode getCalibrationValue aussieht oder wie die Structur der Daten aussieht. Und wozu willst Du das wissen.

Heinz

Gibt es eine Möglichkeit herauszubekommen, wie sich pHSensor.getCalibrationValue() zusammensetzt ??

Was meinst du damit genau?
die Methode getCalibrationValue() gibt ein struct vom Typ PHCalibrationValue zurück.
und das ist so aufgebaut:

struct PHCalibrationValue {                       // Pos 14
  char point;
  float value[2];
  int adc[2];
  float slope;
  int adcOffset;
};

Die Frage ist damit beantwortet, aber ich beführchte das ist nicht das was du wirklich wissen willst.

Die Startadresse ist bei 100 und nicht bei 0.

So sieht das beschriebene EEPROM aus.

Ich habe gehofft, das ich irgendwie nachvollziehen kann, was in welchem byte steht.

Hintergrund des Ganzen ist der, das beim Messen des pH-Wertes und auch anderer Sensoren oft eine Spannung gemessen und dann damit gerechnet wird.
Das Kalibrieren in diesem sketch wird über den ser. Monitor gemacht.
Da sich bei mir die Werte ändern, wenn ich den Arduino mit der USB verbinde (leichte Spannungsunterschiede), habe ich mir die Buttons auf den TFT gelegt und möchte es von dort aus machen, also ohne PC. Funktioniert ja auch soweit.

In der Kalibrieranleitung steht z.B. das zuerst die pH 7 Flüssigkeit genommen werden soll. Dann die pH4 und oder ph10.

Wie sind die Zusammenhänge? Welche Werte stelle ich der LIB zur Verfügung, was speichere ich im EEPROM.

Möchte es halt verstehen, warum es funktioniert.

also in deinem Sketch steht

unsigned int pHCalibrationValueAddress = 0;

und der Wert wird auch nicht verändert, daher sollte er ab 0 schreiben.

Das struct würde sich so zusammensetzen:

struct PHCalibrationValue { // Pos 14
char point; // 1
float value[2]; // 4 + 4
int adc[2]; // 2 + 2
float slope; // 4
int adcOffset; // 2
};

belegt also 19 Byte.
Gib dir die Werte mal über die Serielle Aus, dann wirst meines Erachtens auch zusammen finden

Serial.println(pHCalibrationValue.point);
Serial.println(pHCalibrationValue.value[0]);
Serial.println(pHCalibrationValue.value[1]);
Serial.println(pHCalibrationValue.adc[0]);
Serial.println(pHCalibrationValue.adc[1]);
Serial.println(pHCalibrationValue.slope);
Serial.println(pHCalibrationValue.adcOffset);

kannst auch auch wieder mit HEX oder BIN machen, dann müsstest du die Aufteilung der Variablen in ihre Bytes sehen.

noiasca:
also in deinem Sketch steht

unsigned int pHCalibrationValueAddress = 0;

und der Wert wird auch nicht verändert, daher sollte er ab 0 schreiben.

Bei der Kalibrikation hatte ich die Startadresse geändert. In meinem Sketch frage ich das EEPROM auch ab 100 ab. Passt schon.
Das andere probiere ich mal aus.
Danke

Ich habe gehofft, das ich irgendwie nachvollziehen kann, was in welchem byte steht.

Die Adressen der einzelnen Daten im EEPROM findest du mit offsetof() heraus.

babba110:
Hintergrund des Ganzen ist der, das beim Messen des pH-Wertes und auch anderer Sensoren oft eine Spannung gemessen und dann damit gerechnet wird.
...
Da sich bei mir die Werte ändern, wenn ich den Arduino mit der USB verbinde (leichte Spannungsunterschiede),

Wenn man absolute Spannungswerte messen will, sollte man als Referenz nie die Vcc-Spannung nehmen, sondern die interne Referenzspannung des AD-Wandler. Die ist dann allerdings nur ca. 1V, was auch bei der externen Beschaltung berücksichtigt werden muss. Dann sind die Messergebnisse aber unabhängig von der Versorgungsspannung des Arduino.

sorry, Doppelpost

MicroBahner:
Wenn man absolute Spannungswerte messen will, sollte man als Referenz nie die Vcc-Spannung nehmen, sondern die interne Referenzspannung des AD-Wandler. Die ist dann allerdings nur ca. 1V, was auch bei der externen Beschaltung berücksichtigt werden muss. Dann sind die Messergebnisse aber unabhängig von der Versorgungsspannung des Arduino.

Eine Ergänzung, weil aus diesem Thread nicht hervorgeht welches Board zum Einsatz kommt.
Die interne Referenzspannung hängt vom verwendeten Prozessor ab.
Zum Beispiel:
UNO, Nano (ATmega328P): 1,1V
Leonardo/Micro (ATmega32U4): 2,56V
MEGA (ATmega2560): 1,1V oder 2,56V

Details siehe: analogReference() - Arduino Reference

Erstmal vielen Dank für die Ratschläge und Tips. Ich habe die Zusammenhänge langsam verstanden.

Kalibriersketch
.
#include <AnalogPHMeter.h>
.
.
  //pH-Messung Sensor
  struct PHCalibrationValue pHCalibrationValue;
  EEPROM.get(pH_Wert_Kalibrierung_Adresse, pHCalibrationValue);
  pHSensor.initialize(pHCalibrationValue);

Im Kalibriersketch greife ich direkt auf einen struct zu, der sich in AnalogPHMeter.h verbirgt.

AnalogPHMeter.h
.
struct PHCalibrationValue {
  char point;
  float value[2];
  int adc[2];
  float slope;
  int adcOffset;
};

und der belegt 19 byte im EEPROM
1x char ----- > 1 byte
3x float -----> 12 byte
3x int --------> 6 byte

        Serial.print(offsetof(struct PHCalibrationValue, point));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.point);

        Serial.print(offsetof(struct PHCalibrationValue, value[0]));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.value[0]);

        Serial.print(offsetof(struct PHCalibrationValue, value[1]));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.value[1]);

        Serial.print(offsetof(struct PHCalibrationValue, adc[0]));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.adc[0]);

        Serial.print(offsetof(struct PHCalibrationValue, adc[1]));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.adc[1]);

        Serial.print(offsetof(struct PHCalibrationValue, slope));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.slope);

        Serial.print(offsetof(struct PHCalibrationValue, adcOffset));
        Serial.print("\t");
        Serial.println(pHCalibrationValue.adcOffset);

Das ganze habe ich nun auch mal mit offsetof () ausgelesen und das sieht dann so aus. Unten drunter sind nochmal die einzelnen Adressen mit Inhalt. Startadresse 750

Soweit schonmal 1000 Dank.

Habe aber an einer anderen Stelle nochmal ein Problem.
Ich habe in einem struct mehrere float zusammengefasst und schreibe sie auf das EEPROM

// Temperatur Einstellung --> EEPROM
struct {
  float Soll_Temp_Becken;
  float Soll_Temp_Schwellwert;
  float Soll_Temp_warm;
  float Soll_Temp_kalt;
} TEMPERATUR;

// andere Stelle im Sketch
    if (m_press_4 == main_but95) {
      if (main_but95 = HIGH)
        EEPROM.put(Temperatur_Adresse, TEMPERATUR);
    }

Diese 4 Werte sind “veränderbare Grundeinstellungen” für eine Temperaturregelung.

Gibt es eine einfache Möglichkeit den Inhalt des struct mit dem geschriebenen auf dem EEPROM zu vergleichen??
Also sowas in der Richtung…

if (struct TEMPERATUR |= EEPROM.get(Temperatur_Adresse, TEMPERATUR) dann mache was;

Das der Vorschlag BullShit ist, das ist mir auch klar. Aber wie würde es funktionieren???

Vielen DANK für eure Hilfe !!!

Das ist kein Bullshit, sowas kann man natürlich machen.

Dazu solltest Du Deine Struktur benennen und davon eine zweite Variable (eigentlich Instanz) anlegen:

struct TemperatureData {
  float Soll_Temp_Becken;
  float Soll_Temp_Schwellwert;
  float Soll_Temp_warm;
  float Soll_Temp_kalt;
};

TemperatureData TEMPERATUR;         // für das spätere (evtl.) Schreiben mit put
TemperatureData savedTemperatur;   // für die aktuell im EEPROM stehenden Werte

In diese zweite Variable liest Du mit EEPROM.get() dann das gespeicherte ein und kannst dann vergleichen - z.B. den Wert für "warm":

if (TEMPERATUR.Soll_Temp_warm != savedTemperatur.Soll_Temp_warm) {
  // da hat sich was geändert
}

Variablen nur mit Großbuchstaben zu benennen oder Namen von Strukturelementen mit Großbuchstaben zu beginnen ist übrigens - hmmm - recht wenig verbreitet.

TemperatureData TEMPERATUR;         // für das spätere (evtl.) Schreiben mit put
TemperatureData savedTemperatur;   // für die aktuell im EEPROM stehenden Werte

warum benötigtst du zwei separate Variablen? einfach einmal als Variable im Speicher halten und wenn du ins EEPROM schreiben willst mit put schreiben, wenn du lesen willst, mit get lesen.

Weil er die aktuellen Werte (offensichtlich TEMPERATUR) mit denen im EEPROM vergleichen will.

Gibt es eine einfache Möglichkeit den Inhalt des struct mit dem geschriebenen auf dem EEPROM zu vergleichen??