EEPROM Arduino long zahl

OP #7512320
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.

#7512338
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 ...

(Firma: Gast) #7512342
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.

(Firma: Gast) #7512352
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.

OP #7513141
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]

#7513223
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

OP #7513400
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; } }

#7513474
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.

Moderator Persönliche Seite #7513482
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.

Angehängte Dateien:
OP #7513521
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 von einem Moderator gelöscht.
OP #7513621
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

(Firma: Gast) #7513648
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.

(Firma: 1984now) #7515517
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren