Hallo,
mir fällt partout nicht ein, woher bei dem Auslesen eines I2C-EEPROMs
der Offset herkommt. Die Ausgabe des unten angefügten Programms beginnt
ab einer eepromadresse von ca 5600, obwohl als Startwert säuberlich eine
Null steht.
Ob vielleicht einer der Experten mal einen Blick auf das Programm werfen
könnte? Ich habe schon an allen Stellen gedreht, aber ich komme einfach
nicht weiter.
Vielen Dank!
VG
Egon
1
// i2c_eeprom_lesen_reduz-150807
2
// Ausgabe startet erst bei ca 5600
3
4
#include <EEPROM.h>
5
#include <Wire.h>
6
const int I2CADRESSE = 0x57; // I2C-Adresse des EEPROM, alle Adress-Schalter auf low (und die Pullups auch)
7
8
void setup()
9
{
10
Wire.begin(); // join i2c bus (address optional for master)
11
Serial.begin(9600); // start serial for output
12
unsigned int eepromaddresse;
13
byte wert1, wert2, wert;
14
15
for ( unsigned int eepromaddresse = 0; eepromaddresse < 8000; eepromaddresse++)
Hallo m.n.
geht leider auch nicht besser; die Ausgabe fängt wieder erst bei ca 6000
an und die Ausgaben für den Inhalt des EEPROMs sind allesamt = 0.
VG
Egon
m.n. schrieb:> Egon M. schrieb:>> Auslesen eines I2C-EEPROMs>> Welcher Typ, wie beschaltet?
Auf dem Chip steht 24LC256 und das Motorolasymbol. Montiert ist es
mitsamt den Anschlußteilen auf einer kleinen Platine von DF Robot.
Angeschlossen ist es per I2C, also + / - SDA u. SCL.
Peter D. schrieb:> Beide Pullups (1,8k..10k) angeschlossen?
Ich selbst habe keine Pullups angeschlossen, allerdings sind auf der
Platine EEPROM module von DF Robots fünf SMD-Teile zu sehen, von denen
man annehmen könnte, sie seien welche.
>> Hier mal meine Lib:>> Beitrag "Re: I2C Problem mit Acknowledge Polling"
Das muß ich mir später mal genauer ansehen. Schön wäre es, wenn ich dem
vielleicht ungenügenden libs von Arduino mit ein paar delay's aufhelfen
könnte, andernfalls müßte ich den I2C-Zugriff wieder wie früher manuell
programmieren.
Vielleicht kommt aus dem parallelen Thread noch eine mundfertige Lösung
heraus.
Was mich wundert, ist, daß es bei mir bisher immer gut gegangen ist, ich
benutze ein ähnliches Programm schon seit 2-3 Jahren ohne Probleme.
Egon M. schrieb:> wert = wert1 << 8 | wert2;
Hi,
kann so nicht funktionieren. Alle Variablen sind byte was soll nach
einen <<8 in wert noch stehen?
wert sollte mindestens integer sein.
Gruß
Frank
Frank L. schrieb:> wert sollte mindestens integer sein.
Stimmt!
Das gezeigte Programm ist ein Schnipsel aus einem längeren Programm, das
ich reduziert habe, um das Posting auf das Wichtigste zu beschränken.
Und zum Schluß habe ich darin noch herumfuhrwerkt, sodaß die im bisher
funktionierenden, kompletten Programm vorhandene globale Definition wohl
unter die Räder gekommen ist.
Übrigens, zu dem generellen I2C-Problem hier, ich habe gestern auf die
schnelle ein paar delay(10) eingefügt - und es wwird besser!
VG
Egon
Egon Mueller schrieb:> Übrigens, zu dem generellen I2C-Problem hier, ich habe gestern auf die> schnelle ein paar delay(10) eingefügt - und es wwird besser!
Du könntest auch wild verteilt noch einige Kondensatoren dazulöten.
Vielleicht wird es noch besser, aber es wird niemals gut!
Also lass das blöde delay()-Gemache und such den richtigen Fehler.
Warum steht denn Dein Code in setup() und loop() ist leer?
Ich bin jetzt nicht der Arduino Experte, aber die paar Beispiele,
die ich mir angesehen habe, hatten den Code in loop().
Wer weiss, was Arduino beim Start von loop() so alles macht ;-)
Tom schrieb:> Warum steht denn Dein Code in setup() und loop() ist leer?> Ich bin jetzt nicht der Arduino Experte, aber die paar Beispiele,> die ich mir angesehen habe, hatten den Code in loop().> Wer weiss, was Arduino beim Start von loop() so alles macht ;-)
Es soll nur ein einziges mal ablaufen, dann kopiere ich sofort die
Ausgabe vom Terminal und Schluß.
Du gibst EepromAdresee -3 aus. Fängst bei 0 im unsigned int an, dürfte
also 65532 ausgeben.
Die Adresse unten zum Schreiben schiebst du 8 Bits nach rechts. Das
sollte verlässlich aus deiner 57 eine 0 machen.
Du meinst vielleicht eher einen Shift nach links für die Schreibadresse,
also <<1 anstatt >>8?
Edit: Mist, EepromAdresse und I2CAdresse verwchselt. Das ist also ok.
Ich vermute, es ist schlicht das "-3", und dann Fehler bei der
Übertragung an den Terminal, dass du als Adresse 5532 siehst?
m.n. schrieb:> Egon Mueller schrieb:>> Übrigens, zu dem generellen I2C-Problem hier, ich habe gestern auf die>> schnelle ein paar delay(10) eingefügt - und es wwird besser!>> Du könntest auch wild verteilt noch einige Kondensatoren dazulöten.> Vielleicht wird es noch besser, aber es wird niemals gut!>> Also lass das blöde delay()-Gemache und such den richtigen Fehler.
Die Wirkung der delay() sieht wenigstens nach einem Hinweis aus, wo man
weitersuchen könnte. Allerdings kommt man damit dem Offsetproblem wohl
nicht näher.
mfg
Egon
Egon M. schrieb:> for ( unsigned int eepromaddresse = 0; eepromaddresse < 8000;> eepromaddresse++)> {> wert1 = liesEEPROM(I2CADRESSE, eepromaddresse);> eepromaddresse++;> wert2 = liesEEPROM(I2CADRESSE, eepromaddresse);> eepromaddresse++;>> wert = wert1 << 8 | wert2;>> Serial.print(eepromaddresse -3); // -3 heißt: anfängliche> EEPROM-Adresse
Wenn Du ausgehend von Adresse = 0 zweimal 1 drauf addierst, dann landest
Du bei Adresse = 2. Wenn Du davon dann 3 abziehst, landest Du bei 65535.
Okay, grade gesehen, eepromaddresse ist unsigned int, gibt also keinen
negativen Wert beim subtrahieren von 3. Vielleicht verstümmelt die
Serial.Print-Routine ja den Wert.
Egon M. schrieb:> Wire.requestFrom(I2CADRESSE, 1);> if (Wire.available())> datenbyte = Wire.read();
Was passiert, wenn das if false ist? Dann hast du eine Anfrage gestellt,
einen Wert aus dem EEPROM auszulesen, holst ihn aber nicht ab? Wie
verhält sich der EEPROM dann?
Bauchgefühl sagt eher
while (!Wire.available());
datenbyte = Wire.read();
Könnte erklären, wieso Delays helfen.
Mit der Adresse würde ich, wie Host, auf die Serial.print() tippen.
(Kenne die Arduino-Libs nicht und bin vielleicht deshalb skeptisch).
Gibt die auch den falschen Wert aus, wenn du die -3 weglässt?
Oder Zählvariable in der Schleife mitlaufen lassen -> wird die Schleife
tatsächlich 2666 mal durchlaufen?
Und dass eepromadresse in der setup() doppelt deklariert ist, schiebe
ich mal auf das Umkopieren, richtig? (sollte aber sicher fallen und kein
Problem darstellen)
Mit den Dreierschritten bzw. eepromadresse -3 ist das einfach: Zum
Speichern der Meßwerte werden vier Speicherzellen benötigt.
Beim Auslesen der Meßwerte werden diese vier Werte, aus denen nach
Umrechnung zwei geworden sind, einer einzigen Eepromadresse zugeordnet,
damit sie in einem Diagramm dargestellt werden können. Gewählt wurde die
erste der vier Adressen, also Eepromadresse -3. Mehr steckt da nicht
dahinter.
Wegen der anderen Sachen muß ich demnächst mal in die Arduino-libs
hineinschauen.
VG
Egon
Welchen Speicherbaustein verwendest du genau, dass man mal aufs
Datenblatt gucken kann? Die SPI-Eproms, die ich kenne, machen in der
Standardkonfiguration ein Auto-Inkrement der Adresse.
Edit: Grade gesehen, 24LC256,
http://ww1.microchip.com/downloads/en/devicedoc/21203N.pdf - S. 11,
Sequential Read. Da steht auch was, das man zwei Bytes lesen sollte, da
das erste Rückgabe-Byte ein Control-Byte ist? Hab mir das nicht genauer
angesehen, würde aber erstmal das Lupfen der Augenbraue bewirken.
Nach wie vor kommt das "ungefähr 5600 als Startadresse" (vielleicht mal
etwas präziser werden könnte helfen!) recht gut mit dem abgeschnittenen
65532 -> 5532 (respektive 65535->5535) hin. Wäre an dieser Stelle jedoch
ein reiner Anzeigefehler, da die -3 nur beim PRINT erscheinen.
Der Code passt mit dieser Beschreibung nicht zusammen. Klassisch würde
man 4 Bytes lesen, du liest und adressierst jedoch 2! Zusammen mit dem
Control-Byte kommt da dann Quark zusammen. (Obwohl du das noch gar nicht
moniert hast, sondern nur deine angezigte Adresse eigentlich falsch ist,
mit eingegrenzter Ursache.) Ohne komische Verrenkungen zur Anzeige mit
"-3" wäre auch gut. Und dann das saubere Warten auf die Rückgabe mit dem
while() anstatt if(). Irgendwie ist da ein Durcheinander.
Du lässt Dir die Werte nach dem Schema
1 2 4 5 7 8 10 11 13 14 16 17 19 20 ...
ausgeben. Das hat weder mit 2 noch mit 4 zu tun.
In einem Schleifendurchlauf wird eepromaddresse 3x inkrementiert.
Was Du mit Deinem -3 da hast, ist nicht das Problem, sondern nur eine
weitere Baustelle.
Gruß
Jobst
Egon Mueller schrieb:> Mit den Dreierschritten bzw. eepromadresse -3 ist das einfach: Zum> Speichern der Meßwerte werden vier Speicherzellen benötigt.> Beim Auslesen der Meßwerte werden diese vier Werte, aus denen nach> Umrechnung zwei geworden sind, einer einzigen Eepromadresse zugeordnet,> damit sie in einem Diagramm dargestellt werden können.
Das ist doch kompletter Schwachsinn.
Wenn vier Speicherzellen zum Speichern benötigt werden, muß man erstens
auch tatsächlich genau vier schreiben und später auch genau vier lesen.
Merkst du was? Eine drei kommt da sowas von absolut garnicht vor...
Wenn man nun diese vier Speicherzellen zusammenfassen will, dann ist ihr
gemeinsames Merkmal die EEPROM-Addresse der ersten Zelle (das ist wohl
das, was du versucht hast), dann ist aber nur jede vierte (und nicht
dritte und schon garnicht jede) EEPROM-Addresse hierfür gültig.
Kurzfassung: Du solltest einfach C lernen. Und zwar, bevor du es
verwendest...
c-hater schrieb:> Wenn vier Speicherzellen zum Speichern benötigt werden, muß man erstens> auch tatsächlich genau vier schreiben und später auch genau vier lesen.> Merkst du was? Eine drei kommt da sowas von absolut garnicht vor...
auch wenn du c nicht magst, ich mag deine klaren Worte.
Peter D. schrieb:> Woher weißt Du überhaupt, daß der Fehler erst beim Lesen passiert?> Hast Du den EEPROM vor dem Einlöten programmiert?
Ich habe es nicht eingelötet, es war ein Baustein, fix und fertig von
DF-Robot geliefert und dazu habe ich die unter Arduino verfügbare lib
verwendet (im Pgm. an #include <Wire.h> zu sehen). Da das Programm seit
mindestens zwei Jahren problemlos die beiden Meßwerte und eine
EEPROM-Adresse für die x-Achse (egal, welche, hauptsache immer z.B. die
erste) ausgegeben hat, hatte ich bisher keinen Grund, heinzuschauen.
Nachdem es nun nicht mehr funktioniert und nachdem, was ihr hier
schreibt, sollte ich wohl die libs genauer betrachten und möglicherweise
die I2C-Ansprache wieder von Hand programmieren, wie ich das früher bei
nackten ATmegas tun mußte. Aber Arduino ist halt so schön bequem, da
spart man sich viel Arbeit.
VG
Egon
Joachim B. schrieb:> c-hater schrieb:>> Wenn vier Speicherzellen zum Speichern benötigt werden, muß man erstens>> auch tatsächlich genau vier schreiben und später auch genau vier lesen.>> Merkst du was? Eine drei kommt da sowas von absolut garnicht vor...>
So?
Angenommen, ein Speichervorgang beginne bei 100:
erstes Byte Zelle 100
zweites Byte Zelle 101
drittes Byte Zelle 102
viertes Byte Zelle 103.
Ausgabe der Adresse für das erste Byte 103 - 3 = 100.
Mal abgesehen von einem Controlbyte, von dem dekoepi geschrieben hat,
das ich ich kenne und daher nie berücksichtigt habe.
Frank L. schrieb:>> wert = wert1 << 8 | wert2;>> Hi,>> kann so nicht funktionieren. Alle Variablen sind byte was soll nach> einen <<8 in wert noch stehen?
Du solltest Dir dringend die Regeln für integer promotion nochmal
durchlesen!
Egon M. schrieb:> Angenommen, ein Speichervorgang beginne bei 100:> erstes Byte Zelle 100> zweites Byte Zelle 101> drittes Byte Zelle 102> viertes Byte Zelle 103.>> Ausgabe der Adresse für das erste Byte 103 - 3 = 100.
Und was glaubst Du, wie es weiter geht?
Dein Code macht vermutlich nicht das, was Du glaubst/möchtest ...
(Ganz sicher dann nicht, wenn zwei Datensätze 2 oder 4 Bytes auseinander
liegen)
Gruß
Jobst
Peter D. schrieb:> Woher weißt Du überhaupt, daß der Fehler erst beim Lesen passiert?>
Weiß ich nicht, aber ich finde die Schreiberei plausibel. Hier ist der
Ausschnitt, wo in das EEPROM geschrieben wird:
1
int Templuft = int (Lufttemp); // Lufttemp ist float, muß zu int werden (umbenannt in Templuft)
2
highluft = highByte(Templuft); // damit es in low- und highbyte zerlegt werden kann (wg. des EEPROMs)
Jobst M. schrieb:> Egon M. schrieb:>> Angenommen, ein Speichervorgang beginne bei 100:>> erstes Byte Zelle 100>> zweites Byte Zelle 101>> drittes Byte Zelle 102>> viertes Byte Zelle 103.>>>> Ausgabe der Adresse für das erste Byte 103 - 3 = 100.>> Und was glaubst Du, wie es weiter geht?
Ich hatte gehofft,beim nächsten Schreibzugriff
erstes Byte Zelle 104
zweites Byte Zelle 105
drittes Byte Zelle 106
viertes Byte Zelle 107.
Verwendete Adresse 107 -3 = 104
Was spricht dagegen, welchen Abgrund gibt hier nun schon wieder?
Gruß
Egon
Markus F. schrieb:> Frank L. schrieb:>>> wert = wert1 << 8 | wert2;>>>> Hi,>>>> kann so nicht funktionieren. Alle Variablen sind byte was soll nach>> einen <<8 in wert noch stehen?>> Du solltest Dir dringend die Regeln für integer promotion nochmal> durchlesen!
Hi Markus,
meinst Du mich? Das wert1 << 8 ist lt. Arduino-Manual auch für
byte-Variablen zulässig, und wert ist tatsächlich int, auch wenn es in
dem gezeigten Programmschnipsel vielleicht untergegangen sein könnte.
Gruß
Egon
Egon M. schrieb:> schreibEEPROM(eepromadresse,highluft);> eepromadresse++;> schreibEEPROM(eepromadresse,lowluft);> eepromadresse++;
Im Idealfall (keinerlei Fehlerbehandlung!!!) zwei Bytes geschrieben, OK.
Aber es sollten doch angeblich vier pro Datensatz sein...
Und immer noch weit und breit keine Drei zu sehen...
Egon M. schrieb:> Was spricht dagegen, welchen Abgrund gibt hier nun schon wieder?
Du zählst dafür nicht genug!
Vielleicht solltest Du Dir einfach mal die Adressen, anstelle der
Inhalte ausgeben lassen!
Gruß
Jobst
Egon M. schrieb:> Markus F. schrieb:>> Frank L. schrieb:>>>> wert = wert1 << 8 | wert2;>>>>>> Hi,>>>>>> kann so nicht funktionieren. Alle Variablen sind byte was soll nach>>> einen <<8 in wert noch stehen?>>>> Du solltest Dir dringend die Regeln für integer promotion nochmal>> durchlesen!>> Hi Markus,> meinst Du mich? Das wert1 << 8 ist lt. Arduino-Manual auch für> byte-Variablen zulässig, und wert ist tatsächlich int, auch wenn es in> dem gezeigten Programmschnipsel vielleicht untergegangen sein könnte.>> Gruß> Egon
Hallo Egon,
nein, ich mein' nicht dich. Frank L. (und genau den mein' ich) hat oben
geschrieben, daß dein Code an der Stelle so nicht funktionieren würde,
was natürlich - wie Du schon richtig bemerkt hast, aber mit Arduino nix
zu tun hat - falsch ist.
Gruß,
Markus
Hallo,
wenigstens e i n Problem ist gelöst, das mit dem Offset. Ich wage kaum
zu schreiben, welch primitiven Fehler das war:
wenn das Programm hochgeladen ist, muß man im Arduino-IDE anwählen:
Werkzeuge - serieller Monitor, dann erfolgt die Ausgabe. Je langsamer
man umschaltet, desto mehr von der Ausgabe ist schon durchgerauscht und
auf dem Monitor nicht mehr zu sehen, sodaß man an einen geheimnisvollen
Offset denkt.
Ich habe jetzt vor die Ausgaberoutine geschrieben: delay(5000), dann
kann ich gemächlich auf den seriellen Monitor umschalten und verpasse
nichts mehr.
Ich vermute, daß das bei neueren Arduino-IDE-Versionen geändert worden
ist, denn früher konnte ich beobachten, daß die LED, die die Ausgabe
begleitet, erst aufleuchtete, wenn der serielle Monitor angeklickt
worden ist und deshalb ist von der Ausgabe nichts verloren gegangen. Bei
der neueren IDE-Version leuchtet diese LED sofort. Oder es liegt an der
anderen Hardware, früher lief es auf einem Iteaduine 2.2, jetzt auf
einem Leonardo.
Also, nichts für ungut!
Gruß
Egon