Forum: Mikrocontroller und Digitale Elektronik EEPROM Arduino long zahl


von Daniel E. (everyday_fun69)


Lesenswert?

Hallo in die Runde,
ich beschäftige mich grad mit dem EEPROM vom Arduino Mega2560.

Es gibt ja den Befehl:

EEPROM.get(addr, value);
EEPROM.get(addr, value);

So wie es es bisher verstanden habe, brauch ich mir bei dem Befehl 
"fast" einerlei Gedanken machen bezüglich der Speicherplatzverwaltung. 
Mein plan wäre eine long Zahl (4 Byte) in den EEPROm zu schreiben und zu 
lesen.

Damit würde ich bei einer Zahl bei Speicherstelle 0 anfangen und in der 
Theorie bei Speichertstelle 3 enden. Falls eine weitere Zahl geschrieben 
werden soll, müsste ich dann mit Speicherstelle 4 weiter machen. Ist das 
so korrekt wie ich es verstanden habe?

Danke an alle.

von Stefan F. (Gast)


Lesenswert?

Daniel E. schrieb:
> Ist das so korrekt wie ich es verstanden habe?

Ein konkretes Codebeispiel wäre besser, weil deine Aussagen
Interpretations-spielraum lassen. Wenn du es so gedacht hast, wie ich 
dich verstehe, dann lautet die Antwort: Ja ist korrekt.

von Jens G. (jensig)


Lesenswert?

Stefan F. schrieb:
> Ein konkretes Codebeispiel wäre besser, weil deine Aussagen
> Interpretations-spielraum lassen.

Was wäre denn hier falsch interpretierbar? Ist doch eigentlich alles 
klar - er will die Bytes aller Zahlen entsprechend ihrer 
auf-/absteigenden Endianness bzw. Wertigkeit sequentiell im Speicher 
ablegen, und alle 4 Bytes kommt die nächste Zahl dran. Er muß sich nur 
noch entscheiden, welche Endianness er umsetzen will (little/big 
endianness).
Also ja, richtig verstanden ...

von Georg M. (g_m)


Lesenswert?


von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Stefan F. schrieb:
> Ja ist korrekt.
Nein ist sie nicht.

Daniel E. schrieb:
> EEPROM.get(addr, value);

Da werden keine Values übergeben, sondern Referenzen auf Variablen.

Daniel E. schrieb:
> Falls eine weitere Zahl geschrieben
> werden soll, müsste ich dann mit Speicherstelle 4 weiter machen.
Das ist zawr richtig, aber dennoch eine gute Idee.
Lass den Kompiler rechnen. Der ist da zuverlässiger als ein Mensch.

Jens G. schrieb:
> Er muß sich nur
> noch entscheiden, welche Endianness er umsetzen will (little/big
> endianness).
Wenn him get und put verwendet, ist die Sache schon mal viel klarer, als 
du sie hier darstellst.

Jens G. schrieb:
> er will die Bytes aller Zahlen entsprechend ihrer
> auf-/absteigenden Endianness bzw. Wertigkeit sequentiell im Speicher
> ablegen,
Nein, er möchte Long lesen und schreiben. Und genau das kann get und put
Für Byte gibt es z.B. read write update und den Array Access.

Und natürlich wäre ein testbares Beispiel das Mittel der Wahl hier.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Adressvergabe übernimmt Compiler/Linker
1
#include <EEPROM.h> 
2
#include <Streaming.h> // die Lib findest du selber ;-)
3
Print &cout = Serial; // cout Emulation für "Arme"
4
5
 
6
 // Arduino erstellt *.eep Datei
7
unsigned long resetCount EEMEM {0};
8
unsigned long wasAnderes EEMEM {4711};
9
10
byte test EEMEM {42}; // noch ein byte reset Counter
11
12
13
void setup() 
14
{
15
  Serial.begin(9600);
16
  cout << F("Start: ") << F(__FILE__) << endl;
17
  
18
  unsigned long resetCount {0};
19
  EEPROM.get(int(&::resetCount),resetCount); // read
20
  ++resetCount;                              // modify
21
  EEPROM.put(int(&::resetCount),resetCount); // write
22
  
23
  cout << F("resetCount: ") << resetCount << endl;
24
  
25
  // read modify write und ausgabe in einer Zeile
26
  cout << F("test: ") << ++EEPROM[int(&test)] << endl;
27
}
28
29
void loop() 
30
{
31
32
}

Arduino F. schrieb:
> Das ist zawr richtig, aber dennoch eine gute Idee.
Da fehlt leider ein 'k'
> Das ist zwar richtig, aber dennoch keine gute Idee.

: Bearbeitet durch User
von Daniel E. (everyday_fun69)


Lesenswert?

Hallo und Danke für das zahlreiche Feedback.

Meinen Code muss ich noch mal ordnungsgemäß hier einstellen…

Danke erstmal

: Bearbeitet durch User
von Daniel E. (everyday_fun69)


Lesenswert?

Hallo und nochmal Danke für das zahlreiche Feedback.

Es wurde nach Code verlangt..

In diesem Progrämmlein wird nach jedem Neustart eine Zahl um +5 höher 
als vorher angezeigt. Außer beim ersten Mal, da wird 0 angezeigt, da der 
EEPROM Inhalt leer ist.

Korrekt ?

Leider hab ich keinen Arduino hier zum grad mal schnell testen.

Danke.
1
#include <EEPROM.h>
2
3
long Wegstrecke = 2100000000;                                  //-2.147.483.648 bis +2147483648. Ein Long benötigt 32 Bits/4 Bytes Speicherplatz
4
byte Adresse = 0;                 // 0 bis 255
5
bool Zahl =0;                                                
6
7
void setup() 
8
{
9
 // put your setup code here, to run once:
10
}
11
12
void loop()
13
{
14
15
if (Zahl == 0)
16
 {
17
 EEPROM.get(Adresse, Wegstrecke);                      
18
 Serial.println(Wegstrecke);          //nach den ersten Mal wir hier 0 angezeigt, dann später 2100000005 usw.
19
 Wegstrecke ++;
20
 Wegstrecke ++;
21
 Wegstrecke ++;
22
 Wegstrecke ++;
23
 Wegstrecke ++;
24
 EEPROM.put(Adresse, Wegstrecke);                  
25
 Zahl = 1;
26
 }
27
}

[Mod: C-Code in C-Tags verpackt]

: Bearbeitet durch Moderator
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Daniel E. schrieb:
>  Wegstrecke ++;
>  Wegstrecke ++;
>  Wegstrecke ++;
>  Wegstrecke ++;
>  Wegstrecke ++;


Wegstrecke += 5;

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Daniel E. schrieb:
> Meinen Code muss ich noch mal ordnungsgemäß hier einstellen…

Bist seit neun Jahren hier angemeldet und schaffst es nicht
deinen Code in entsprechende Code-Tags einzurahmen?

von Sebastian W. (wangnick)


Lesenswert?

Daniel E. schrieb:
> In diesem Progrämmlein wird nach jedem Neustart eine Zahl um +5 höher
> als vorher angezeigt. Außer beim ersten Mal, da wird 0 angezeigt, da der
> EEPROM Inhalt leer ist.
> Korrekt ?

Leeres bzw. gelöschtes Eeprom enthält 0xFF. Also wird wohl beim ersten 
Mal -1 angezeigt.

Bei dir ist die Adresse vom Typ byte. Das funktioniert nur für den 
vorderen Bereich des Eeproms. Der Atmega2560 hat 4K Eeprom, die Adressen 
laufen also bis 4095.

Die Größe einer Variablen in byte liefert sizeof(). Damit kannst du die 
die Adressen deiner Daten im Eeprom ausrechnen anstatt sie hart zu 
codieren. Oder du benutzt, noch eleganter, das EEMEM-Konstrukt des gcc 
wie oben von arduinof schon beschrieben.

LG, Sebastian

: Bearbeitet durch User
von Daniel E. (everyday_fun69)


Lesenswert?

> Bist seit neun Jahren hier angemeldet und schaffst es nicht
> deinen Code in entsprechende Code-Tags einzurahmen?


Ja, leider nicht aber ich Probier mich mal hier

<
#include <EEPROM.h>
long Wegstrecke = 2100000000; 
//-2.147.483.648 bis +2147483648. Ein Long benötigt 32 Bits/4 Bytes 
Speicherplatz
byte Adresse = 0;                 // 0 bis 255
bool Zahl =0;
void setup()
{
 // put your setup code here, to run once:
}
void loop()
{
if (Zahl == 0)
 {
 EEPROM.get(Adresse, Wegstrecke);
 Serial.println(Wegstrecke);          //nach den ersten Mal wir hier 0 
angezeigt, dann später 2100000005 usw.
 Wegstrecke ++;
 Wegstrecke ++;
 Wegstrecke ++;
 Wegstrecke ++;
 Wegstrecke ++;
 EEPROM.put(Adresse, Wegstrecke);
 Zahl = 1;
 }
}
>

: Bearbeitet durch User
von Christian M. (christian_m280)


Lesenswert?

Falsche Formatierung! Steht ja gleich obendran wie's geht!

Gruss Chregu

von Peter D. (peda)


Lesenswert?

Ich vermeide es prinzipiell von überall her auf den EEPROM zuzugreifen.
Ein einziges long zu schreiben, kostet auf dem AVR schon 32ms, das ist 
aus CPU-Sicht eine elend lange Zeit. Und wenn dabei die Spannung 
absackt, ist der Wert ungültig.
Ich lege daher alle zu speichernden Variablen im RAM in einer Struct an 
und arbeite nur darauf. Und wenn dann die Struct gespeichert werden 
soll, erfolgt das per Polling oder Interrupt im Hintergrund, d.h. keine 
CPU-Zeit wird verwartet.
Damit die Daten als gültig erkannt werden, kommt noch eine CRC16 dran. 
Entweder wird bei ungültiger CRC die Werksinitialisierung des RAM 
behalten oder noch eine 2. Kopie auf gültige CRC geprüft.
RAM-Variablen lassen sich ja ganz einfach vorbelegen. Bei 
EEPROM-Variablen kann das aber recht knifflig werden.

von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Daniel E. schrieb:
> ich Probier mich mal hier

Das hat nicht geklappt.

Der Hinweis, wie es geht, steht immer oberhalb des Textfeldes, in 
welchem Du einen neuen Beitrag erfasst. Ich habe mal einen Screenshot 
davon angefügt.

P.S.

Im zweiten Screenshot siehst Du, wie Dein C-Code auf Mobilgeräten 
aussieht, wenn Du keine C-Tags verwendest.

: Bearbeitet durch Moderator
von Daniel E. (everyday_fun69)


Lesenswert?

Peter D. schrieb:
> Ich vermeide es prinzipiell von überall her auf den EEPROM zuzugreifen.
> Ein einziges long zu schreiben, kostet auf dem AVR schon 32ms, das ist
> aus CPU-Sicht eine elend lange Zeit. Und wenn dabei die Spannung
> absackt, ist der Wert ungültig.
> Ich lege daher alle zu speichernden Variablen im RAM in einer Struct an
> und arbeite nur darauf. Und wenn dann die Struct gespeichert werden
> soll, erfolgt das per Polling oder Interrupt im Hintergrund, d.h. keine
> CPU-Zeit wird verwartet.
> Damit die Daten als gültig erkannt werden, kommt noch eine CRC16 dran.
> Entweder wird bei ungültiger CRC die Werksinitialisierung des RAM
> behalten oder noch eine 2. Kopie auf gültige CRC geprüft.
> RAM-Variablen lassen sich ja ganz einfach vorbelegen. Bei
> EEPROM-Variablen kann das aber recht knifflig werden.

Danke für das Feedback. Plan ist den km vom Tacho der Simme bei Zündung 
oder der Motor wird ausgemacht 1x zu schreiben. Dazu soll über einen 
analog Eingang die Spannung (12 V) überwacht werden und bei unter X V 
wird er Wert 1x geschrieben. Hierzu wird Controller und Display 
entkoppelt und mit genügend Kondensatoren am uC dafür gesorgt, dass die 
Spannung hält bis das Schreiben abgeschlossen ist. So der Plan.

Beitrag #7513527 wurde vom Autor gelöscht.
von Daniel E. (everyday_fun69)


Lesenswert?

Test 🙃
1
#include <EEPROM.h>
2
long Wegstrecke = 2100000000;                                  //-2.147.483.648 bis +2147483648. Ein Long benötigt 32 Bits/4 Bytes Speicherplatz
3
byte Adresse = 0;                 // 0 bis 255
4
bool Zahl =0;                                                
5
void setup() 
6
{
7
 // put your setup code here, to run once:
8
}

Got it 👍

: Bearbeitet durch User
von Daniel E. (everyday_fun69)


Lesenswert?

Noch eine „blöde Frage“

kann ich mit Program/Sketch X in den Eeprom Speicher 0 = 100 erstmals 
Schreiben und mit dem 2. Programm/Sketch Y was ich übertrage dann die 
100 auslesen oder wird mit dem zweiten Programm der Eeprom Inhalt 
verändert?

Sollte eigentlich nicht so sein … ich frage aber trotzdem mal 🙈

Dankeschön

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Daniel E. schrieb:
> oder wird mit dem zweiten Programm der Eeprom Inhalt
> verändert?

Die EESAVE Fuse bestimmt, ob ein ChipErase das EEPROM  löscht.
Ansonsten bleibt der Inhalt erhalten!

Damit die Konsistenz erhalten bleibt, geht die von mir vorgeschlagene 
Variante nicht zuverlässig, da der Linker die Adressen würfeln darf.

Alternativ:
Alle EEPROM Daten in eine Struktur stopfen und entweder in einem Rumms 
lesen, oder per offsetof() einzelne Daten.

von Rolf M. (rmagnus)


Lesenswert?

Daniel E. schrieb:
> So wie es es bisher verstanden habe, brauch ich mir bei dem Befehl
> "fast" einerlei Gedanken machen bezüglich der Speicherplatzverwaltung.

Naja, du musst sie halt komplett selber machen.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Peter D. schrieb:

> Ich vermeide es prinzipiell von überall her auf den EEPROM zuzugreifen.
> Ein einziges long zu schreiben, kostet auf dem AVR schon 32ms, das ist
> aus CPU-Sicht eine elend lange Zeit. Und wenn dabei die Spannung
> absackt, ist der Wert ungültig.
> Ich lege daher alle zu speichernden Variablen im RAM in einer Struct an
> und arbeite nur darauf. Und wenn dann die Struct gespeichert werden
> soll, erfolgt das per Polling oder Interrupt im Hintergrund, d.h. keine
> CPU-Zeit wird verwartet.
> Damit die Daten als gültig erkannt werden, kommt noch eine CRC16 dran.

Ein absolut sinnvolles Vorgehen.

Kann man Richtung "fail safe" noch etwas aufblasen, aber das ist dann 
sehr oft unter dem Aspekt der konkreten Anwendung bzw. des konkreten 
Wertes dieser Anwendung zu sehen. Sprich: das läßt sich nicht wirklich 
abstrahieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.