Hallo allemiteinander,
ein ATMEGA16 nutzt zum Ablegen eines Parameters das interne EEPROM. Das
funktioniert auch soweit, d.h., der Parameter wird, falls er sich beim
normalen Betrieb verändert, ins EEPROM geschrieben. Ich habe immer
wieder den EEPROM-Inhalt ausgelesen und das überprüft.
Wenn man den Prozessor per Reset neu startet, wird der zuletzt
gespeicherte Wert aus dem EEPROM geholt - passt also auch. Wenn ich
jetzt die Versorgungsspannung aus- und wieder einschalte, funktioniert
das Procedere nicht mehr. Den abgespeicherten Wert gibt es nicht mehr.
Ich benutze die Fuse EESAVE, um den EEPROM-Inhalt beim Neubeschreiben
des Flash zu behalten. Dann habe ich rein zum Testen mal eine
Zeitschleife in die main-function gebaut, bevor der EEPROM-Inhalt nach
einem Neustart gelesen wird. Das hat aber auch nichts geholfen. Für
meine EEPROM-Geschichte benutze ich die im AVR-GCC-Tutorial
vorgestellten Routinen.
Was habe ich übersehen, weil sich der ATMEGA16 bei mir so verhält? Ich
habe jetzt nicht den gesamten Programmcode gepostet, sondern nur die
Teile, die für die EEPROM-Sachen zuständig sind. Vielleich mache ich ja
einen grundsätzlichen Fehler:
1
#include<avr/eeprom.h>
2
int8_tvalue=0;
3
uint8_teeGluehByteEEMEM=1;
4
5
// init nach einschalten oder reset:
6
7
value=eeprom_read_byte(&eeGluehByte);//gespeicherten Wert aus EEPROM lesen
8
9
// bei neuem ATMEGA sind die EEPROM-Zellen 0xFF
10
// falls der gelesene Wert ueber 0x46 liegt, wird in die EEPROM-Zelle 0x14 geschrieben
11
// value hat dann den (dezimalen) Wert 20
12
13
if(value>70)
14
{
15
value=20;
16
eeprom_write_byte(&eeGluehByte,value);
17
}
18
19
// später dann in der function main():
20
21
Status.Data_changed=1;
22
eeprom_write_byte(&eeGluehByte,value);// neuen Wert in EEPROM speichern
23
Status.Data_changed=0;
Kann mir jemand einen Tipp geben, was ich falsch mache?
Servus
Peter
und überlasse das Festlegen der eigentlichen Adresse im EEPROM dem
Kompiler.
Nimm hier mal das Leerzeichen raus:
1
eeprom_read_byte(&eeGluehByte);
Schreib übrigens nicht zu oft ins EEPROM. Es ist 'nur' für ca. 100000
Schreibzyklen pro Zelle spezifiziert, so das du sparsam mit
Schreibzyklen umgehen solltest.
Hallo Matthias,
danke für Deine Antwort.
Matthias Sch. schrieb:> Peter Spiess schrieb:>> uint8_t eeGluehByte EEMEM = 1;>> Das sieht nicht so richtig nach einer EEPROM Deklaration aus. Probier> mal>
> und überlasse das Festlegen der eigentlichen Adresse im EEPROM dem> Kompiler.
Ok, habe ich so ausprobiert. Das funktioniert ohne Probleme, allerdings
mit gleichem Ergebnis. Bei einem Reset, ohne dem Controller die
Stromversorgung zu nehmen, wird der gespeicherte Wert wieder geladen.
Wenn ich den Strom aus- und wieder einschalte, ist der Wert weg.
Elektrisch ist der ATMEGA16 wie im Bild angeschlossen. Die Kondensatoren
C6 - C8 sind direkt bei den uP-Pins 5, 17 und 38 platziert. Das sollte
doch so in Ordnung sein.
> Nimm hier mal das Leerzeichen raus:>
1
>eeprom_read_byte(&eeGluehByte);
2
>
Habe ich gemacht.
> Schreib übrigens nicht zu oft ins EEPROM. Es ist 'nur' für ca. 100000> Schreibzyklen pro Zelle spezifiziert, so das du sparsam mit> Schreibzyklen umgehen solltest.
Ja, das ist klar. Es wird nur bei einer Änderung des Wertes ins EEPROM
geschrieben.
Servus
Peter
Du mußt den Brown Out Detector verwenden, damit ein sauberer Reset bei
fehlerhafter Eingangsspannung ausgelöst wird.
Die älteren ATmega hatten immer wieder Probleme mit dem EEPROM; ein
neuer Typ dürfte besser funktionieren.
Peter Spiess schrieb:> Kann mir jemand einen Tipp geben, was ich falsch mache?
Gar nichts. Das funktioniert auf einem Attiny25 einwandfrei, was du da
gemacht hast.
War da nicht irgendwas mit EEPROM-Adresse 0 bei den alten Gurken? Ich
meine natürlich bei den beliebten Klassikern. Aber da soll Atmel
irgendwas mit Adresse 0 vergurkt haben. Da gibt es, glaube ich, auch
eine Empfehlung, Adresse 0 nicht zu benutzen.
Probier das mal "händisch" auf einer anderen Adresse:
Peter Spiess schrieb:> Ok, habe ich so ausprobiert. Das funktioniert ohne Probleme, allerdings> mit gleichem Ergebnis. Bei einem Reset, ohne dem Controller die> Stromversorgung zu nehmen, wird der gespeicherte Wert wieder geladen.> Wenn ich den Strom aus- und wieder einschalte, ist der Wert weg.
Typischer Brown-Out-Effekt. Deine Versorgungsspannung fällt zu langsam.
Das gibt dem µC ein Zeitfenster, in dem er noch irgendwas macht weil die
Spannung dafür noch hoch genug ist, dies aber nicht mehr richtig macht,
weil die Spannung für eine korrekte Arbeit bereits zu gering ist.
Sprich: er stürzt undefiniert ab und dabei wird in deinem Fall mehr oder
weniger zufällig der EEPROM-Inhalt in Mitleidenschaft gezogen. Es können
dabei auch völlig andere Sachen passieren, bis hin zur teilweisen oder
gar vollständigen Löschung des Programms im Flash.
Dagegen helfen Softwareänderungen höchstens zufällig. Nur zwei Maßnahmen
lösen das Problem wirklich:
1) (Bezogen auf den Zweck) sinnvolles Design der Versorgung.
2) µC bei ungenügender Spannung in den Reset-Zustand zwingen durch:
2.a) Internen Brownout-Detektor
2.b) Externen Reset-IC
Es spricht übrigens auch absolut nix dagegen, 1) und 2) in Kombination
anzuwenden...
Hallo m.n. und c-hater,
Ihr habt Recht, mit aktivierten Brown Out Detektor funktioniert es
einwandfrei!
Versorgt habe ich die Schaltung über einen 7805 mit entsprechenden Elkos
am Ein- und Ausgang. Wenn ich die Versorgung wegnehme, gehen die
geregelten 5V nicht aprupt, sondern relativ langsam in die Knie. Ist ja
nachvollziehbar, dass der uP unkontrolliert abstürzt.
Daran hatte ich nicht gedacht, vielen Dank für Eure Hinweise und Hilfe.
Servus
Peter
Hallo Thomas,
Thomas Eckmann schrieb:> War da nicht irgendwas mit EEPROM-Adresse 0 bei den alten Gurken? Ich> meine natürlich bei den beliebten Klassikern.
:-)
Das mit dem Problem bei Adresse 0 habe ich auch schon gehört. Was
würdest Du mir als modernen Nachfolgetyp für die alten ATMEGAs
empfehlen?
Servus
Peter
Peter Spiess schrieb:> Hallo Thomas,>> Thomas Eckmann schrieb:>> War da nicht irgendwas mit EEPROM-Adresse 0 bei den alten Gurken? Ich>> meine natürlich bei den beliebten Klassikern.>> :-)> Das mit dem Problem bei Adresse 0 habe ich auch schon gehört. Was> würdest Du mir als modernen Nachfolgetyp für die alten ATMEGAs> empfehlen?>> Servus> Peter
Pinkompatibel zum 16er sind die 164, 324, 644 in der letzten Version
jeweils als A oder PA und der 1284 und 1284P.
mfg.
Peter Spiess schrieb:> int8_t value = 0;> if (value > 70)
Falls die gelesene Zelle nicht initialisiert ist und 0xff enthält, wird
valie zu -1 und damit der Vergleich nicht erfüllt.
Hallo Johann,
Johann L. schrieb:> Peter Spiess schrieb:>> int8_t value = 0;>> if (value > 70)>> Falls die gelesene Zelle nicht initialisiert ist und 0xff enthält, wird> value zu -1 und damit der Vergleich nicht erfüllt.
ok, hast Du Recht. Wäre dann ein
Johann L. schrieb:> Kommt ganz darauf an, was der Test value > 70 soll und wie value im> weiteren Verlauf des Programms verwendet wird.
Es geht um eine Glühkerzenregelung für Modellmotore. value wird mit
einem Drehencoder eingestellt und kann Werte zwischen 20 ... 70 haben.
Das wiederum bestimmt, wie hell die Glühkerze leuchtet.
Ursprünglich hatte ich vor (und möchte das auch noch verwirklichen),
dass nach jedem Schreiben in eine EEPROM-Zelle die nächste Zelle
genommen wird. Somit "verbrauche" ich nicht eine einzelne Zelle, sondern
verteile die Schreibzyklen auf das gesamte EEPROM. Jede neu zu
verwendende Zelle enthält 0xFF.
Wenn jetzt der Wert 0xFF gelesen wird, bekommt die Glühkerze zuviel
Strom und brennt durch. Deshalb wollte ich sicherstellen, dass eine
nicht initialisierte Zelle einen definierten Wert bekommt.
Servus
Peter
Peter Spiess schrieb:
> Ursprünglich hatte ich vor (und möchte das auch noch verwirklichen),
> dass nach jedem Schreiben in eine EEPROM-Zelle die nächste Zelle> genommen wird. Somit "verbrauche" ich nicht eine einzelne Zelle, sondern> verteile die Schreibzyklen auf das gesamte EEPROM. Jede neu zu> verwendende Zelle enthält 0xFF.
Rein akademisch kann man das natürlich machen. Aber mehr als eine kleine
Programmierübung ist das nicht.
Wenn sich der Wert durch Drehen am Encoder ändert, wird er
abgespeichert.
Das muß aber nicht sofort passieren. Ich verbinde das mit einem Timer
und prüfe 1s nachdem sich am Encoder nichts mehr getan hat, ob der Wert
sich gegenüber dem EEPROM-Inhalt geändert hat. Klar, wenn in der
Zwischenzeit der Akku schlapp macht(bla)...
Nur dann wird dieser auch abgespeichert. Die 100.000 Zyklen des EEPROMS
beziehen sich auf das Löschen und sind in diesem Fall mehr als du jemals
brauchen wirst. Wenn der täglich, auch Weihnachten, Silvester und Omas
Geburtstag, 10 Mal geändert wird, sind das knapp 30 Jahre.
mfg.
Hallo Thomas,
Deine Berechnung ist ok :-) Ich sehe es als kleine Programmierübung, da
ich noch nicht so fit in C bin.
Von den von Dir genannten Alternativcontrollern lasse ich mir bei meiner
nächsten Bestellung einen zum Ausprobieren mitschicken.
Servus
Peter