Forum: Mikrocontroller und Digitale Elektronik Arduino Festwerttabelle ins EEPROM stellen - wie?


von El Friede (Gast)


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};

von Stefan F. (Gast)


Lesenswert?


von Stromverdichter (Gast)


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.

von Harry L. (mysth)


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.

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

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.

von Stromverdichter (Gast)


Lesenswert?

Ach ja, und volatile ist hier imho nicht nötig

von Stefan F. (Gast)


Lesenswert?

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?

von Harry L. (mysth)


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?

Natürlich mit AVRDude!
Es wird eine .eep-Datei generiert.

: Bearbeitet durch User
von MikeH (Gast)


Lesenswert?

Du solltest die Tabelle lieber ins Flash legen, so wie hier beschrieben

https://www.nongnu.org/avr-libc/user-manual/pgmspace.html

von Harry L. (mysth)


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.

von O.Ffset (Gast)


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.

von Stromverdichter (Gast)


Lesenswert?

O.Ffset schrieb:
> Der Offset darf maximal so groß sein, wie der kleinste Wert im Array,
> bei o.g. Belegung also 494.

Du hast ja echt Adleraugen;-)

von El Friede (Gast)


Lesenswert?

Vermutlich habe ich mich mit EEPROM falsch ausgedrückt. Ich meine in den 
Speicher, wo der Programmcode steht. Ist auch EEPROM, wird aber wohl 
Flash genannt.

von Stefan F. (Gast)


Lesenswert?

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

von El Friede (Gast)


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.

von Stefan F. (Gast)


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.

von El Friede (Gast)


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?

von El Friede (Gast)


Lesenswert?

El Friede schrieb:
> Mit PROGMEM müssten sie 2x im Flash stehen: 1x zum initialisieren und
> zum 2. als Tabelle. Ist das so?

Ich korrigiere: nur 1x natürlich.

von Stromverdichter (Gast)


Lesenswert?

El Friede schrieb:
> 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?

richtig,

deinen 2ten Teil versteh ich nicht, dürfte wohl falsch sein.

von El Friede (Gast)


Lesenswert?

Stromverdichter schrieb:
> deinen 2ten Teil versteh ich nicht, dürfte wohl falsch sein.

Habs schon gemerkt, danke.

Und danke auch an alle.

von Einer K. (Gast)


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

von Georg G. (df2au)


Lesenswert?

Stefanus F. schrieb:
> Wie werden dann die initialen Werte ins EEprom geschrieben?

Nur als Ergänzung: Wenn man ein .elf File erzeugten lässt, hat man alles 
beisammen, Flash, EEProm und Fuses.

von Joachim B. (jar)


Lesenswert?

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.

von MikeH (Gast)


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.

von Andre R. (ltisystem)


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.

: Bearbeitet durch User
von Stefan F. (Gast)


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.

von Einer K. (Gast)


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.

von MikeH (Gast)


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.

von Einer K. (Gast)


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.

von Stefan F. (Gast)


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.

von Joachim B. (jar)


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.

El Friede schrieb:
> {500,505,506,497,

da aber mindestens ein Wert 497 ist würde ich 450 abziehen dann bleiben 
alle Werte >0 && <255 jedenfalls positiv

von ~Mercedes~ (Gast)


Lesenswert?

Beim C-Compiler der IAR Workbench gibt es das
Attribut "flash".

So wird

flash char Name[]={"Mercedes"};

im Flash gehalten und auch von dort verwendet.

mfg

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.