Hallo,
ich versuche, mit einem Arduinoprogramm einige Zahlen in ein I2C-EEPROM
zu schreiben und sie später wieder auszulesen. Dies funktioniert ganz
gut, bis auf den ersten der sechs Werte, der einfach entweder nicht
geschrieben oder nicht gelesen wird.
Im ersten Code-Schnipsel sieht man, wie die Daten (die Zeit und zwei
Temperaturwerte) in das EEPROM geschrieben werden sollen:
Für das Auslesen ist ein anderes Programm (oder Sketch, wie das wohl bei
Arduino heißt,) vorhanden:
1
for (eepromadresse = 0; eepromadresse < 5000; eepromadresse++){
2
3
byte1 = (liesEEPROM(eepromadresse)); // highByte von Time
4
eepromadresse++;
5
byte2 = (liesEEPROM(eepromadresse)); // lowByte von Time
6
eepromadresse++;
7
byte3 = (liesEEPROM(eepromadresse)); // HighByte von Temp1
8
eepromadresse++;
9
byte4 = (liesEEPROM(eepromadresse)); // LowByte von Temp1
10
eepromadresse++;
11
byte5 = (liesEEPROM(eepromadresse)); // HighByte von Temp2
12
eepromadresse++;
13
byte6 = (liesEEPROM(eepromadresse)); // LowByte von Temp2
14
15
Serial.print(eepromadresse);
16
17
Serial.print("\t");
18
Serial.print(byte1);
19
Serial.print("\t");
20
Serial.print(byte2);
21
Serial.print("\t");
22
Serial.print(byte1 << 8 | byte2);
23
Serial.print("\t");
24
25
Serial.print(byte3);
26
Serial.print("\t");
27
Serial.print(byte4);
28
Serial.print("\t");
29
Serial.print(byte3 << 8 | byte4);
30
Serial.print("\t");
31
32
Serial.print(byte5);
33
Serial.print("\t");
34
Serial.print(byte6);
35
Serial.print("\t");
36
Serial.println(byte5 << 8 | byte6);
37
} // Ende for
Das mir unverständliche Ergebnis ist im folgenden Abschnitt zu sehen:
1
Adresse Zeit Temp.
2
5 0 210 210 1 144 400 22 255 5887
3
11 0 210 210 1 162 418 22 193 5825
4
17 0 206 206 1 56 312 22 199 5831
5
23 0 174 174 1 69 325 22 186 5818
6
29 0 56 56 1 81 337 22 186 5818
7
35 0 217 217 1 87 343 22 186 5818
8
41 0 53 53 1 100 356 22 243 5875
9
47 0 221 221 1 131 387 22 243 5875
10
53 0 130 130 1 131 387 22 249 5881
In der zweiten Spalte sollte immer eine 4 stehen (aus dem Dummy 1234
für die Variable Time), aber ich schaffe es einfach nicht, in die erste
der EEPROM-Zellen das HighByte des ersten Wertes hineinzubekommen.
Manchmal gelingt mir es zwar, aber der Code sieht dann genau so aus,
sodaß ich nicht erkennen kann, woran es liegt.
Es wäre nett, wenn einer der Experten mal eine Blick auf den Code
werfen könnte und mir des Rätsels Lösung nennen würde. Da ich nicht
weiß, ob es beim Schreiben oder Lesen daneben geht, habe ich beide
Programmteile beigefügt - und ordentlich gekürzt, damit es nicht zu lang
zum Lesen wird.
Da ich schier am Verzweifeln bin, würde ich mich über einen Hinweis sehr
freuen.
VG
Alexander
Die Zeilen sehen alle OK aus, wie schon gesagt wurde, der weggelassene
Code wäre interessant. Erste/spontane Vermutung: Du hast irgendwo bei
dir statt ein >= oder <= ein > bzw. <. Ist aber nur geraten.
Einige Anmerkungen aber auch mal grundsätzlich:
Man kann ein EEPROM natürlich Byte für Byte beschreiben, sehr sinnvoll
ist das aber nicht. Eigentlich haben EEPROMs Funktionen mit denen sich
auch gleich eine ganze Batterie an Bytes drauf schreiben lassen. Das
Maximum an Bytes, dass man "gleichzeitig" schreiben lassen kann nennt
man einen Pagewrite.
Einige EEPROMs haben auch einen Adress-Auto-Increment, d.h. man muss nur
einmal die Adresse setzen bei der man starten will und kann dann ein
Byte nach dem anderen schicken, die Adresse wird automatisch
incrementiert.
Hier mal ein Beispiel wie eine Bibliothek zu sowas aussehen kann (hier
für ein 24LC1025 EEPROM von Mikrochip, da ich die "kleineren" nicht habe
weiß ich nicht wie gut die damit laufen, sollten aber auch problemlos
damit funktionieren)
ok, hier schicke ich die beiden kompletten (aber noch unfertigen)
Programme. Ich habe allen Kram drin gelassen, nichts gekürzt.
Nr 1, für das Schreiben:
Edit:
Das Dilemma scheint mit der im Programm als Brennerabfrage bezeichneten
Passage bzw. der if- oder while- Schleife zusammenzuhängen. Deaktiviert
man sie, wird es besser. Allerdings kann ich nicht nachvollziehen,
weshalb.
VG
Alexander
Sieht mir erstmal zu komplex aus um mich da reinzufuchsen und ich
schätze mal, anderen geht es ähnlich.
Ich empfehle dir: Reduziere den Code so weit dass er nicht mit Elementen
beladen ist, die mit dem Problem nichts zu tun haben, d.h. baue ein
Beispiel-Programm, dass den Fehler zeigt. Das ist natürlich etwas
aufwand, es kann aber durchaus dabei passieren, dass du dabei den Fehler
selber findest.
Was mir auffällt: Bei "schreibeEEPROM()" hast du die Speicheradresse als
int deklariert obwohl es ein uint16_t ist. Das ist auch wenig schön.
Hier solltest du mehr eine rote Linie in deinen Code rein bekommen,
sprich ordentlicher arbeiten. Es ist sicher von Vorteil wenn der
Programmierstyle gleich ist, so sieht man insbesondere bei ähnlichen
Funktionen direkt die Unterschiede. Das wird bei dir schon schwer, da du
einmal den Parameter für die Speicheradresse eepromadress nennst und
einmal adresse.
M. K. schrieb:
Mache ich, also alles raus, was nichts mit dem Problem zu tun hat.
> Was mir auffällt: Bei "schreibeEEPROM()" hast du die Speicheradresse als> int deklariert obwohl es ein uint16_t ist.
Bereitet mir etwas Schwierigkeiten, da ja in Arduino für Duo das int aus
zwei Bytes besteht. Ich bin mir auch nicht sicher, ob die Zerlegung von
int in HighByte und Lowbyte so zulässig ist, wie ich es gemacht habe
(funktioniert aber).
Mit den Adressen habe ich auch long bzw. unsigned int probiert, hat aber
nichts geändert.
VG
Alexander
Alexander S. schrieb:> Bereitet mir etwas Schwierigkeiten, da ja in Arduino für Duo das int aus> zwei Bytes besteht. Ich bin mir auch nicht sicher, ob die Zerlegung von> int in HighByte und Lowbyte so zulässig ist, wie ich es gemacht habe> (funktioniert aber).
Würde auch sagen, dass das so zulässig ist, ist halt nur wegen der
Lesbarkeit etwas schwierig.
Hier mal ein Beispiel wie ich die Funktionen zum Lesen und Schreiben
aufgebaut hätte (ich kenne allerdings die Wire-Library nicht, daher sind
die Funktionen nur "geschätzt" von mir eingesetzt)
EEPROM lesen
1
uint8_treadByteFromEEPROM(uint16_tadressToRead){
2
uint8_tdata=0xff;
3
Wire.beginTransmission(I2CADRESSE);// Ich schätze mal, das sendet die Startcondition
4
Wire.write((uint8_t)adressToRead>>8);
5
Wire.write((uint8_t)adressToRead&0xff);
6
Wire.beginTransmission(I2CADRESSE|1);// vergleiche Datenblatt EEPROM, wahrscheinlich muss das LSB der I2C-Adresse 1 sein um das EEPROM zum Senden zu bewegen, das wäre zumindest nicht unüblich.
7
data=Wire.read();// Vermute read liest das Byte vom i2c-Bus, wie gibt man ACK oder NACK vor? Wahrscheinlich kann man da noch einen Parameter mit übergeben, oder?
8
Wire.endTransmission();// Hier, vermute ich, wird die Stopcondition gesendet