Eines vorweg: mein Programm funktioniert wie es soll aber es gibt da
eine
Sache die mir nicht gefaellt,weil ich keine Antwort darauf habe.
Zur Sache:
Mein Programm speichert bestimmte Usereinstellungen im EEprom ab.Das ist
an sich nix besonderes=>
==========================
Mit "EEPROM.put(0,205); // brightness"
===========================
wird also an der Adresse 0 der Wert 205 abgelegt.(Ich verwende die
Arduino-GUI).
Mein Problem ist nun,dass bei einem Usergewollten "Factory"-Reset
mehrere Daten im EEprom in einem Rutsch abgelegt werden.
Das funktioniert auch, aber nur wenn die Adressen in aufsteigender(!)
Reihenfolge durchlaufen werden.
Also in etwa so:
EEPROM.put(0,205);
EEPROM.put(4,12);
EEPROM.put(10,124);
Wenn ich aber die Reihenfolge aendere:
EEPROM.put(10,124);
EEPROM.put(4,12);
EEPROM.put(0,205);
werden teilweise falsche Daten abgelegt.
Dieses Problem habe ich nur wenn die EEpromdaten innerhalb einer Routine
und die Adressen in beliebiger Reihenfolge abgelegt werden.
Hat dazu jemand eine Erklaerung?
Hinweis:
Als Gast kann ich erst wieder in einer Stunde antworten,sollte hier eine
Antwort eintrudeln....
Put ist für komplexere Datentypen gedacht.
> EEPROM.put(10,124);> EEPROM.put(4,12);> EEPROM.put(0,205);
Wenn du bytes ablegen willst:
EEPROM[10] = 124;
EEPROM[4] = 12;
EEPROM[0] = 205;
Davon mal abgesehen:
Ich halte es für fast schon verwerflich die Adressen händisch zu
berechnen.
Überlasse das besser dem Kompiler.
Der kann das.
Hallo,
sagen wir mal so. Die Adresse ist ein int und der Wert ein Byte. :-)
Kommt praktisch gesehen aufs Gleiche raus - Datensalat. Ja da lauert
eine kleine Falle die ich auch nicht auf dem Schirm hatte.
https://www.arduino.cc/en/Reference/EEPROMWrite
Veit D. schrieb:> nimm einmal statt put das write. Bleibt der Effekt erhalten?
So wie ich Zeit habe teste ich es mal mit nur int/long/ etc- Daten
Arduino Fanboy D. schrieb:> Put ist für komplexere Datentypen gedacht.
Ich will fuer meine EEpromdaten spaeter eine "structure" anlegen.
Arduino Fanboy D. schrieb:> Wenn du bytes ablegen willst
Ich verwende byte/long/float etc....
Die Testzeilen sind nur als Beispiel angegeben.
Arduino Fanboy D. schrieb:> EEPROM[10] = 124
Diese Zeile ist mir im Bezug auf die Arduino-Referenz neu.Wenn ich hin
und wieder mal auf die Schnelle was mit einem Arduino mache (meist
verwende ich Pics...)schaue ich kurz in der Referenz nach wie was
geschrieben werden muss und gehe dann auch davon aus ,dass es
funktioniert.
Fuer mich stellt sich immer noch die Frage ,warum ich mit der
EEPROM.put-Anweisung solche Probleme bekomme.
Auch wenn sie fuer komplexere Datentypen geschrieben und damit
eigentlich universeller ausgelegt wurde,sollte sie doch in der Lage sein
ein paar EEPROM-Zeilen in beliebiger Reihenfolge abzufertigen.
====================
Arduino Fanboy D. schrieb:> Veit D. schrieb:>> sehe ich nur Bytes> Ich sehe da int!> Darum überschreibt jedes seiner Put auch 2 Zellen.
Ich sehen da eigentlich auch nur "bytes" aber ist es moeglich,dass der
Compiler einen Wert von z.B. "205" implizit als Integer erkennt?
Dann duerfte mein Programm eigentlich ueberhaupt nicht laufen.
Toxic schrieb:> aber ist es moeglich,dass der> Compiler einen Wert von z.B. "205" implizit als Integer erkennt?AVR?
Natürlich sind Literale wie 205 int!
und 40000 wird zu einem long
Scheinbar schreibst du:
EEPROM.put(0,205);// schreibt int
Meinst aber
EEPROM.put(0,byte(205)); // schreibt byte
Toxic schrieb:> Ich will fuer meine EEpromdaten spaeter eine "structure" anlegen.
Das ist der richtige Ansatz.
Damit gehst du u.A, auch diesen Problemen aus dem Weg.
Denn dann stimmen deine Adressen und Datenblocklängen
Toxic schrieb:> Arduino Fanboy D. schrieb:>> EEPROM[10] = 124>> Diese Zeile ist mir im Bezug auf die Arduino-Referenz neu.Wenn ich hin> und wieder mal auf die Schnelle was mit einem Arduino mache (meist> verwende ich Pics...)schaue ich kurz in der Referenz nach wie was> geschrieben werden muss und gehe dann auch davon aus ,dass es> funktioniert.
Funktioniert auch!
Musst dich nur an die Regeln halten, welcher dir der Kompiler vorgibt!
Lesestoff: https://www.arduino.cc/en/Reference/EEPROMObject
Tipp:
Auch EEPROM[10]++ usw. funktioniert damit.
Arduino Fanboy D. schrieb:> Scheinbar schreibst du:> EEPROM.put(0,205);> Meinst aber> EEPROM.put(0,byte(205));
So isses und so funktioniert es auch bei mir(zufaelligerweise?).
Wenn der Compiler meine banale "205" aber als "int" ansieht und dann die
EEprom-Anweisung dies auch als 2-byte Wert abspeichert dann waere mein
Programm tot,da er damit die naechsten EEpromzellen ueberschreibt.
Wenn der Complier implizit denken darf ,will ich das aber auch und "205"
ist fuer mich ein Byte ;-) kleiner Scherz...
Und nochmal: Ich kann einzelne Zellen manuell im Programm nach belieben
abspeichern und das funktioniert ohne Datenverlust.Die Katastrophe(naja
etwas uebertrieben...) entsteht erst bei der sequentiellen Abarbeitung
der EEpromanweisungen.
Hallo,
nach nochmaligen nachdenken hatte ich das mit dem int für Daten auch
begriffen, so wie das Fanboy meinte. :-)
Einen bunt gemischten struct Datensatz habe ich soeben ausprobiert.
Funktioniert einwandfrei. Wenn du dir noch für jedes struct die Länge
ermitteln lässt, kannste beim Eeprom schreiben/lesen locker flockig an
die richtige Startadresse hüpfen.
Toxic schrieb:> Und nochmal: Ich kann einzelne Zellen manuell im Programm nach belieben> abspeichern und das funktioniert ohne Datenverlust.Die Katastrophe(naja> etwas uebertrieben...) entsteht erst bei der sequentiellen Abarbeitung> der EEpromanweisungen.
Du kannst beschweren wie du willst.
205 ist ein int Literal!
So steht es in der C++ Referenz.
z.B. auch hier:
https://en.cppreference.com/w/cpp/language/integer_literal
Der Kompiler befolgt die Regeln.
Ihm ist es völlig egal, ob du sie kennst, oder sie gut findest.
Mit deinen Fantasien kann er nichts anfangen, auch weil er nicht in
deinen Kopf schauen kann.
Du kannst dir tolle Sachen ausdenken, aber er gehorcht nur dem, was du
schreibst.
Toxic schrieb:> So isses und so funktioniert es auch bei mir(zufaelligerweise?).> Wenn der Compiler meine banale "205" aber als "int" ansieht und dann die> EEprom-Anweisung dies auch als 2-byte Wert abspeichert dann waere mein> Programm tot,da er damit die naechsten EEpromzellen ueberschreibt.> Wenn der Complier implizit denken darf ,will ich das aber auch und "205"> ist fuer mich ein Byte ;-) kleiner Scherz...>>> Und nochmal: Ich kann einzelne Zellen manuell im Programm nach belieben> abspeichern und das funktioniert ohne Datenverlust.Die Katastrophe(naja> etwas uebertrieben...) entsteht erst bei der sequentiellen Abarbeitung> der EEpromanweisungen.
Jetzt mal Butter bei die Fische, zeige deinen echten Code und nicht so
ein konstruiertes Beispiel, welches das von dir beschriebene Problem
nicht hat.
Natürlich betrachtet der Compiler einen normalen Zahlenwert als Integer
wenn du ihm nichts anderes sagst, oder wenn nicht eine implizite
Typkonversion erfolgt. Und das ist bei der 'put' Funktion nicht der
Fall. In deinem Beispiel werden immer 2 Bytes geschrieben.
Ich bin überzeugt, in deinem funktionierenden Code werden Variable
übergeben, die natürlich einen bestimmten Typ haben.
Hallo,
ich glaube ich weiß was der TO meint bzw. fragen möchte.
Auch wenn die Werte als int interpretiert und geschrieben werden, so ist
zwischen seinen Adressen 0, 4 und 10 genügend Platz für die jeweils 2
Byte großen int Werte. Und dennoch kommt Müll bei raus. Dafür habe ich
auch keine Erklärung.
Veit D. schrieb:> Wenn du dir noch für jedes struct die Länge> ermitteln lässt, kannste beim Eeprom schreiben/lesen locker flockig an> die richtige Startadresse hüpfen.
Das kann alles der Kompiler!
Dazu muss man nur die Struktur in EEPROM anlegen
1
structTest
2
{
3
chara,b,c,d;
4
// hier weitere Daten
5
};
6
TesttestEEMEM;
7
8
// später dann
9
chara;
10
EEPROM.get(int(&test.a),a);// nur ein char aus der Struktur importieren
Veit D. schrieb:> Und dennoch kommt Müll bei raus. Dafür habe ich> auch keine Erklärung.
Nöö..
Das ist nur, weil er Fantasiecode zeigt.
Man kann Arduino Libs hassen, oder lieben....
Aber die EEPROM Lib ist eine der besseren und funktioniert perfekt!
Hallo,
das das alles der Kompiler automatisch kann war mir so nicht bewusst.
Ist gut zu wissen. Danke.
Ich dachte bei meiner Ausführung vorhin daran das man vielleicht mehrere
structs haben könnte und dann beim schreiben oder lesen nur das struct
an die Eeprom Funktion im Gesamten übergibt und später auch im Gesamten
wieder ausliest. Dabei mit der ermittelten Länge von bequem von struct
Anfang zum nächsten struct Anfang springt. Falls das jetzt irgendwie
verständlich rüberkommt.
Okay, bei genauer Betrachtung doppelt gemoppelt. Man hat eben wie immer
verschiedene Möglichkeiten für den Zugriff auf seine Variablen. :-)
Veit D. schrieb:> // definieren des Datensatzes> struct Daten> {> byte d1;> float d2;> long d3;> const char text[20] {"Testausgabe"};> } daten, daten2;Veit D. schrieb:> Serial.println();> EEPROM.get(int(&daten2.d1), daten2.d1);> EEPROM.get(int(&daten2.d2), daten2.d2);> EEPROM.get(int(&daten2.d3), daten2.d3);> EEPROM.get(int(&daten2.text), daten2.text);
Das geht so nicht!
Denn daten und daten2 liegen im SRAM.
Deine Adressen sind damit falsch.
1
structDaten
2
{
3
byted1;
4
floatd2;
5
longd3;
6
constchartext[20]{"Testausgabe"};
7
}datenEEMEM,daten2;
So liegt daten im EEPROM und daten2 im SRAM
Veit D. schrieb:> Dabei mit der ermittelten Länge von bequem von struct> Anfang zum nächsten struct Anfang springt. Falls das jetzt irgendwie> verständlich rüberkommt.
Du kannst viele Variablen ins EEPROM legen.
Der Kompiler berechnet die Adresse immer richtig(wenn du selber keinen
Bock schießt)
z.B auch
float a EEMEM = 3.2; // Arduino erzeugt *.eep Datei
neben deiner Struktur.
Hallo,
vestehe. Der benötigte Syntax wird komplizierter. Leider steht das mit
dem EEMEM nicht in der Arduino Referenz. Kommt man da nicht besser man
schreibt und liest das Gesamte struct und greift dann normal wie immer
auf die Member zu? In daten2 stehen hinterher die Werte von daten.
1
#include<EEPROM.h>
2
3
// definieren des Datensatzes
4
structDaten
5
{
6
byted1{0};
7
floatd2{0};
8
longd3{0};
9
constchartext[20]{"abcyxz"};
10
}daten,daten2;
11
12
constbytelengthDaten=sizeof(Daten);
13
constunsignedintadresse{100};
14
15
voidsetup(){
16
17
Serial.begin(250000);
18
Serial.println(F("\nSTART #### ####"));
19
20
daten.d1=123;
21
daten.d2=1.23;
22
daten.d3=987654;
23
24
Serial.print(F("Länge vom struct: "));Serial.println(lengthDaten);
Arduino Fanboy D. schrieb:> Mit deinen Fantasien kann er nichts anfangen
Sie das Ganze doch nicht so ernst....natuerlich ist mir klar ,das es
Regeln gibt ansonsten waere ich ueberhaupt nicht in der Lage auch nur
eine einzige Zeile Code zu schreiben.
Angehaengt der komplette Code fuer die EEprom-Routine,so wie er zu 100%
funktioniert.
Bitte nun keine Diskussionen darueber,warum ich dies und das so
umstaendlich mache.Ich schreib meine Programme frei herunter und raeume
dann spaeter auf...Das Programm ist mittlerweile so komplex,dass ich um
einen FlowChart nicht herumkomme wenn ich noch nach Jahren wissen
moechte wie und wo ich was gemacht habe.
Hier 2 lausige Videos ,dass meinen Programmuell in der Praxis zeigt.War
nur fuer meinen Bruder gedacht damit er weiss was er geschenkt
bekommt....
Es handelt sich um den 20 Millionsten Spotwelder...die Welt kann nicht
genug davon haben.
https://www.youtube.com/watch?v=ajXF-H-lbus&feature=youtu.behttps://www.youtube.com/watch?v=hlXl4XwpfZM&feature=youtu.be
Toxic schrieb:> Angehängte Dateien:> EEprom_Reset.txt
Du darfst Dateien gerne mit der richtigen Extension hochladen.
Dann funktioniert beim Betrachter auch das Syntax Highlightning
Veit D. schrieb:> Der benötigte Syntax wird komplizierter.
Eigentlich nicht!
Du kannst bei jeder Variablen angeben, in welcher Sektion sie landen
soll.
Der Compiler erwartet per default alle Variablen in einer der SRAM
Sections.
Die kann er ohne Klimmzüge lesen und auch schreiben
unsignedresetcounterNOINIT;// diese liegt im RAM wird allerdings nicht automatisch initialisiert
5
// überlebt also auch einen Reset.
6
7
charsPROGMEM;// im Flash
8
chartEEMEM;// im EEPROM
Für PROGMEM und EEMEM Zugriffe musst du spezielle Zugriffsmethoden
verwenden.
Also die dir schon bekannte Syntax.
z.B. EEPROM.get() oder pgm_read_byte()
C kennt zusätzlich
char u __flash;
C++ leider nicht.
------------
Veit D. schrieb:> const byte lengthDaten = sizeof(Daten);> const unsigned int adresse {100};
Natürlich kannst du auch die Adressen händisch bestimmen/festlegen. Mit
dem Risiko auch mal einen schwer zu findenden Bock zu schießen.
Ins besondere wird das schwierig, wenn sich viele Adressberechnungen
über viele Dateien verteilen.
Veit D. schrieb:> Kommt man da nicht besser man> schreibt und liest das Gesamte struct
Kann man natürlich tun.
... wenn man nicht mit RAM geizen muss....
PS:
Habe mir eine EEPROM Klassen Erweiterung gebaut, die das etwas
Typesicherer macht, unterzubringen in EEPROM.h bei den schon vorhandenen
get und put
1
2
template<typenameT>T&get(T&ram,T&t){
3
returnget((int)ram,t);
4
}
5
6
template<typenameT>constT&put(T&ram,constT&t){
7
returnput((int)ram,t);
8
}
Nutzung:
1
floatimEepromaEEMEM;
2
floatimRamb;
3
EEPROM.get(a,b);// aus dem EEPROM ins Ram
4
EEPROM.put(a,b);// aus dem Ram ins EEPROM schreiben
Hallo,
nochmal zurück zum TO Eingangsproblem. Ich habe versucht das
nachzustellen.
Egal ob ich mit read/write oder put/get arbeite, klappt immer.
¯\_(ツ)_/¯
1
// https://www.mikrocontroller.net/topic/511826
2
3
#include<Streaming.h>
4
#include<EEPROM.h>
5
6
constbyteanz{3};
7
bytedaten1[anz]={112,134,156};
8
bytedaten2[anz];
9
10
constunsignedintstartAdresse{80};
11
constbyteabstand{4};
12
13
voidsetup()
14
{
15
unsignedintaddrBuffer{0};
16
17
Serial.begin(250000);
18
Serial.println(F("\nSTART #### ####"));
19
20
Serial.println(F("Testausgabe ..."));
21
for(auto&i:daten1)
22
{
23
Serial.println(i);
24
}
25
26
Serial.println(F("daten1 ins Eeprom schreiben ..."));
27
addrBuffer=startAdresse;
28
for(auto&i:daten1)
29
{
30
EEPROM.put(addrBuffer,i);
31
Serial<<"addr: "<<addrBuffer<<" "<<i<<endl;
32
addrBuffer+=abstand;
33
}
34
35
Serial.println(F("Eeprom lesen und in daten2 schreiben ..."));
36
addrBuffer=startAdresse;
37
for(auto&i:daten2)
38
{
39
EEPROM.get(addrBuffer,i);
40
Serial<<"addr: "<<addrBuffer<<" "<<i<<endl;
41
addrBuffer+=abstand;
42
}
43
44
Serial.println(F("daten1 ins Eeprom rückwärts schreiben ..."));
45
addrBuffer=startAdresse+abstand+abstand;
46
for(auto&i:daten1)
47
{
48
EEPROM.put(addrBuffer,i);
49
Serial<<"addr: "<<addrBuffer<<" "<<i<<endl;
50
addrBuffer-=abstand;
51
}
52
53
Serial.println(F("Eeprom vorwärts lesen und in daten2 schreiben ..."));
Veit D. schrieb:> addrBuffer
Genau das Gehampel meine ich, darauf sollte man verzichten!
Wenn du genau weißt, dass du klüger bist als der Compiler und nie Fehler
machst, dann ok...
Erst wenn du mir das garantieren kannst, empfehle ich es dir.
(aber keinem anderen)
Arduino Fanboy D. schrieb:> Veit D. schrieb:>> Kommt man da nicht besser man>> schreibt und liest das Gesamte struct> Kann man natürlich tun.> ... wenn man nicht mit RAM geizen muss....
Man muss immer eine Hand breit RAM unterm Hintern haben. :-)
Ich muss das mit dem EEMEM nochmal in Ruhe geistig durchdringen.
Danke für die neuen Hinweise und Erkenntnisse.
Toxic schrieb:> Angehaengt der komplette Code fuer die EEprom-Routine,so wie er zu 100%> funktioniert.
Unter komplett verstehe ich auch das Lesen des EEPROM. Aber dein Problem
lässt sich auch mit den vorhandenen Codefragmenten erklären, die in
einem wesentlichen Punkt von deinem konstruierten Beispiel abweichen. Da
hatten die Adressen ausreichend Abstand voneinander.
Beim aktuellen Code stehen nach der Schreibsequenz
EEPROM.put(27, 1); // preheat on/off => 0 = off
EEPROM.put(28, 12); // preheat_time in %
EEPROM.put(29, 12); // pulseduration
folgende Daten in den EEPROM Zellen:
27: 0x01 LSB put(27,1)
28: 0x0C LSB put(28,12) hat MSB put(27,1) überschrieben
29: 0x0C LSB put(29,12) hat MSB put(28,12) überschrieben
30: 0x00 MSB put(29,12) wird dann auch überschrieben
Das sieht für dich funktionierend aus, da du angenommen hast, daß nur 1
Byte geschrieben wird, und du deshalb von diesen Adressen jeweils nur 1
Byte lesen wirst (diesen Code hast du leider nicht geliefert).
Wenn nun die Schreibreihenfolge geändert wird
EEPROM.put(29, 12); // pulseduration
EEPROM.put(28, 12); // preheat_time in %
EEPROM.put(27, 1); // preheat on/off => 0 = off
stehen folgende Daten im EEPROM:
27: 0x01 LSB put(27,1)
28: 0x00 MSB put(27,1) hat LSB put(28,12) überschrieben
29: 0x00 MSB put(28,12) hat LSB put(29,12) überschrieben
30: 0x00 MSB put(29,12)
Wenn du jetzt die EEPROM Adressen 27..29 byteweise ausliest, stimmt der
Wert von Adresse 27 und Adresse 28 und 29 sind falsch.
> Es handelt sich um den 20 Millionsten Spotwelder...die Welt kann nicht> genug davon haben.
Dann hast du unter diesen Voraussetzungen Glück gehabt, daß deine
Hardware nicht in Rauch aufgegangen ist.
Arduino Fanboy D. schrieb:> PS:> Habe mir eine EEPROM Klassen Erweiterung gebaut, die das etwas> Typesicherer macht, unterzubringen in EEPROM.h bei den schon vorhandenen
Sorry, da habe ich einen alten experimentellen Stand erwischt..
Dieses ist der Aktuelle:
Hallo,
die Erklärung stimmt leider noch nicht. Geschrieben und gelesen wird ja
wirklich nur ein Byte. Nimm mal meinen Code davor und ändere den
'abstand' von 4 auf 1. Funktioniert immer noch.
Man darf sich nicht durcheinanderbringen lassen das die Adresse ein int
ist. Das spielt keine Rolle. An Adresse 200 passt ein Byte und an die
Adresse 201 passt das nächte Byte. Was intern mit dem Adresszähler
passiert sieht man nicht. Das ist wie bei Zeigern. Welche Adresse
reserviert wird kann einem egal sein. Es wird nur ausreichend Speicher
für den Datentyp reserviert auf den er zeigt.
Wenn der EEprom 1024 Bytes speichern kann. Dann sind 1024 'int' Adressen
hinterlegt. An jeder Adresse hat ein Byte Platz.
Hoffentlich habe ich das richtig erklärt ...
Der TO müßte wirklich einmal nachvollziehbaren Testcode zeigen der sein
Problem auch zeigt. Sonst wird das nichts.
Edit:
Arduino Fanboy: Danke fürs Update
Veit D. schrieb:> Geschrieben und gelesen wird ja> wirklich nur ein Byte.
EEPROM.put(29, 12);
12 ist ein int
put schreibt aus dem Grund 2 byte
Belegt also Adresse 29 und 30
Was vorher auf 30 stand, ist unwiederbringlich verloren
Ein einfaches sizeof(12) beweist dir das.
Hummel schrieb:> Dann hast du unter diesen Voraussetzungen Glück gehabt, daß deine> Hardware nicht in Rauch aufgegangen ist.
Bevor ich Software teure MosFets ansteuere teste ich per Oszi alle
Signale.Ich habe viel Zeit investiert fuer die ganze Displayansteuerung
und zig implementierten Optionen.
Ich habe zudem alle Parameter wie Impulslaenge etc waehrend in der
Software/Hardwarephase staendig veraendert und gecheckt.Irgendwie
scheine ich ein Hans im Glueck gewesen zu sein...
Wenn ich also bei Zahlenwerten bis 255 mit einem 2-Byte Ergebnis rechnen
muss,ist ein Ueberschreiben nicht zu vermeiden,da ich die Adressen
(nicht alle) direkt hintereinander ansiedelte.
Das von dir gezeigte Beispiel wuerde in meinem Falle beim Veraendern der
"pulseduration" den "preheat_time"-Wert durch ueberschreiben dessen
MSB's total veraendern und einen voellig absurden Wert live(!)auf dem
Display abgeben.In einem der Videos sieht man aber,dass dies trotz allem
nicht der Fall ist und auch die Osziwerte vollkommen mit den berechneten
Werten uebereinstimmen. What the fuck...
Nun voellig egal:
Der Fehler (auch wenn alles funktioniert...) liegt ganz offensichtlich
bei mir.Ein vermeintliches Byte ist eben kein Byte sondern ein
2-Byte-Wert.
Ich werde morgen,die EEpromadressen entsprechend abaendern ,nochmal
testen und mir vor allem klar machen warum ich soviel Glueck hatte,dass
waehrend der Testphasen nicht einmal Mist aufgetaucht ist.
Ein Dank an alle die hier gepostet und ihre Zeit investiert haben.
Hallo,
Ich glaube wir müssen alle einen Reset machen.
Das sizeof(12) zwei Byte ergibt bestreitet niemand.
Kann man jedoch nicht mit der Eeprom Lib blind vergleichen. In der
Arduino Referenz wird immer von Byte geredet. Schauen wir einmal genauer
nach in der Eeprom Header Datei.
https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/EEPROM/src/EEPROM.h
Ganz unten in der Klasse steht überall uint8_t für den eigentlichen
Wert.
Das erklärt zur Zeit für mich warum mein Testcode auch mit Adress
abstand 1 noch funktioniert.
Wenn ich morgen versuche bewußt int Werte hintereinander zu schreiben,
dann sollte wirklich Datenmüll rauskommen.
Für heute ist bei mir erstmal Schluss.
Toxic schrieb:> Ich werde morgen,die EEpromadressen entsprechend abaendern
Und ich rate dir (nochmal), den Compiler die Adressen und
Größenberechnungen machen zu lassen.
Veit D. schrieb:> Arduino Referenz wird immer von Byte geredet.
Nöö...
https://www.arduino.cc/en/Reference/EEPROMPut> data: the data to write, can be a primitive type> (eg. float) or a custom struct> Kann man jedoch nicht mit der Eeprom Lib blind vergleichen.
Doch!
Wenn man in die Lib schaut, sieht man, dass sizeof() verwendet wird.
Toxic schrieb:> Wenn ich also bei Zahlenwerten bis 255 mit einem 2-Byte Ergebnis rechnen> muss,ist ein Ueberschreiben nicht zu vermeiden,da ich die Adressen> (nicht alle) direkt hintereinander ansiedelte.> Das von dir gezeigte Beispiel wuerde in meinem Falle beim Veraendern der> "pulseduration" den "preheat_time"-Wert durch ueberschreiben dessen> MSB's total veraendern und einen voellig absurden Wert live(!)auf dem> Display abgeben.In einem der Videos sieht man aber,dass dies trotz allem> nicht der Fall ist und auch die Osziwerte vollkommen mit den berechneten> Werten uebereinstimmen. What the fuck...
Da du ja in deinem gezeigten Code fortlaufend aufsteigende Adressen
beschrieben hast, passiert trotz Überschreiben von EEPROM Zellen nichts
wenn du jeweils nur (wie von mir angenommen) nur das LSB ausliest und
anzeigst. Wenn du dann in deinem Code 1-Byte Variable benutzt um
Einstellungen zu verändern, dann passiert auch kein weiteres
überschreiben. Nur wenn du dem 'put' einen direkten Zahlenwert
übergibst, wird implizit ein Integer angenommen.
Beispiel:
uint8_t preheadTime;
EEPROM.get(28,preheatTime);
preheatTime++;
EEPROM.put(28,preheatTime); // hier wird nur 1 Byte geschrieben
EEPROM.put(28,155); // hier werden 2 Bytes geschrieben
> Nun voellig egal:> Der Fehler (auch wenn alles funktioniert...) liegt ganz offensichtlich> bei mir.Ein vermeintliches Byte ist eben kein Byte sondern ein> 2-Byte-Wert.> Ich werde morgen,die EEpromadressen entsprechend abaendern ,nochmal> testen und mir vor allem klar machen warum ich soviel Glueck hatte,dass> waehrend der Testphasen nicht einmal Mist aufgetaucht ist.
Im Prinzip brauchst du die Adressen nicht ändern, du musst nur dem
Compiler mitteilen, daß er ein uint8_t schreiben soll.
Hallo,
wenn man den Thread so liest kann man den Eindruck gewinnen die EEprom
Lib könnte nur mit int umgehen, was ja nicht der Fall ist. Deswegen
zeigte ich auf die Klasse wo man sieht das read/write nur mit Bytes
umgeht. Das put/get alles verdaut ist auch klar, wurde aber nicht gleich
ersichtlich. Das mein Testcode nicht das zeigt was der TO zeigte ist mir
nun auch klar, da ich explizit ein Byte Array verwendet habe und es
deswegen keine Rolle spielte ob ich read/write odder put/get verwende.
Der TO hat nur Literale eingesetzt die zu int formierten. Wenn das
Antworten später noch nicht so ankam wie gedacht sollte man den
geneigten Leser nochmal an der Stelle abholen wo er falsch abgebogen
ist. Dann verkürzt sich auch die Threadlänge. Man sollte aufeinander
zugehen, sonst redet man zu lange aneinander vorbei.
Aber das wurde ja nun alles zum Guten erklärt. Ende gut alles gut. :-)
Veit D. schrieb:> wenn man den Thread so liest kann man den Eindruck gewinnen die EEprom> Lib könnte nur mit int umgehen, was ja nicht der Fall ist
Wenn man nur auf sein Herz hört und die geschriebenen Worte
geflissentlich ignoriert, ja, dann könnte man das meinen.
Andere könnten auch meinen, dass die EEPROM Lib nur Byte verarbeiten
kann.
Was genauso falsch ist.
Richtig ist: put schreibt das, was man ihm vorwirft!
Es liegt in der Verantwortung des Programmierers, das jeweilige
Verhalten von put zu bestimmen.
Was dann dazu führt, dass man ihm auch byte vorwerfen muss, wenn man
byte speichern will.
Veit D. schrieb:> Das put/get alles verdaut ist auch klar, wurde aber nicht gleich> ersichtlich.
Wenn man die Doku ignoriert, dann ist das nicht offensichtlich.
Veit D. schrieb:> Das mein Testcode nicht das zeigt was der TO zeigte ist mir> nun auch klar, da ich explizit ein Byte Array verwendet habe und es> deswegen keine Rolle spielte ob ich read/write odder put/get verwende.
So ist es...
Und so, oder so ähnlich kommt es, wenn ein Fragesteller Fantasiecode
zeigt, welcher NICHT das Problem überprüfbar abbildet.
Veit D. schrieb:> Der TO hat nur Literale eingesetzt die zu int formierten. Wenn das> Antworten später noch nicht so ankam wie gedacht sollte man den> geneigten Leser nochmal an der Stelle abholen wo er falsch abgebogen> ist.
Eigentlich eine gute Idee...
Aber wenn nach einem gefühlten Dutzend Erklärungen, von mehreren
Personen, der Groschen nicht fallen will, die irrige Vorstellung nicht
aus dem Kopf will, dann ist es halt schwierig.
Dabei sollte es in der Programmiererwelt schon bekannt sein, dass sich
logische Fehler gerne bis zum Tag der Inbetriebnahme/Auslieferung
verstecken.
Und dann mit roher Gewalt das ganze Projekt in die Tonne befördern.
Toxic schrieb:> Ich will fuer meine EEpromdaten spaeter eine "structure" anlegen.
Hier ist der logische Fehler, zumindest einer davon.
Sowas tut man nicht "später"!
Sondern man legt eigentlich erst die Datenstrukturen an, oder fest, und
baut dann den Code dazu, welcher auf den Strukturen reitet.
Veit D. schrieb:> Dann verkürzt sich auch die Threadlänge.
Irrtum begehen
Irrtum erklären
Irrtum einsehen
Irrtum beseitigen
Das steckt sich ein wenig, ins besondere, wenn da noch ein fulminantes
Beharrungsvermögen dazu kommt.
Veit D. schrieb:> Man sollte aufeinander> zugehen, sonst redet man zu lange aneinander vorbei.
Dazu gehören mindestens 2, auch gerne mehr.
Veit D. schrieb:> Aber das wurde ja nun alles zum Guten erklärt.
Das warten wir mal ab, was die "Einsicht", so an Früchten trägt.
----
Irgendwie scheint es mir, du wolltest die Hilfe hier im Thread
kritisieren...
Ok, kannst du machen...
Aus meiner Sicht ist dieses ein erstaunlich friedlicher Arduino Thread.
Keinerlei Bösartigkeiten.
Hallo,
> Aus meiner Sicht ist dieses ein erstaunlich friedlicher Arduino Thread.
Das soll auch so bleiben.
Vielleicht habe ich auch zwischendurch zur eigenen Verwirrung
beigetragen. Da will ich mich nicht ausnehmen, hinsichtlich des kleinen
Kommunikations- bzw. Verständnisproblems. War nicht böse gemeint.
Im kann im Moment noch kein Feedback(keine Zeit...) geben um euch den
fatalen von mir selbst produzierten Bockmist nochmal zu bestaetigen.
Die irrige Annahme,dass Werte =< 255 nur ein Byte im EEprom in Anspruch
nehmen hat mich in die Bredouille gebracht.So ein Mist aber auch.Ich war
so felsenfest davon ueberzeugt,dass es mir nie in den Sinn kam,dass da
ein Problem sein koennte.
Ich habe eure letzten Postings gelesen und werde mir den einen oder
anderen Tip zu Gemuete fuehren.
Ich hatte eigentlich nicht vor im Forum nachzufragen,da
(zufaelliegerweise)
mein Projekt funktionierte und ich es schon auf's Abstellgleis geschoben
hatte.
Trotzdem hatte es mich gewurmt,dass ich dieses seltsame Verhalten nicht
nachvollziehen konnte.
OK - ich steh jetzt natuerlich da wie eine Dumpfbacke und ich koennte
mich auch selbst dafuer ohrfeigen.Aber immerhin hab ich dank eurer Hilfe
einen bei mir im Gehirn eingebrannten Denkfehler eliminieren koennen und
dafuer gibt es ein 👍
Toxic schrieb:> OK - ich steh jetzt natuerlich da wie eine Dumpfbacke und ich koennte> mich auch selbst dafuer ohrfeigen.Aber immerhin hab ich dank eurer Hilfe> einen bei mir im Gehirn eingebrannten Denkfehler eliminieren koennen und> dafuer gibt es ein 👍
Dazu kann ich nur eins sagen:
> Irren ist menschlich> Im Irrtum verharren, ist Dummheit
Also, mir scheint, du bist auf dem richtigen Weg!
Hallo,
ich hätte noch eine Zusatzfrage. Wenn ich mit write ein int schreibe,
warum gibts dann beim kompilieren keine einzige Warnung? Es wird doch
sonst auch immer alles angemeckert was nicht passt, overflow warning
o.ä.. Das verstehe ich im Moment nicht.
Hallo,
aja okay, wegen dem impiliziten cast macht der das einfach und gut ist.
Das mit der {} Klammer ist ein guter Tipp. Mache ich bis jetzt nur beim
initialisieren.
Dann kann man nicht nur bei einer Variablen Initialisierung den Datentyp
prüfen lassen, sondern immer und überall auch bei deren Übergabe. Das
ist ja cool. Danke.