Guten Abend,
ich versuche aktuell auf einem ESP8266 eine Art Software I2C zu
implementieren um damit später den BMP290 auslesen zu können. Aktuell
passiert noch nicht viel und trotzdem funktioniert es nicht. Der ESP8266
resettet sich regelmäßig ohne ersichtlichen Grund, das Einzige, was ich
mache, ist ein paar Pins zu toggeln, mein Code:
Pack mal einen dicken Kondensator über die Spannungsversorgung, der ESP
ist ziemlich zickig bei Spannungseinbrüchen.
Übrigens: Es gibt einige fertige Libs für I2C.
Oliver S. schrieb:> Pack mal einen dicken Kondensator über die Spannungsversorgung, der ESP> ist ziemlich zickig bei Spannungseinbrüchen.
Ich hab 100µF in 0805 zwischen VCC und GND (und den obligatorischen
100nF). Ist das zu wenig? Ich hab mit dem ESP8266 bereits eine 7-Segment
Anzeige + WLan betrieben, das benötigt doch eindeutig mehr Strom als 2
Pins aus und ein zu schalten, oder?
Oliver S. schrieb:> Übrigens: Es gibt einige fertige Libs für I2C.
Ja, ich will das aber selber machen.
Ich habe auf den ersten Blick zwar nicht ganz den Sinn von SDO
verstanden, aber daran sollte es ja nicht liegen.
Meine persönlich vage Vermutung, wo das Problem liegt:
Du togglest SCK und SDI soweit ich das sehen kann immer zwischen "output
high" und "output low".
Ich vermute aber, Du musst beide Pins stattdessen zwischen "input" und
"output low" togglen; der high-level wird bei I2C m.W.n. doch über extra
Pull-Up-Widerstände erzeugt, und nicht von den einzelnen Bus-Knoten.
Kurzum, ich vermute: überall, wo Du
gpio_output_set(x, 0, x, 0)
stehen hast, müsste stattdessen stehen
gpio_output_set(0, 0, 0, x)
Max M. schrieb:> Der ESP8266> resettet sich regelmäßig ohne ersichtlichen Grund
Beim esp8266 läuft Wifi auch im Hintergrund.
Bei längeren Abarbeitungszyklen schlägt da gerne mal reset zu, wenn
nicht durch Maßnahmen wie einfügen von yield() oder delay(0) der wdog
zurückgepfiffen wird..
Wie lang ist die Zeit, in welcher der Wdog bedient werden muss, ich habe
ähnliche Probleme, dass ab und zu der ESP neustartet.
@Max MMM
Der ESP hat einen Hardware-I2C und es gibt auch fertige Libs dafür. Mal
drübergeschaut, sehe ich keinen Fehler in Deinem Code.
Joachim S. schrieb:> Ich habe auf den ersten Blick zwar nicht ganz den Sinn von SDO> verstanden, aber daran sollte es ja nicht liegen.
Der Sensor BMP280 hat sowohl ein SPI als auch ein I2C Interface, laut
Datenblatt muss der SDO-Pin bei I2C entweder mit GND oder Vcc verbunden
werden, je nach dem ergibt sich dann sie Slave-Adresse:
"The I²C interface uses the following pins:
SCK: serial clock (SCL)
SDI: data (SDA)
SDO: Slave address LSB (GND = ‘0’, VDDIO = ‘1’)"
Joachim S. schrieb:> Ich vermute aber, Du musst beide Pins stattdessen zwischen "input" und> "output low" togglen; der high-level wird bei I2C m.W.n. doch über extra> Pull-Up-Widerstände erzeugt, und nicht von den einzelnen Bus-Knoten.
Hm, mit meiner 7-Segment LED hat das an/aus der Pins wie ich es jetzt
mache wunderbar funktioniert. Aufm Logic Analyzer kommen die Signale
auch an, nur der Controller resettet sich dauernd :(
e-d schrieb:> Beim esp8266 läuft Wifi auch im Hintergrund.> Bei längeren Abarbeitungszyklen schlägt da gerne mal reset zu, wenn> nicht durch Maßnahmen wie einfügen von yield() oder delay(0) der wdog> zurückgepfiffen wird..
Welchen Grund hat das? Ich hab nun im Code verhindert, dass sich der
Controller automatisch mit dem zuletzt verbundenen Wifi verbindet:
Max M. schrieb:> Joachim S. schrieb:>> Ich habe auf den ersten Blick zwar nicht ganz den Sinn von SDO>> verstanden, aber daran sollte es ja nicht liegen.>> Der Sensor BMP280 hat sowohl ein SPI als auch ein I2C Interface, laut> Datenblatt muss der SDO-Pin bei I2C entweder mit GND oder Vcc verbunden> werden, je nach dem ergibt sich dann sie Slave-Adresse:
Ah, verstehe.
> Joachim S. schrieb:>> Ich vermute aber, Du musst beide Pins stattdessen zwischen "input" und>> "output low" togglen; der high-level wird bei I2C m.W.n. doch über extra>> Pull-Up-Widerstände erzeugt, und nicht von den einzelnen Bus-Knoten.>> Hm, mit meiner 7-Segment LED hat das an/aus der Pins wie ich es jetzt> mache wunderbar funktioniert. Aufm Logic Analyzer kommen die Signale> auch an, nur der Controller resettet sich dauernd :(
Den Zusammenhang mit der 7-Segment-Anzeige habe ich jetzt ehrlich gesagt
nicht ganz verstanden. Dass auf deinem Logic Analyzer das Signal richtig
aussieht, ist meiner Meinung nach aber sogar ganz normal.
Hast Du meinen Lösungsvorschlag denn wenigstens mal ausprobiert? Ich bin
zu ca. 75% sicher, dass das Problem damit zusammenhängt.
Max M. schrieb:> Oliver S. schrieb:>> Übrigens: Es gibt einige fertige Libs für I2C.>> Ja, ich will das aber selber machen.Max M. schrieb:> Hm, mit meiner 7-Segment LED hat das an/aus der Pins wie ich es jetzt> mache wunderbar funktioniert.
Ich würd mal mit dem Lesen und verstehen der I2C Spec anfangen. Dabei
könnte man sich dann auch überlegen was passiert, wenn der selbst
verkorkste Master ein Signal aktiv auf High zieht, währen ein Slave ihn
nach Low treibt.
MfG Klaus
Joachim S. schrieb:> Hast Du meinen Lösungsvorschlag denn wenigstens mal ausprobiert? Ich bin> zu ca. 75% sicher, dass das Problem damit zusammenhängt.
Ich hab meine Code dahingehend abgeändert:
Leider resettet der Controller immer noch.
Klaus schrieb:> Ich würd mal mit dem Lesen und verstehen der I2C Spec anfangen. Dabei> könnte man sich dann auch überlegen was passiert, wenn der selbst> verkorkste Master ein Signal aktiv auf High zieht, währen ein Slave ihn> nach Low treibt.
Ich versuche aktuell erstmal, die Flanken und die Daten richtig zu
erzeugen, wohin dann welcher Pin gezogen wird, darum kümmere ich mich
später. Aktuell hängt der Sensor noch nicht dran.
Max M. schrieb:> Ich versuche aktuell erstmal, die Flanken und die Daten richtig zu> erzeugen, wohin dann welcher Pin gezogen wird, darum kümmere ich mich> später. Aktuell hängt der Sensor noch nicht dran.
Prima Anfang, erst mal kräftig Strom fließen lassen. Und sollte dir der
Slave deine Daten und Flanken doch mal durcheinander bringen, nimm
einfach einen stärkeren Treiber.
MfG Klaus
Max M. schrieb:> Wie schaltet man beim ESP8266 einen Pin als Open-Drain?Joachim S. schrieb:> Meine persönlich vage Vermutung, wo das Problem liegt:> Du togglest SCK und SDI soweit ich das sehen kann immer zwischen "output> high" und "output low".>> Ich vermute aber, Du musst beide Pins stattdessen zwischen "input" und> "output low" togglen; der high-level wird bei I2C m.W.n. doch über extra> Pull-Up-Widerstände erzeugt, und nicht von den einzelnen Bus-Knoten.
Oder die eingebaute HW benutzen
http://download.arduino.org/products/UNOWIFI/0A-ESP8266-Datasheet-EN-v4.3.pdf
Section 3.4
MfG Klaus
Danke für den Hinweis Klaus, da war ich etwas falsch gewickelt. Ich
dachte I2C funktioniert so (ähnlich) wie SPI.
Ich hab meinen Code abermals umgeschrieben:
Der ESP8266 meldet doch beim Booten/resetten über die serielle
Schnittstelle den "rst cause" und den "boot mode". Diese Informationen
sollten helfen zu verstehen, aus welchem Grund der ESP überhaupt
resettet.
Ansonsten wäre mal interessant, wie deine Schaltung derzeit überhaupt
konkret aussieht, vielleicht wird man dann etwas schlauer.
p.s.: So ganz habe ich doch noch nicht den Sinn des GPIO-Pins für SDO
verstanden. Bzw. ich verstehe nicht ganz, warum Du den entsprechenden
Pin des BMP280 nicht einfach fest mit GND oder VCC verdrahtest, wenn
dadurch eh nur die Slave-Adresse konfiguriert wird. Du wirst ja wohl
kaum die Slave-Adresse während des Betriebs ändern, warum also einen
kostbaren GPIO-Pin des ESP8266 verbrauchen?
Joachim S. schrieb:> Du wirst ja wohl> kaum die Slave-Adresse während des Betriebs ändern, warum also einen> kostbaren GPIO-Pin des ESP8266 verbrauchen?
Da hast du eigentlich Recht. Auf die Idee kam ich nur nicht ^^
Joachim S. schrieb:> Diese Informationen> sollten helfen zu verstehen, aus welchem Grund der ESP überhaupt> resettet.
Hm, sagt mir nicht so viel:
1
SDKver:1.5.4(baaeaebb)compiled@May17201619:23:54
2
phyver:972,ppver:10.1
3
mode:sta(5c:cf:7f:1c:0a:10)
4
¢@*r…Ä(±±Kít¥dmXK
5
nzAl
6
±#Nørf[112]:03
7
rf[113]:00
8
rf[114]:01
Joachim S. schrieb:> Ansonsten wäre mal interessant, wie deine Schaltung derzeit überhaupt> konkret aussieht, vielleicht wird man dann etwas schlauer.
Siehe Anhang, 22uF wurden durch 100uF ersetzt.
Resepp schrieb:> Ist das eigentlich vom Mosul abhängig, wie stabil die Spannung sein> muss?> Wollte mir dieses da besorgen:> http://www.ramser-elektro.at/shop/module-sensoren-adapter-und-co/esp8266-esp12f-wlan-modul/
Nicht dass ich wüsste. Neben kompletten "NodeMCU DevKit"-Boards benutze
ich persönlich auch nur die ESP-12F-Module. Direkt neben mir habe ich
gerade eins auf einem Breadboard, zufällig auch genau mit einem
100µF-Stützkondensator. Da hatte ich bislang auch noch keine Probleme.
(Aber vielleicht wäre es testweise mal nicht schlecht, ein anderes
Netzteil zu benutzen, nur um das als Fehlerquelle auszuschliessen?)
Dein Schaltplan sieht ansonsten für mich auch absolut okay aus, da
könnte ich jetzt auf Anhieb keinen Fehler entdecken.
Was die Ausgabe über die serielle Schnittstelle betrifft: Ich fürchte,
dass der "reset cause" ausgerechnet in den unleserlichen Zeichen in der
Mitte steht.
Der reset cause etc. wird mit der etwas ungewöhnlichen Baudrate von
74880 geschickt - versuche mal, diese Baudrate einzustellen, wenn's
klappt dann sollte beim booten/reset eine Debug-Nachricht ähnlich der
folgenden zu lesen sein:
Joachim S. schrieb:> versuche mal, diese Baudrate einzustellen, wenn's> klappt dann sollte beim booten/reset eine Debug-Nachricht ähnlich der> folgenden zu lesen sein:
Okay, hier ist die Ausgabe:
1
ets Jan 8 2013,rst cause:2, boot mode:(3,0)
2
3
load 0x40100000, len 24404, room 16
4
tail 4
5
chksum 0x04
6
load 0x3ffe8000, len 884, room 4
7
tail 0
8
chksum 0x81
9
load 0x3ffe8380, len 168, room 8
10
tail 0
11
chksum 0xba
12
csum 0xba
13
ø
14
ets Jan 8 2013,rst cause:2, boot mode:(3,7)
15
16
load 0x40100000, len 24404, room 16
17
tail 4
18
chksum 0x04
19
load 0x3ffe8000, len 884, room 4
20
tail 0
21
chksum 0x81
22
load 0x3ffe8380, len 168, room 8
23
tail 0
24
chksum 0xba
25
csum 0xba
26
rf[112] : 03
27
rf[113] : 00
28
rf[114] : 01
Die kommt aber nur, wenn ich den ESP8266 manuell neu starte (Strom
ab/an) und auch nur einmal. Ansonsten erhalte ich auch mit einer Baud
Rate von 74880 nur nichtssagende Zeichen wenn er automatisch resetet.
Wenn ich GPIO2 (also SCK) mit meinem Logic Analyzer verbinde, sehe ich,
dass der ESP viel mehr Pin Toggles macht, als er nach der Schleife
sollte. Das Aufrufen der Funktion alle 5 Sekunden klappt. Ich frag mich
nur, was da vor sich geht, Eigentlich sollten da doch höchstens 8 mal
ein Pin getoggelt werden. Stattdessen passiert das aber fast 2 Sekunden
lang!?
Max M. schrieb:> if(currentBit == 1)> setHigh(SDA);> else> setLow(SDA);> setHigh(SCK);> setLow(SCK);> }
Ans Clock stretching gedacht? Und wie siehts mit ACK/NAK aus?
MfG Klaus
Klaus schrieb:> Ans Clock stretching gedacht? Und wie siehts mit ACK/NAK aus?
Das kommt alles noch, wobei ich hoffe, dass mein Sensor kein Clock
stretching macht sonst wirds echt kompliziert (für mich) zum
programmieren, wenn nötig, mach ich die Übertragung so langsam wie
nötig. Ich bin froh, dass der ESP (erstmal) nicht mehr zickt. Lustig,
dass der Fehler dazu geführt hat, dass ich mir das SDK auf meinem
Linux-PC installiert hab. Klappt dort wesentlich besser und hab auch
keine Probleme mehr mit dem aktuellen SDK 2.0.
Max M. schrieb:> Viele Dank! Da sieht man den Wald vor lauter Bäumen nicht,> unglaublich.> Danke für die Lösung des Problems! :)
bitCycle++
bitCycle--
diese Doppelpostings in allen Foren
und dann auch noch unterschiedlich abgeschrieben:
man sollte sich mal entscheiden?
http://www.esp8266.com/viewtopic.php?f=6&t=12776&p=59024#p59024
Wie gesagt, ich war an einer schnellen Problemlösung interessiert, in
Zukunft benutze ich ausschließlich dieses Forum, ich hoffe, dass nimmt
mir keiner übel.
Ich bin gerade dabei zu überprüfen, ob der Slave ein ACK gesendet hat.
Meiner Information nach, passiert das, wenn die Datenleitung (SDA) auf
Low gezogen wird. Nun bin ich mir nicht ganz sicher, wie ich denn beim
ESP den Status eines GPIOs auslese. In der SDK Api Reference gibt es die
Funktion GPIO_INPUT_GET(gpio_no). Muss da als Parameter nun das Bit (so
wie bei gpio_output_set ) oder die tatsächliche Nummer (also 0,1,2
usw). rein?
Okay, anscheinend muss man hier direkt mit der Nummer des Ports
arbeiten. Noch eine Frage:
Wie ermittle ich, ob der Slave sein ACK gesendet hat? Nach dieser Seite:
http://www.cc-zwei.de/wiki/index.php?title=I2C_Bus_Hintergrundwissen
wird bei einem Slave-ACK die Datenleitung auf low gezogen. Was würde
aber nun passieren, wenn das letzte übertragene Bit eine 0 ist, dann
wäre SDA schon standardmäßig auf low und ich würde ich eine 0 lesen
obwohl der Slave möglicherweise gar nichts gesendet hat?
Ich bin mir nicht ganz sicher, ob meine Vorgehensweise so richtig ist:
Nach jedem gesendeten Byte überprüfe ich mit "checkSlaveClkReceived", ob
die Clock-Leitung high ist (nach meiner Information müsste der Slave ein
Clock Signal für das Ack erzeugen), ist das so richtig? Ich bin für jede
Hilfe zu diesem Thema dankbar.
Max M. schrieb:> (nach meiner Information müsste der Slave ein> Clock Signal für das Ack erzeugen)
Nein, der Master muß einen 9tes Clocksignal erzeugen und dabei SDA
beobachten. Als ACK zieht der Slave SDA auf Low. Wenn der Slave für das
ACK etwas länger braucht, stretched er die Clock ein wenig. Ist er gar
nicht da (oder die Adresse falsch) bleibt SDA durch den Pullup einfach
HIGH, also NAK.
Die I2C Spec lesen und sie verstehen hilft ungemein. Auch eine
Umgebung, wo man mit LA und Debugger sich die ganze Sache Bit für Bit
ansehen kann, hilft beim Verstehen. Eine Erkenntnis, die man daraus
gewinnen kann, ist das das Handshaking der Clockleitung zwischen Master
und Slave, auch Clock-Stretching genannt, mandantory für das
Funktionieren von I2C ist.
MfG Klaus
Klaus schrieb:> Nein, der Master muß einen 9tes Clocksignal erzeugen und dabei SDA> beobachten. Als ACK zieht der Slave SDA auf Low.
Hier ist das Diagramm vom Logic Analyzer, sieht doch eigentlich okay
aus, oder?
In diesem Fall (das letzte Bit ist 0 ergo ist auch SDA 0) könnte ich
doch beim Ack gar nicht unterscheiden zwischen einer "0" vom Slave und
einer "0" vom letzten Bit?
Max M. schrieb:> In diesem Fall (das letzte Bit ist 0 ergo ist auch SDA 0) könnte ich> doch beim Ack gar nicht unterscheiden zwischen einer "0" vom Slave und> einer "0" vom letzten Bit?
Da lässt der Master SDA beim letzten Bit nicht los. Der I2C Bus ist
Opencollektor getrieben. Nur für das Bit, das gerade in Arbeit ist, darf
einer, Master oder Slave den Bus auf Low ziehen.
Klaus schrieb:> Die I2C Spec lesen und sie verstehen hilft ungemein.
MfG Klaus
Danke für deine Hilfe, Klaus.
Klaus schrieb:> Da lässt der Master SDA beim letzten Bit nicht los. Der I2C Bus ist> Opencollektor getrieben. Nur für das Bit, das gerade in Arbeit ist, darf> einer, Master oder Slave den Bus auf Low ziehen.
Sieht das nun so besser aus? Wenn der Slave kein Ack senden würde, gäbe
es aber doch kein gültiges Stop-Signal (oder ist das dann schon "egal")?
Also inzwischen bin ich schon so weit, dass ich Acks vom Slave empfange
(wenn ich die SDO-Leitung vom BMP280 abziehe, bekomme ich kein Ack mehr,
ebenso wenn ich SCK, SDA oder GND abziehe, ergo kann ich wahrscheinlich
einen Software-Fehler ausschließen).
Das Lesen der Register-Werte funktioniert noch nicht so ganz. Wie im
Datenblatt des BMP280 zu lesen ist gibt man das Start-Register, von dem
man lesen möchte, an und danach wird nach jedem Ack vom Master die
Register-Adresse auto-inkrementiert. So wie ich das aktuell sehe, ist
ein Master Ack, wenn bei einem zusätzlichen clk-Impuls die SDA-Leitung
auf low gezogen wird. Beim Master Nack wäre stattdessen die SDA-Leitung
auf high.
Das ist aktuell die Funktion, die das realisieren soll:
1
uint32_tI2CReadBMP280Temperature(){
2
uint8_tmsb=0;
3
uint8_tlsb=0;
4
uint8_txlsb=0;
5
I2CStart();
6
if(sendByteWithSlaveAck(SLAVE_WRITE)){
7
if(sendByteWithSlaveAck(0xFA)){//tell slave the register we want to read from
8
I2CStart();
9
if(sendByteWithSlaveAck(SLAVE_READ)){
10
uart0_sendStr("Received slave's last read ack.\r\n");
11
msb=readByte();//data from 0xFA
12
I2CMasterAck();
13
lsb=readByte();
14
I2CMasterAck();
15
xlsb=readByte();
16
I2CMasterNAck();
17
}
18
}
19
}
20
I2CStop();
21
return((msb<<12)|lsb)|xlsb;
22
}
Meine Read-Funktion:
1
uint8_treadByte(){
2
int16_tbitCounter;
3
uint8_treceivedByte=0;
4
for(bitCounter=7;bitCounter>=0;bitCounter--){
5
setHigh(SCK);
6
os_delay_us(4);
7
if(GPIO_INPUT_GET(12)==1){
8
receivedByte|=(1<<bitCounter);
9
}
10
setLow(SCK);
11
}
12
returnreceivedByte;
13
}
Master Ack + Master Nack:
1
voidI2CMasterAck(){
2
setHigh(SCK);
3
setLow(SDA);
4
os_delay_us(2);
5
setLow(SCK);
6
os_delay_us(2);
7
setHigh(SDA);//release SDA
8
}
9
10
voidI2CMasterNAck(){
11
setHigh(SCK);
12
setHigh(SDA);
13
os_delay_us(2);
14
setLow(SCK);
15
}
Auf meiner Konsole bekomme ich:
1
Setup BMP280 successfully.
2
Received slave's last read ack.
3
1044735
Also ich schaffe es schon einmal in die innerste Anweisung. Allerdings
bekomme ich immer die oben stehende Zahl, normalerweise müsste die sich
bei jedem Lesen etwas ändern (ich lese alle 500ms), oder?
Hat jemand noch einen Tipp für mich?
Könnte das Problem vielleicht die 2. Start Kondition beim Lesen sein? Um
eine Startkondition erkennen zu können, müssen doch sowohl SDA als auch
SCK von high auf low gehen? D.h. ich muss irgendwie sicher stellen das
SDA und SCK high sind. Wie mache ich das? Kann ich SCK und SDA einfach
auf high setzen oder wird das vom Sensor möglicherweise falsch
interpretiert?
Ich hab nun noch mal den Read-Vorgang durch meinen Analyzer laufen
lassen, diesmal setze ich SCK explizit auf High bevor die 2.
Start-Bedingung kommt, eigentlich sieht alles gut aus, sogar die Logic
Analyzer Software erkennt, um was es sich bei der Bitfolge handelt. Hat
noch jemand Ideen dazu?
Max M. schrieb:> diesmal setze ich SCK explizit auf High bevor die 2.> Start-Bedingung kommt
Darfst du eigentlich nicht.
Der Master darf SCK nur auf Low ziehen, nie auf High.
Und der Master sollte eigentlich, wenn er SCK "loslässt", also nicht
mehr auf LOW zieht, die SCK-Leitung auf die L->H Flanke überwachen, und
auf diese Flanke Reagieren.
Sonst kann das Device den SCK-Clock nicht verlangsamen, wenn der Master
zu schnell ist.
Planlos schrieb:> Der Master darf SCK nur auf Low ziehen, nie auf High.> Und der Master sollte eigentlich, wenn er SCK "loslässt", also nicht> mehr auf LOW zieht, die SCK-Leitung auf die L->H Flanke überwachen, und> auf diese Flanke Reagieren.
Kann es sein, dass du hier SDA und SCK verwechselst? Beim Lesevorgang
muss doch der Master den Clock generieren damit der Slave die Bits über
SDA rausschiebt, oder?
Okay, ich habs nun endlich hinbekommen. Das Auslesen der Device ID
funktioniert auf jeden Fall, bei dem Temperatur-Register kommt ein Wert
raus, der sich erhöht, wenn ich den Sensor berühre und verringert, wenn
ich wieder loslasse. Außerdem ändert er sich bei jedem Auslesen etwas,
von dem her denke ich mal, das müsste passen. Jetzt ist nur das Problem,
dass ich nicht ganz durch die Formel steige, mit der man die Temperatur
berechnet. Im Datenblatt
(https://cdn-shop.adafruit.com/datasheets/BST-BMP280-DS001-11.pdf) auf
S.22 ff ist die Formel zu finden. Anscheinend muss ich noch zusätzliche
Werte auslesen (dig_T1, dig_T2, dig_T3). In der Formel kommt allerdings
auch ein Wert "adc_T" vor. Woher bekomme ich den?
Max M. schrieb:> Kann es sein, dass du hier SDA und SCK verwechselst?
Nein. Sowohl für SDA als auch für SCL gilt: der einzige "Busteilnehmer",
der die Leitung auf HIGH stellen darf, ist der Pull-Up.
Das ist das Problem mit den Logic-Analyzer-Auswertungen:
Du siehst, was am Bus ist, aber nicht, wer es verursacht.
Das "Wer" ist bei I²C aber wichtig.
Max M. schrieb:> S.22 ff ist die Formel zu finden. Anscheinend muss ich noch zusätzliche> Werte auslesen (dig_T1, dig_T2, dig_T3). In der Formel kommt allerdings> auch ein Wert "adc_T" vor. Woher bekomme ich den?
Schau besser hier rein:
https://github.com/BoschSensortec/BMP280_driver
Planlos schrieb:> Nein. Sowohl für SDA als auch für SCL gilt: der einzige "Busteilnehmer",> der die Leitung auf HIGH stellen darf, ist der Pull-Up.
Okay, mit high meinte ich, wenn keiner der Busteilnehmer die Leitung auf
low zieht (wenn also der portpin als Eingang geschaltet ist). SCK wird
der slave ja wohl kaum auf low ziehen, oder?
Hallo,
Max M. schrieb:> Okay, mit high meinte ich, wenn keiner der Busteilnehmer die Leitung auf> low zieht (wenn also der portpin als Eingang geschaltet ist). SCK wird> der slave ja wohl kaum auf low ziehen, oder?
eben doch! Ein Slave darf SCK auf Low halten wenn er noch Zeit braucht,
eben Clock Stretching.
Der Master muß also auch bei SCK nach dem freigenen von SCK dieses
einlesen und muß warten, bis SCK wirklich wirder auf high ist.
Es sind relativ wenige Slave-Devices, die es nutzen.
Den Fehler hatte selbst Atmel in seinem allerersten I2C Beispielcode
drin.
Mein MAS3507 hatte damals garkein Verständnis dafür...
Gruß aus Berlin
Michael
Planlos schrieb:> Der Master darf SCK nur auf Low ziehen, nie auf High.> Und der Master sollte eigentlich, wenn er SCK "loslässt", also nicht> mehr auf LOW zieht, die SCK-Leitung auf die L->H Flanke überwachen, und> auf diese Flanke Reagieren.Max M. schrieb:> SCK wird der slave ja wohl kaum auf low ziehen, oder?
Aber sicher doch. Manchmal so kurz, daß du es nicht bemerkst. manchmal
auch länger. Ein sauber implementierter Slave legt SCL auf Low, sobald
er merkt, daß der Master es auf Low gelegt hat. So kann ihm dieser Takt
nicht mehr durch die Lappen gehen. Dann tut er was nötig ist und lässt
SCL wieder los. Ist er damit schneller als der Master, merkst du das
nicht. Ist er langsamer, muß der Master länger auf das High warten.
MfG Klaus
Ich schreib zu langsam
Hallo,
Klaus schrieb:> Ich schreib zu langsam
dafür mit weniger Tippfehlern als ich... ;-)
Es ist bei eigenen I2C-Routinen dann gern der nächste Fehler, in dieser
Abfrage von SCK beim Master kein Timeout einzubauen. Eine Störung oder
ein hängender Slave sorgt dann sicher dafür, daß sich garnichts mehr
rührt.
Gruß aus Berlin
Michael
Michael U. schrieb:> Es ist bei eigenen I2C-Routinen dann gern der nächste Fehler, in dieser> Abfrage von SCK beim Master kein Timeout einzubauen. Eine Störung oder> ein hängender Slave sorgt dann sicher dafür, daß sich garnichts mehr> rührt.
Das verstehe ich gerade nicht ganz, kannst Du das nochmal etwas
ausführlicher erklären?
Meinst Du damit, dass der Master in der Routine, in der er die SCK-Line
auf eventuelles Clock-Stretching durch den Slave überprüft (indem er
darauf wartet, dass SCK wieder high-level hat), einen Timeout benutzen
sollte?
Falls ja, verstehe ich nämlich gerade nicht, was der Vorteil des
Timeouts sein soll - denn solange SCK durch den Slave oder was auch
immer auf low gezogen wird, ist der Bus doch eh komplett blockiert? Der
Master wüsste im Falle eines Timeouts dann zwar vielleicht, dass etwas
nicht stimmt, aber ändern kann er daran dann doch auch nichts?
Joachim S. schrieb:
..
> Das verstehe ich gerade nicht ganz, kannst Du das nochmal etwas> ausführlicher erklären?> Meinst Du damit, ..> Falls ja, verstehe ich nämlich gerade nicht, was der Vorteil des> Timeouts sein soll - .. ist der Bus doch eh komplett blockiert? ..> Der Master wüsste im Falle eines Timeouts dann zwar vielleicht,> dass etwas nicht stimmt
"errorlevel" auswerten
> aber ändern kann er daran dann doch auch nichts?
handlen kann er aber:
"SLAVE Reseten" kann er dann, wenn er hängt.
"STÖRUNG" anzeigen kann er nach fruchtlosen Versuchen
"..." ...
Ich sehe ein, dass es potentiell sinnvoll und nützlich sein könnte, eine
zu lange "gestretchte" SCK-Line per Timeout zu erkennen.
Auch, dass der Master man mit gewissen Vorkehrungen (Slave resetten)
unter Umständen sogar das Problem beheben kann.
Aber ich würde jetzt vermuten, dass Vorkehrungen wie "Slave Resetten
wenn Clock zu lange gestretcht" in der Praxis doch nur sehr selten
eingesetzt werden.
Von daher hätte ich das jetzt eher als rein optionale,
"kann-man-machen"-Massnahme betrachtet; dass amiga den Verzicht auf
diese Massnahme stattdessen als "Fehler" bezeichnet, verwundert mich
halt ein bisschen.
Joachim S. schrieb:> Von daher hätte ich das jetzt eher als rein optionale,> "kann-man-machen"-Massnahme betrachtet;
Und dann kommt so eine Frage wie: "Mein Baustein resettet sich ...." Tja
weil der Watchdog nicht bedient wurde, weil der Prozessor aus einer
Schleife nicht mehr raus kam
MfG Klaus
Hallo,
Joachim S. schrieb:> Von daher hätte ich das jetzt eher als rein optionale,> "kann-man-machen"-Massnahme betrachtet; dass amiga den Verzicht auf> diese Massnahme stattdessen als "Fehler" bezeichnet, verwundert mich> halt ein bisschen.
gut, sagen wir es so: normalerweise passiert das nicht.
Ein abgestürzter Slave, der SCK auf Low festhält, ist normalweise nicht
mehr anzusprechen. PowerOn-Reset ist dann normalerweise nötig.
Es muß auch nicht dort abgesichert werden, wenn man den genauen Fehler
nicht wissen muß. Es sollte nur darauf hinweisen, daß man die ganze
I2C-Routine per TimeOut o.ä. dagegen absichern sollte.
Ein einzelner Sensor, der den ganzen µC lahmlegt, ist nicht die ideale
Lösung.
Gruß aus Berlin
Michael
Ich weiß nicht, ob dir das hilft, aber ich bin auch schon mal fast
verrückt geworden, weil mein ESP-12F sich immer wieder mal resettete.
Bei mir war die Lösung, dass ich keine oder zu geringe Delays zwischen
dem Ein/Ausschalten eines GPIOs hatte (brauchte das für eine
Schrittmotorsteuerung. Sobald ich dazwischen ein tmr.delay(100) baute
(ich nutze die NodeMCU Firmware, heißt bei dir wohl anders)
funktionierte alles total stabil und es gab seitdem überhaupt keine
Resets mehr.
Hallo,
dem ESP ist es egal, wie schnell Di die GPIOs umschaltest,
aber als Beispiel:
1
for (int i =0; i<100; i++)
2
{
3
digitalWrite(GPIO,LOW);
4
digitalWrite(GPIO,HIGH);
5
}
ist blockierend, der ESP kann während der Laufzeit der for-Schleife
nichts anderes machen. Da die WALN-Routinen usw. aber zum Zug kommen
müssen und damit auch der WatchDog zurückgesetzt werden muß, schlägt der
zu, wenn solch eine blockierende Schleife zu lange dauert.
1
for (int i =0; i<100; i++)
2
{
3
yield();
4
digitalWrite(GPIO,LOW);
5
digitalWrite(GPIO,HIGH);
6
}
Ein yield(); (oder delay(0);) behebt das Problem, da dort die Routinen
abgearbeitet werden wenn nötig.
Gruß aus Berlin
Michael
Wer hat sich denn die **** Formel fürs Temperatur umrechnen ausgedacht?
Nicht nur, dass man da ohne Ende doubles benutzen muss, was nicht gerade
speicherplatzschonend ist, nein, man muss auch noch wie wild schieben so
dass man sich gar nicht mehr auskennt. Auf GitHub erkennt man vor lauter
Klammern nicht mehr, welcher Wert denn nun wie oft wo hin geschoben wird
und mit welchem Operator er mit welchen anderen Werten verbunden ist.
20-bit Temperaturauflösung schön und gut, aber das ist doch Mist...Kein
normaler Mensch erkennt den Hintergrund der Formel. Anscheinend braucht
man dafür einen 32-bit ARM mit FPU um das auszurechnen.
Hat jemand zufällig eine Idee, wie das einfach(er) funktioniert bzw. hat
schon mal jemand mit dem BMP280 gearbeitet?
Hallo,
Max M. schrieb:> Hat jemand zufällig eine Idee, wie das einfach(er) funktioniert bzw. hat> schon mal jemand mit dem BMP280 gearbeitet?
naja, die Bibliotheken, die ich kenne, halten sich nahezu 1:1 an das
Datenblatt des BME280.
Und die gehen auch auf einem Mega328 problemlos...
Gruß aus Berlin
Michael
Hab ich die Formel so richtig entziffert?
Edit: Nächster Knaller, der Sensor ist so ausgelegt, dass er die Adresse
des Registers nach jedem Lesevorgang automatisch inkrementiert, so dass
man mit einem Rutsch mehrere nach einander folgende Register lesen kann.
Bei der Temperatur klappt das noch, da zuerst MSB (aus Register "x"),
dann LSB (aus x+1) dann XLSB (aus x+2). Bei den Korrekturwerten dig_T1
ist es jedoch genau umgedreht, also es kommt zuerst LSB, dann MSB, frag
mich nicht warum!
Hallo,
wenn der Hersteller die Register so angeordnet hat, hat er das eben...
Zu den Formeln: im Datenblatt sind doch Beispiel-Source drin, in
Ganzzahl-Arithmetik usw. usw.
Die funktionieren auch in der Realität.
Ich habe das Spielchen vor Jahren mit dem FOST HP03S durchexerziert,
ohne wirkliche Beispiele usw. Hat etwas halt gedauert, bis alle
Wertebereiche passten usw. Läuft heute noch auch einem Mega in ASM
geschrieben.
Bei den BME280 habe ich mit der Erfahrung zugegebenermaßen lieber auf
die Arbeit anderer zurückgegriffen...
Gruß aus Berlin
Michael
Michael U. schrieb:> Zu den Formeln: im Datenblatt sind doch Beispiel-Source drin, in> Ganzzahl-Arithmetik usw. usw.> Die funktionieren auch in der Realität.
Danke für den Hinweis, hab ich zu spät gesehen. Ich frage mich gerade,
wie ich über I2C einen signed-Wert lesen kann (für dig_T3 und dig_T2
benötigt) und was passiert, wenn ich den shifte? Mein Ansatz:
Hallo,
ich habe jetzt nicht im Detail geschaut, aber:
über I2C kommen 8 Bit-Werte.
{code]
int daten;
daten = I2CreadByte() << 8; // wenn h zuerst kommt
daten = I2CreadByte();
[/code]
Ob Du das dann als signed oder unsigned behandelst hängt nur von der
Definiton von daten ab.
Hoffentlich keinen krassen fFehler reingetippt...
Gruß aus Berlin
Michael
Muss meine Funktion readByte einen int8_t oder uint8_t zurückgeben,
damit ich in der I2CReadBMP280Signed-Funktion auch einen passenden
signed Wert zusammenbekomme, immerhin wird da auch geschoben? Oder ist
das egal?
Heureca, ich habs nun endlich geschafft. Mit der Ganzzahl-Formel bekomme
ich valide Werte (~2387 = 23.87°C). Falls es jemanden interessiert, hier
der gesamte Code für den ESP8266: