Arduino Festwerttabelle ins EEPROM stellen - wie?

Gast #5618336
Lesenswert?

Hallo,

ich habe ein paar Tabellen, die sehr groß sind. Für einen Nano könnte es 
schon eng werden. Da auf die Tabellen nur lesend zugegriffen wird, habe 
ich mir überlegt, ob man die nicht auch ins EEPROM verlegen könnte. Wie 
kriege ich das am besten hin?

Beispieltabelle:
1
volatile const int TestArray[400] = {500,505,506,497,535,524,494,550,532,534,533,535,523,559,567,588,579,568,611,621,611,648,594,596,629,659,556,617,642,588,590,610,608,612,616,615,590,626,560,598,573,627,636,572,577,562,622,606,620,604,588,652,582,655,625,613,618,592,554,629,640,577,589,580,619,620,584,589,620,651,626,632,629,602,554,635,599,613,585,569,651,562,600,581,623,606,595,584,621,617,629,617,624,586,620,620,604,614,579,614,560,605,582,583,562,653,620,608,595,627,571,586,591,637,610,601,635,550,599,562,650,553,617,596,591,605,616,620,621,575,610,636,598,607,574,587,635,621,631,583,645,592,623,587,554,627,554,614,626,574,634,604,555,589,601,646,630,592,608,650,573,612,620,660,592,592,603,603,598,605,584,592,627,600,603,615,594,586,659,620,603,567,632,606,585,591,650,591,605,577,649,597,583,579,608,633,633,632,615,617,637,622,623,588,604,633,560,600,657,568,601,653,632,572,616,643,603,605,638,590,596,648,582,622,601,632,639,642,595,621,611,602,601,601,598,571,637,626,619,639,615,585,625,595,577,656,579,592,623,598,643,584,636,614,606,573,592,617,601,579,601,590,600,628,599,619,568,586,594,588,636,583,576,603,593,608,639,569,609,619,642,606,632,612,633,562,612,574,650,613,562,594,614,578,585,564,621,612,607,584,619,604,614,552,595,612,589,629,640,602,609,606,630,603,602,632,610,565,591,585,598,585,593,602,627,547,609,616,603,613,589,614,609,632,596,572,624,610,602,631,644,568,591,625,593,639,601,624,634,613,573,577,610,615,579,604,609,633,606,645,616,597,587,592,646,603,639,606,564,595,602,609,570,606,594,628,610,622,604,594,596,579,587,611,609,602,550,617,579,600,613,586,642,611,580,627,622,636,579,569};
Gast #5618357
Lesenswert?

Hallo Elli,
hast tu tatsächlich so wenig Varianz in deiner Tabelle?
Dann zieh einfach für die Tabelle 500 ab, und schlag sie später wieder 
drauf. Dann reicht dir ein uint8_t(0-255) und schon passt doppelt so 
viel in den Flash.
#5618464
Lesenswert?

Wenn das konstante Werte sind gehören die ins Flash!
So, wie es oben steht liegt die im RAM,

Wenn das Flash bereits voll ist, bringen dich die 512 Byte EEPROM auch
nicht wirklich weiter, und dein eigentliches Problem liegt mit grosser 
Wahrscheinlichkeit an einer ganz anderen Stelle.
Gast #5618490
Lesenswert?

Stromverdichter schrieb:
> Dann zieh einfach für die Tabelle 500 ab, und schlag sie später wieder
> drauf. Dann reicht dir ein uint8_t(0-255) und schon passt doppelt so
> viel in den Flash.

Das würde wohl voll daneben gehen.
Wie willst du in einer uint8_t eine Wert von -6 unterbringen? ;-)

Der Offset darf maximal so groß sein, wie der kleinste Wert im Array, 
bei o.g. Belegung also 494.
Gast #5618555
Lesenswert?

Stefanus F. schrieb:
> El Friede schrieb:
>> Vermutlich habe ich mich mit EEPROM falsch ausgedrückt.
>> Ich meine in den Speicher, wo der Programmcode steht.
>
> https://www.nongnu.org/avr-libc/user-manual/pgmspace.html

Jepp, es funzt. Mit PROGMEM bleibt deutlich mehr RAM frei. Danke.

Beispiel:
1
<avr/pgmspace.h
2

3
volatile const int TestArray[400] PROGMEM = {500,505,506,497,535,524,494,550,532,534,533,535,523,559,567,588,579,568,611,621,611,648,594,596,629,659,556,617,642,588,590,610,608,612,616,615,590,626,560,598,573,627,636,572,577,562,622,606,620,604,588,652,582,655,625,613,618,592,554,629,640,577,589,580,619,620,584,589,620,651,626,632,629,602,554,635,599,613,585,569,651,562,600,581,623,606,595,584,621,617,629,617,624,586,620,620,604,614,579,614,560,605,582,583,562,653,620,608,595,627,571,586,591,637,610,601,635,550,599,562,650,553,617,596,591,605,616,620,621,575,610,636,598,607,574,587,635,621,631,583,645,592,623,587,554,627,554,614,626,574,634,604,555,589,601,646,630,592,608,650,573,612,620,660,592,592,603,603,598,605,584,592,627,600,603,615,594,586,659,620,603,567,632,606,585,591,650,591,605,577,649,597,583,579,608,633,633,632,615,617,637,622,623,588,604,633,560,600,657,568,601,653,632,572,616,643,603,605,638,590,596,648,582,622,601,632,639,642,595,621,611,602,601,601,598,571,637,626,619,639,615,585,625,595,577,656,579,592,623,598,643,584,636,614,606,573,592,617,601,579,601,590,600,628,599,619,568,586,594,588,636,583,576,603,593,608,639,569,609,619,642,606,632,612,633,562,612,574,650,613,562,594,614,578,585,564,621,612,607,584,619,604,614,552,595,612,589,629,640,602,609,606,630,603,602,632,610,565,591,585,598,585,593,602,627,547,609,616,603,613,589,614,609,632,596,572,624,610,602,631,644,568,591,625,593,639,601,624,634,613,573,577,610,615,579,604,609,633,606,645,616,597,587,592,646,603,639,606,564,595,602,609,570,606,594,628,610,622,604,594,596,579,587,611,609,602,550,617,579,600,613,586,642,611,580,627,622,636,579,569};

Result:
> Der Sketch verwendet 10508 Bytes (34%) des Programmspeicherplatzes.
> Das Maximum sind 30720 Bytes.
> Globale Variablen verwenden 624 Bytes (30%) des dynamischen Speichers,
> 1424 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Und jetzt ohne PROGMEM:
1
<avr/pgmspace.h
2

3
volatile const int TestArray[400] = {500,...,569};

> Der Sketch verwendet 10508 Bytes (34%) des Programmspeicherplatzes.
> Das Maximum sind 30720 Bytes.
> Globale Variablen verwenden 1424 Bytes (69%) des dynamischen Speichers,
> 624 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.


Eine Frage noch: Wieso ändert sich die Belegung des 
Programmspeicherplatzes nicht? Hier wie da bleiben es 10508 Bytes.
Gast #5618564
Lesenswert?

El Friede schrieb:
> Eine Frage noch: Wieso ändert sich die Belegung des
> Programmspeicherplatzes nicht? Hier wie da bleiben es 10508 Bytes.

Weil die initialen Werte beim Programmstart noch vor der main() Funktion 
vom Flash in das RAM kopiert werden. Das RAM weiß ja sonst nicht, welche 
Werte diese Speicherzellen haben sollen.
Gast #5618569
Lesenswert?

Stefanus F. schrieb:
> Weil die initialen Werte beim Programmstart noch vor der main() Funktion
> vom Flash in das RAM kopiert werden. Das RAM weiß ja sonst nicht, welche
> Werte diese Speicherzellen haben sollen.

OK. Nur zum besser verstehen: Heißt das im Umkehrschluss, dass die Werte 
ohne PROGMEM auch schon im Flash stehen, nur zum initialisieren des 
RAM?

Mit PROGMEM müssten sie 2x im Flash stehen: 1x zum initialisieren und 
zum 2. als Tabelle. Ist das so?
Gast #5618696
Lesenswert?

Stefanus F. schrieb:
> Georg G. schrieb:
>> Man kann Variable mit dem Attribut der Memory Section versehen.
>> eeprom ist definiert. Dann landet alles gleich dort,wo es hin
>> soll und man kann sich den Umweg über das File ersparen.
>
> Wie werden dann die initialen Werte ins EEprom geschrieben?

Ja, das Problem ist mir schon unter gekommen...
Dazu habe ich meine Arduino IDE so erweitert, dass ich die erzeugte 
*.eep aus dem Menü auf einen Arduino spielen kann. Incl. Anwendung und 
auch Bootloader, wenn nötig.
Eigentlich ist es nur eine Zeile in einer Konfigurationsdatei (ohne die 
originalen Dateien anzufassen)
Und der Upload erfolgt über einen (beliebigen?) ISP Programmer.

Wenn Bedarf besteht, dann kann ich es ja mal raus suchen und versuchen, 
in erklärende Worte zu fassen ...
Gast #5618960
Lesenswert?

Stefanus F. schrieb:
> Weil die initialen Werte beim Programmstart noch vor der main() Funktion
> vom Flash in das RAM kopiert werden. Das RAM weiß ja sonst nicht, welche
> Werte diese Speicherzellen haben sollen.

Die werden nicht kopiert, sondern man muss per Pointer darauf zugreifen. 
Steht ebenfalls auf der von mir und dir verlinkten Seite.
#5618970
Lesenswert?

Hallo,

eine andere Idee wäre mal zu schauen ob sich deine Werte nicht auch 
durch eine einfache Funktion (4.-5. Grades) darstellen lässt? Muss man 
natürlich schauen wie gut man eine Funktion annähern kann, aber dann 
müsstest du gar ncihts mehr speichern außer deine Funktion und 
berechnest die Werte on the fly. Wie gesagt nur ne Idee, hab nicht 
überprüft wie die Werte aussehen bzw. MATLAB angeschmissen und was 
berechnen lassen.

Gruß

EDIT = Vergiss meine Idee, die Funktion wäre zu komplex.
Gast #5619016
Lesenswert?

MikeH schrieb:
>> Weil die initialen Werte beim Programmstart noch vor der main() Funktion
>> vom Flash in das RAM kopiert werden. Das RAM weiß ja sonst nicht, welche
>> Werte diese Speicherzellen haben sollen.

> Die werden nicht kopiert, sondern man muss per Pointer darauf zugreifen.
> Steht ebenfalls auf der von mir und dir verlinkten Seite.

Normale globale Variablen liegen im RAM. Wenn sie Initialisierungswerte 
ungleich 0 haben, werden diese vor dem Start der main() Funktion vom 
Flash ins RAM kopiert.

Wenn Du mir nicht glaubst, schau Dir das Assembler-Listing an.
Gast #5619030
Lesenswert?

Joachim B. schrieb:
> Arduino Fanboy D. schrieb:
>> Ja, das Problem ist mir schon unter gekommen...
>
> eine eep wird normal nicht erzeugt, ich nutze noch den flash und später
> das EEPROM vom RTC, ist leicher zu tauschen als den AVR.
>
> Ausserdem löscht die IDE den ganzen AVR auch das EEPROM, das müsste
> verhindert werden, aber bis jetzt brauche ich das nicht.

Da muss ich dir leider widersprechen.



Von den AVR Arduinos ist mir bekannt:

A:
Die Arduino IDE erzeugt beim kompilieren automatisch eine *.eep Datei.
Immer.
Das kann man nur verhindern, wenn man die Konfigurationsdateien 
verändert.

B:
Beim normalen Upload aus der Arduino IDE, wird das EEPROM nicht 
gelöscht, da bei allen Arduinos die EESAVE Fuse standardmäßig gesetzt 
ist.
Gast #5619036
Lesenswert?

Stefanus F. schrieb:
> Wenn Du mir nicht glaubst, schau Dir das Assembler-Listing an.

Die u.a. von dir verlinkte Dokumentation gibt eine ausführliche 
Erklärung:

"Now that your data resides in the Program Space, your code to access 
(read) the data will no longer work. The code that gets generated will 
retrieve the data that is located at the address of the mydata array, 
plus offsets indexed by the i and j variables. However, the final 
address that is calculated where to the retrieve the data points to the 
Data Space! Not the Program Space where the data is actually located. It 
is likely that you will be retrieving some garbage. The problem is that 
AVR GCC does not intrinsically know that the data resides in the Program 
Space."

Alles andere wäre auch sinnlos, weil kein bit im RAM gespart würde.
Ich bin damit raus.
Gast #5619064
Lesenswert?

MikeH schrieb:
> Now that your data resides in the Program Space, your code to access
> (read) the data will no longer work.

Das ist für C++ absolut richtig.
C hingegen kennt das __flash Attribut für Variablen.

Wenn man also die Datendefinition und die Zugriffsroutinen in C Dateien 
unterbringt, kann man da doch was managen, ohne explizit auf die 
pgm_read_***() Dinger zurückgreifen zu müssen.
Gast #5619101
Lesenswert?

MikeH schrieb:
> "Now that your data resides in the Program Space

Das gilt für den Fall mit PROGMEM.

Ich habe aber über normale Variablen ohne PROGMEM geschrieben. Das war 
doch der Fall, wo doppelt Speicher belegt wurde und der TO nachgehakt 
hatte, warum das so sei.

Wir haben aneinander vorbei geredet.

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