EEPROM Wert aufteilen...

Moin,

Ich bins mal wieder.

Ich hab wieder ein Problem, dessen Lösung ich einfach nicht finde.

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>

int X1Speichern = 8; 

int y = analogRead(A0);
int x = analogRead(y);
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int X1Speichern, int x)
  {
  byte lowByte = ((x >> 0) & 0xFF);
  byte highByte = ((x >> 8) & 0xFF);

  EEPROM.write(X1Speichern, lowByte);
  EEPROM.write(X1Speichern + 1, highByte);
  }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int X1Speichern)
  {
  byte lowByte = EEPROM.read(X1Speichern);
  byte highByte = EEPROM.read(X1Speichern + 1);

  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
  }

void setup()
  {
    int sensor = analogRead(y);
    lcd.begin(20, 4); 
  Serial.begin(9600);

  EEPROMWriteInt(0, 0xABCD);

  Serial.print("Read the following int at the eeprom address 0: ");
  Serial.println(EEPROMReadInt(0), HEX);
  }

void loop()
  {int sensor = analogRead(y);
    lcd.setCursor(0,0);
    lcd.print(" ");
   lcd.print(x);
    lcd.setCursor(0,1);
    lcd.print(sensor);
  }

Ich versuche meinen AnalogRead als "ganzen" Wert zu speichern. Natürlich muss dieser geteilt werden.

Als Wert erwarte ich ca 350.

Wenn ich "X" durch die Zahl 350 ersetze, klappt alles.
Aber ich kriege es nicht hin ein analogRead einzubauen....
Ich versteh einfach nicht was ich falsch mache...

Hinterher muss ich auch noch hinbekommen, dass ich lediglich auf "IF" Anweisung das ganze ausführe...

Danke schonmal im vorraus.

Gruß
Kahzia

Mit EEPROM.get/.put kannst du doch den ganzen uint_16 oder long direkt speichern.
Oder habe ich da was falsch verstanden?

Kahzia:
... ein Problem, dessen Lösung ich einfach nicht finde. ...

Mein Top-Tipp zur Lösungsfindung: Formatiere Deinen Code so, dass man sich schnell darin zurecht findet. Wenn Du die Struktur(en) Deines Codes schnell erfassbar machst, findest Du die Lösung evtl. sogar ohne die Hilfe anderer.

Gruß

Gregor

Mh,

Naja der Code besteht ja aus nichts weiterem als X und X1Speicher..
Das war die Anleitung aus dem Forum hier...
Ich finde ihn übersichtlich wenn man diesen in das Arduino Programm kopiert.

Ich komme mit put und get leider auch nicht wirklich weiter.
Da fehlt mir komplett die Übersicht was da überhaupt geschieht.
Der vorgefertigte Code von Arduino hilft mir da leider auch nicht.

Ich würde nach wie vor den Wert einfach aufteilen in low und high byte.
Das funktioniert ja auch mit Statischen Werten. Ich bräuchte nur Hilfe wie ich da ein analogRead integriere.

wert = analogRead

EEPROM.put(eeprom-adresse, wert)

2 Byte werden gespeichert.

EEPROM.get(eeprom-adresse, wert)

Serial.print(wert, DEC);

Was passiert da?

if(Button ==  HIGH){ 

double x1 = PhMittelwert;   
EEPROM.put(X1Speichern, x1);  
}



if(Kali7 == HIGH){
   double x2 = round (PhMittelwert/4.0);
   EEPROM.write(X2Speichern, x2);  
     


if(Steigung == true){
  
  float X2 = EEPROM.read(X2Ausgabe);
  X1 = EEPROM.get(X1Speichern, x1);

Hmmm wenn ich X1Speichern durch Ausgabe ersetze, komme ich aufs gleicher Ergebniss.
Ich erhalte immer den Wert 128
Obwohl dieser 367 sein müsste.
Mit dem EEPROM.read auf der anderen Variable klappt das.

Was übersehe ich

Es ist natürlich ziemlich schwierig aus den Code-Fragmenten etwas zu erkennen.
Bitte poste immer den kompletten Code in dem der Fehler auftritt. In den meisten Fällen liegt der Fehler nämlich in jenem Teil des Codes, der nicht gepostet wurde!

Ich rate also mal einfach vor mich hin... :slight_smile:

Wie wäre es, wenn du zum Beispiel statt

if (Button ==  HIGH) { 
...

folgendes verwendest:

if (digitalRead(Button) ==  HIGH) { 
...

Vielleicht ist das mal ein Anfang.

Und noch einmal die Bitte:
Poste Code der kompiliert, sonst ist es sehr schwierig Fehler zu finden.

Vielleicht liegt es ja daran, das du in den EEPROM-Funktionen als Variablen-Typ int angibts.
Probier es doch mal mit unsigned int, da wird das MSb auf jedenfall nicht verändert.

Ansonsten kannst du es gerne mit folgendem Code-Schnipsel aus einem AVR-PDF probieren:

unsigned int EEPROMReadWord(unsigned int uiAddress){
  return (EEPROMRead(uiAddress++)<<8)|EEPROMRead(uiAddress);
}

unsigned char EEPROMRead(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // Wait for completion of previous write
  EEAR = uiAddress;         // Set up address register
  EECR |= (1<<EERE);        // Start eeprom read by writing EERE
  return EEDR;              // Return data from Data Register
}

unsigned int EEPROMWriteWord(unsigned int uiAddress, unsigned int ucData){
  uiAddress=EEPROMWrite (uiAddress,ucData>>8);
  uiAddress=EEPROMWrite (uiAddress,ucData&255);
  return uiAddress;
}

unsigned int EEPROMWrite(unsigned int uiAddress, unsigned char ucData){
//  yellowLEDPort^=yellowLED;
  while(EECR & (1<<EEPE));  // Wait for completion of previous write
  noInterrupts();
  EEAR = uiAddress++;         // Set up address and Data Registers
  EEDR = ucData;
  EECR |= (1<<EEMPE);       //   Write logical one to EEMPE
  EECR |= (1<<EEPE);        // Start eeprom write by setting EEPE
  interrupts();
//  yellowLEDPort^=yellowLED;
  return uiAddress;
}

Nicht wundern über die EEPROMWrite(Word)-Funktionen das diese die nächste Adresse zurück geben.
Wenn man z. B. Adresse=EEPROMWriteWord(Adresse,Wert) aufruft und dann wieder und wieder um einen größeren Block zu schreiben erspaart man sich das ständige Adresse++ oder Adresse+=2.
Ansonsten einfach mit EEPROMWriteWord(Adresse,Wert) aufrufen.
yellowLEDPort^=yellowLED toggelt beim schreiben eine LED auf dem AVR-Board, zur Kontrolle.
Wenn erwünscht vorher die richtigen Definitionen für den Port dieser setzen und dann aktivieren.
Ach ja, diese EEPROM-Routinen kommen ohne Librarie zurecht.
Die EEPROM....Word-Funktionen schreiben/lesen zuerst das MSB dann das LSB, wenn lieber anders herum, glaube Intel-Norm war das, dann einfach die Reihenfolge vertauschen.

MfG
Andi

Hallo,

ich bin erst ein paar Tage hier. Mir wurde gleich geholfen, so will ich auch Ihnen helfen.

Das EEPROM Problem hatte ich auch zahlen über 10'000.

Ich habe das so gelöst:

long Wert1 = 12312;

// EEPROM Schreiben

  EEPROM.write(1, Wert1 / 256);   // Wert durch 256 geteilt, 
      EEPROM.write(2,Wert1 % 256); // Rest von Wert kleiner als 256

Benötigt zwei Adressbereiche im EEPROM

// EEPROM lesen

Wert2 = EEPROM.read(1) * 256 + EEPROM.read(2); // Zerlegte Dezimal-Zahl wird aus EEPROM gelesen und zusammengefügt

Gruss Konrad

Bitte poste immer den kompletten Code in dem der Fehler auftritt.

Naja wie krieg ich hier 300 Zeilen hoch ?
Ich glaube das wird unübersichtlich
Wie Handhabe ich das am besten ?
Ich lad den Code jetzt einfach mal hoch.
Da könnt Ihr den über den Link downloaden :slight_smile:

http://workupload.com/file/JYYcEDD

Es geht ab 174 los. bis 205
Ziel ist eine Kalibrierung. Der Sensor wird mit der Sonde in eine Lösung gehalten und dann per Button der Wert gespeichert zur errechung der Steigung.

wert = analogRead

EEPROM.put(eeprom-adresse, wert)

2 Byte werden gespeichert.

EEPROM.get(eeprom-adresse, wert)

Serial.print(wert, DEC);

Was passiert da?

Mit deiner Variante steh ich kurz vor einer Lösung.

Da könnt Ihr den über den Link downloaden

Solche Links machen auf mich den Eindruck von gefundenen gebrauchten Kaugummis.
Die stecke ich mir nicht in den Mund.

Tipp:
Wir haben hier im Forum eine Code Formatierung. Das ist schon übersichtlich, dann.

Auch kann man Dateien anhängen. Das ist für die Nachwelt besser. Denn die Daten bleiben erhalten. Bei deiner Methode ist irgendwann der Thread wertlos, weil Datei weg.
Sowas unterstütze ich nicht.

Solche Links machen auf mich den Eindruck von gefundenen gebrauchten Kaugummis.
Die stecke ich mir nicht in den Mund.

Deswegen fragte ich ja...

Den Code kann ich hier nicht komplett einfügen.
Da ich die maximalen Zeichen überschreite.

Oder es gibt noch eine andere Formatierung () die ich leider nicht kenne. Klärt mich gerne auf.

Ansonsten nochmal als Attachment angehängt

X1 Speichern macht die Probleme. Zeile 166.

Danach geht er zwar in die andere IF Bedingung die arbeitet er auch sauber ab, da ich dort zum Vergleich noch mit "write" gearbeitet habe.

ab 199 wird beides ausgegeben und die Steigung berechnet.

Ausgabe ist bei X1 128 und X2 359(richtig).
Ich erwarte den gleichen Wert wie bei X2 da ich die Sonde in der gleichen Flüssigkeit lasse.

PH_AUSGABE.ino (9.08 KB)

Ansonsten nochmal als Attachment angehängt

Danke!

double x1 = PhMittelwert;    // ÜBERGABE DES ANALOGEN WERTES AND x1      /4 DA DIE ZAHL ZU GROß IST FÜR DEN SPEICHER

EEPROM.put(X1Speichern, x1);          // SPEICHERN VON x1 IN EEPROM ÜBER X1SPEICHERN

x1 benötigt 4 Byte!

 int X1Speichern = 0;             // EEPROM SPEICHERORT PH4

int X2Speichern = 1;            // EEPROM SPEICHERORT PH7

Die Adresse von x2 ist so gelegt, dass 3 Byte von x1 überschrieben werden!

Daum mein Tipp:
Lege Strukturen an.
Nutze die EEMEM Möglichkeiten des Kompilers.
Dann werden solche Fehler unterbunden!

= 0;
= 1;
= 14;

Wie wählst du deine Adressen aus?
:grin: Würfeln? :grin:

Das ist nicht sonderlich Sinn voll!

Also:
Wenn du eine Variable im EEPROM anlegen willst, dann sage dem Kompiler das.

Beispiel:

double EEMEM maxTemperatur = 44.5;

So, jetzt kennt der Kompiler die exakte Adresse im EEPROM.
Und die Arduino IDE erzeugt eine *.eep Datei, welche du als Default nutzen kannst.

Schreiben und lesen würde dann so gehen:

double lokaleMaxTemperatur = 0.0; // Stellvertreter im RAM anlegen
EEPROM.get((int)&maxTemperatur,lokaleMaxTemperatur); // Wert einlesen
// tu was mit  lokaleMaxTemperatur
EEPROM.put((int)&maxTemperatur,lokaleMaxTemperatur); // Wert schreiben

ungetestet

Mhhh,
Ich hab mich an write gehalten, ich dachte man definiert die Addr. oben einfach.
z.B mit 0 oder 15

Oder lieg ich da falsch ?

Mit meiner Variante lief es jetzt eig.
Ich hab oben definiert 20 und 50 für x1 und x2

Ich habe deins natürlich auch probiert, aber da krieg ich als x1 wieder nur 128.
Also irgendwie fehlt da was.

Ich hab den Code nochmal hochgeladen, magst nochmal rüberschauen ?

PH_AUSGABE1.ino (9.02 KB)

Ich hab mich an write gehalten, ich dachte man definiert die Addr. oben einfach.
z.B mit 0 oder 15

Oder lieg ich da falsch ?

Was würde ein Postbote von dir halten, wenn du ihm sowas erzählst?

Adressen unterliegen einem Ordnungssystem.
Zumindest sollte man eins darauf anwenden, um erfolgreich zu sein.
Chaos und würfeln, sind da bedenkliche Strategien.

double EEMEM X1Speichern = 20; // EEPROM SPEICHERORT PH4

Ein Speicherort(EEPROM Adresse) ist vom Type int. und nicht Double
Auch macht es kleinen/selten Sinn einen Speicherort ins EEPROM zu legen...

Was würde ein Postbote von dir halten, wenn du ihm sowas erzählst?

Ich frage doch extra ....

Ein Speicherort(EEPROM Adresse) ist vom Type int. und nicht Double

Ich hab deine Vorlage verwendet.
Dann war die nicht verständlich für mich.

Auch wenn ich es mit INT mache kommt es auf das gleiche Ergebnis.

Ich würde es wirklich gerne verstehen, wie lege ich einen Speicherort richtig fest ?
Anscheind nicht mit:

int EEMEM Speicherort = 20;

und wie beschreibe und rufe ich diesen richtig ab.

EEPROM.put((int)&Speicherort, WERT);

float X1 = EEPROM.get((int)&Speicherort, WERT);

Könntest du mir es Anhand eines Beispieles erklären.

OK...

Dann nochmal, aber diesmal ganz langsam, von vorn....

Du hast 2 Speicher, welche uns hier interessieren:

  1. EEPROM
  2. RAM

Der Prozessor kann nur im RAM rechnen, für das EEPROM sind extra Zugriffe nötig.

Das bedingt, dass wir die Daten vom EEPROM ins RAM schaufeln müssen, um sie zu verarbeiten. Und dann wieder zurück, für eine dauerhafte Speicherung.

Soweit einig?

Wenn du also mit einem "Wert" arbeiten möchtest, brauchen wir 2 Orte!

// globale Variablen
float ramWert = 0.0;
float EEMEM eepWert = 47.4;

Die Variable ramWert liegt im RAM
Die Variable eepWert liegt im EEPROM

Der Kompiler kennt die Speicherorte!
Überlasse ihm die Speicherortverwaltung.
Er kann das besser, als du, denn er wurde, unter Anderem, dafür geschaffen.

Jetzt möchte ich den, im EEPROM gespeicherten, Wert um 1 erhöhen:

// in einer Funktion
EEPROM.get((int)&eepWert,ramWert); // Wert aus dem EEPROM ins RAM lesen

ramWert += 1; // Wert um 1 erhöhen

EEPROM.put((int)&eepWert,ramWert); // Wert aus dem RAM ins EEPROM schreiben

Klarer?

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>



int Kali4 = 0;                    // IF BEDINGUNG FÜR BUTTON

int wert = A0;



// AB HIER
float ramWert = analogRead(A0);
float EEMEM eepWert = 47.4;

//

LiquidCrystal_I2C lcd(0x3F, 2, 1,0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


const int PH4 = 2;                // EINGANG FÜR BUTTON
const int PH7 = 3;                // EINGANG FÜR BUTTON
void setup() {
  // testweise hier nochein analogread unwichtig hier
float ramWert = analogRead(A0);

Serial.begin(9600);
pinMode(PH4, INPUT);            // TASTER INPUT

  Serial.print(analogRead(A0));
}
void loop() {

  
Kali4 = digitalRead(PH4);
if (Kali4 == HIGH){ 
          EEPROM.get((int)&eepWert,ramWert);
          EEPROM.put((int)&eepWert, ramWert);       
          delay(20);
          
         
      
}
EEPROM.get((int)&eepWert,ramWert);
float ramWert1 = analogRead(A0);
 Serial.println(ramWert);
  Serial.println(eepWert);
  Serial.println(ramWert1);
  delay(800);
}

Ich weiß nicht was für eine Blockade ich habe.
Er sucht sich sein Speicherort selber und weiß diesen auch selber ? soweit richtig ?

Wieso speichert er immer nur 128 stat 367.

Der oberiege Code ist extra fürs "Verständnis" gemacht :slight_smile:
Aber danke das du es immernoch probierst mir zu erklären :slight_smile: