Hallo,
Ich möchte mal ein kleines Projekt starten! Dieses wird ein
Elektronisches Sparschwein! Die Geldwurfanlage und so weiter ist noch in
Arbeit, es happert am Programm!
Angelehnt an diesen Beitrag:
Beitrag "float - Wert in EEPROM speichern"
hab ich meine Funktionen geschrieben, die es irgendwie nicht richtig
tun.
Ich benutze einen ATMEGA16L8 so wie das AVRStudio 4.18 SP2 und das
AVR-Starterkit STK500 zu testzwecken. Angeschlossen sind im Moment die 8
Taster um die Münzen zu simulieren! Der Speicher ist eine (double)
Variable, die ich einem I²C EEPROM (ST24C02) speichern möchte, damit der
Speicher erhalten bleibt, wenn der Strom ausgeschaltet wird.
Um die Funktion des EEPROMs zu testen schreibe ich den Startwert rein
und lese ihn anschliessend wieder aus, um damit weiter zu arbeiten!
Jedoch schreibe ich eine 10.00 rein und bekomme immer wieder 12.08
raus!?!
Bei anderen Versuchen meines Programms bekam ich andauernd 0.00 raus!?!
Hier der wichtige Teil des Codes:
1
intmain()
2
{
3
lcd_init();// LCD Initialisieren
4
5
6
7
lcd_print("Hallo Da");
8
lcd_line(3);
9
lcd_print("gobert ");
10
_delay_ms(PAUSE4);
11
12
EEOpen();
13
14
floatdSpeicher=10.00;// 1. Durchlauf!
15
schreiben(dSpeicher);// Zählstand des Geldspeichers in den EEPROM schreiben
16
17
18
dSpeicher=lesen();// 2. Durchlauf!
19
// Zählstand des Geldspeicher aus dem EEPROM lesen
Meine Funktionen sind:
1
// Schreibvorgang. Speichert (double) in die ersten 8 Speicherzellen des I²C-EEPROM
2
voidschreiben(floatdWert)
3
{
4
unsignedintaddress=0;
5
6
char*c=(char*)&dWert;
7
8
9
for(address=0;address<sizeof(float);address++)
10
{
11
lcd_clear();
12
lcd_print("schreibe");
13
lcd_line(3);
14
lcd_print(*c);
15
_delay_ms(PAUSE1);
16
if(EEWriteByte(address,*c)==0)// Bediengung erfüllt wenn schreiben Fehlerhaft
17
{
18
lcd_clear();
19
lcd_print("Fehler a");
20
lcd_line(3);
21
lcd_print("t: Write");
22
while(1);// Endlosschleife um weiteres schreiben zu verhindern
23
24
}
25
if(EEReadByte(address)!=*c)
26
{
27
lcd_clear();
28
lcd_print("Fehler a");
29
lcd_line(3);
30
lcd_print("t: Read");
31
while(1);// Endlosschleife um weiteres schreiben zu verhindern
32
33
}
34
//address++;
35
c++;
36
}
37
lcd_ausgabe(dWert);
38
_delay_ms(PAUSE1);
39
}
40
41
// Lesevorgang. Speichert 8 Bytes in dWert und gibt (double) zurück
42
floatlesen(void)
43
{
44
unsignedintaddress=0;
45
floatdWert;
46
47
char*c=(char*)&dWert;
48
49
for(address=0;address<sizeof(float);address++)
50
{
51
*c=EEReadByte(address);
52
53
c++;
54
}
55
56
57
58
lcd_ausgabe(dWert);
59
_delay_ms(PAUSE1);
60
returndWert;
61
62
}
ich verwnede double bzw float um auch 1 Cent münzen addieren zu können!
Vielleicht gitbs auch andere Möglichkeiten bzw Variablen, mit denen ich
rechnen könnte und die dann einfacher zum abspeichern im EEPROM sind!?!
lg und danke im vorraus
Gregor
Gregor schrieb:> Jedoch schreibe ich eine 10.00 rein und bekomme immer wieder 12.08> raus!?!> Bei anderen Versuchen meines Programms bekam ich andauernd 0.00 raus!?!
Sieh dir mal die einzelnen Bytes an, die du reinschreibst und die wieder
gelesen werden. Vielleicht kann man ja dort etwas erkennen.
> ich verwnede double bzw float um auch 1 Cent münzen addieren zu können!
Ist noch lange kein Grund.
Mit einem uint32_t kann man wunderbar auch Cent zählen.
Ganze 4294967296 davon.
Das sind dann ~ 42949672 Euro, oder knapp 43 Milliarden Euro.
Sicher das das nicht reicht?
> Vielleicht gitbs auch andere Möglichkeiten bzw Variablen, mit denen ich> rechnen könnte und die dann einfacher zum abspeichern im EEPROM sind!?!
Eher nicht.
An dieser Stelle ist float sicher nicht dein Problem.
Der float wird eher dann zum Problem, wenn du 100 mal 1 Cent einwirfst
und am Ende dann nicht 1 Euro im Sparschwein ist. Aber das ist momentan
eine andere Baustelle.
Sieh dir mal auf Byte Ebene an was du schreibst und was du liest.
PS: Der Datentyp der Wahl um mit Bytes zu arbeiten ist 'unsigned char'.
Auf keinen Fall aber ist er 'char'.
Hallo Gregor,
beim gcc-avr kann man auch ganze Speicherblöcke lesen/schreiben. Geht
das bei deinem Compiler nicht? Das wäre vielleicht eine Alternative.
Für diesen speziellen Fall würde ich allerdings auch zu integer-Werten
raten.
Gruß, DetlevT
Detlev T. schrieb:> Hallo Gregor,>> beim gcc-avr kann man auch ganze Speicherblöcke lesen/schreiben. Geht> das bei deinem Compiler nicht? Das wäre vielleicht eine Alternative.
Achtung: Er benutzt einen externen EEPROM.
Warum weiß ich zwar nicht, aber ist so.
Die double oder float variable erschien fürs erste als bequemer zum
rechnen!
Den externen EEPROm wollte ich nutzen, da der eine wesentlich mehr
Schreibzyklen garantiert (mehr als 1.000.000).
Finds schade, dass die DIee so nicht funktioniert(warum auch immer) und
ich keine Lösung daüfr finde!?!
Werde dann wohl doch auf den internen EEPROM zurück greifen und die
fertigen Funktionen ausprobieren!
Ps: char oder unsigned char macht keinen unterschied( Ergebnis: 12.08)
@ Karl heinz Buchegger (kbuchegg) (Moderator)
>> ich verwnede double bzw float um auch 1 Cent münzen addieren zu können!>Ist noch lange kein Grund.>Mit einem uint32_t kann man wunderbar auch Cent zählen.>Ganze 4294967296 davon.>Das sind dann ~ 42949672 Euro, oder knapp 43 Milliarden Euro.>Sicher das das nicht reicht?
Na Karl Heinz, hat dich die Finanzkrise auch erwischt? Bei mir sind das
nur 43 MILLIONEN Euro. ;-)
MFg
Falk
> bei mir sind das nur 43 MILLIONEN Euro. ;-)
Jetzt müßte man aber auch noch das minimale virtuelle Volumen des
virtellen Sparschweins ausrechnen, wenn mit größtmöglicher mechanischer
virtueller Münze eingezahlt wird .....
Gregor schrieb:> Die double oder float variable erschien fürs erste als bequemer zum> rechnen!
Das schaut aber nur so aus.
Ob du intern in Euro (mit Kommazahlen) oder in Cent (ohne Kommazahlen)
rechnest, macht aber einen Riesenunterschied. Sowohl was Genauigkeit
(speziell beim Aufsummieren) als auch Geschwindigkeit angeht.
> Den externen EEPROm wollte ich nutzen, da der eine wesentlich mehr> Schreibzyklen garantiert (mehr als 1.000.000).
Dann rechne dir doch einmal aus, wieviele Einzahlungen du auf dein
internes EEPROM machen musst, ehe die garantierte Lebensdauer hinüber
ist und wie lang das in etwa durchhalten wird, wenn du, sagen wir mal,
alle 2 Tage eine Einzahlung machst.
Mit diesen (zugegeben angenommenen) Rahmenbedingungen wird das EEPROM
noch funktionieren, wenn deine Kinder selber schon Opa sind.
Und ausserdem sagt niemand, das das EEPROM sofort ausfällt, wenn die von
Atmel garantierte Zyklenzahl erreicht ist.
> Werde dann wohl doch auf den internen EEPROM zurück greifen und die> fertigen Funktionen ausprobieren!
Du gibst zu schnell auf.
Da gibt es ein Problem und keiner weiß was genau das Problem ist. Ist
immer schlecht, wenn man den Dingen nicht auf den Grund geht. Eines
Tages wirst du vielleicht wirklich ein externes EEPROM benötigen, und
was dann?
>> Ps: char oder unsigned char macht keinen unterschied( Ergebnis: 12.08)
Das macht nichts.
Es geht ums Prinzip. Byte == unsigned char
AUch wenn es bei dir momentan keinen Unterschied macht. Es gibt einen!
Und der schlägt genau dann zu, wenn du es am allerwenigsten gebrauchen
kannst.
Hallo,
ich hab jetzt mal das interne EEPROM genutzt.
Das scheint zu funnktionieren!
Hab mich da an das tutorial gerichtet!
Jeztt hab ich das Problem, dass ich schreiben und lesen kann, doch wenn
ich es so compiliere, dass ich nur lese, bekomme ich ein "nan" raus!
Ich wollte nun versuchen das mit festen Adressen im EEPROM zu
realisieren, doch irgendwie klappts nicht und ich weiss jetzt nicht so
genau, wie ich das lösen soll!?!
Kann mir einer nen tipp geben, wie ich das machen kann? Hab das im
Tutorial nicht richtig verstanden.
> Jeztt hab ich das Problem, dass ich schreiben und lesen kann, doch wenn> ich es so compiliere, dass ich nur lese, bekomme ich ein "nan" raus!
Kann es sein, dass du dir beim Flashen des neuen Programms das EEPROM
löscht?
Das weiss ich nicht!
Wenn die standard eeprom.h dies beim Programmstart tut, dann ja!?!
Ansonsten ruf ich eigentlich nichts auf, dass mir das EEPROM löschen
sollte!?!
Gregor schrieb:> Das weiss ich nicht!
Das solltest du aber!
> Wenn die standard eeprom.h dies beim Programmstart tut, dann ja!?!> Ansonsten ruf ich eigentlich nichts auf, dass mir das EEPROM löschen> sollte!?!
Das hat nichts mit C File oder Header File oder dergleichen zu tun.
Du musst in dem Brenn-Programm nach einer Einstellung suchen, mit der du
dem Brennprogramm mitteilst: "nur das Flash neu beschreiben, das EEPROM
in Ruhe lassen!" Alternativ gibt es auch noch die Möglichkeit, mittels
einer Fuse das EEPROM vor Überschreiben von aussen zu schützen.
SUPER!!!!!!!!!!!!!
Danke für den Tipp!!!
Einstellugnen bei den Fuses:
EESAVE --> Hacken rein, und das wars!
Mensch bin ich blöd! Da hätt ich auch selber drauf kommen müssen ;)
Danke!