Forum: Mikrocontroller und Digitale Elektronik I2C RTC+EEPROM mit ESP8266. Mal funktionierts mal nicht


von Felix N. (felix_n888)


Angehängte Dateien:

Lesenswert?

Guten Abend,

In meinem aktuellen Projekt kommt als Prozessor ein ESP8266(ESP12-F 
Modul) zum Einsatz. Desweitern befindet sich noch eine Echtzeituhr 
(MCP7940N) und ein EEPROM(M24C32) auf der Platine welche mit dem I2C 
Interface verbunden sind.

Leider macht der I2C Bus ziemlich Probleme bei mir in form von er 
funktioniert mal und dann mal wieder nicht.

Wenn der Bus dann mal nicht funktioniert konnte ich feststellen das die 
Datenleitung(SDA) dauerhaft auf LOW gezogen wird während SCL auf HIGH 
ist. Verursacher scheint wohl möglicherweise die RTC(MCP7940N) zu sein. 
Ich habe mal zum testen das EEPROM & RTC ausgelötet wenn der Bus nicht 
funktioniert hat.

Wenn die RTC raus war funktionierte das EEPROM direkt auch ohne 
Codeänderung. Die RTC wurde dabei im Code nicht initialisiert. Die RTC 
habe ich auch schonmal testweise gegen eine neue getauscht um ein Defekt 
auszuschließen. Jedoch ohne Erfolg.

Hin und wieder krieg ich den Bus ans laufen wo dann RTC & EEPROM so 
funktionieren wie es soll. Wenn ich dann ein neues Programm auf den ESP 
lade scheint das wohl Glücksspiel zu sein ob der läuft oder nicht.

Ich bin mir auch nicht sicher ob es sich um ein Hardware oder 
Softwareproblem handelt. Die Anbindung des EEPROM hab ich selbst 
geschrieben und ist vom AVR-C portiert worden wo halt die i2c_xxx 
Funktionen durch die Methoden der Wire Library ersetzt wurden. So wie 
ich das verstanden habe hat der ESP8266 ja auch kein richtiges I2C 
Interface in Hardware wie zB. der AVR/STM32, sondern das ganze sei in 
Software via Bit-Banging gelöst.

PullUp Widerstände(2,2kOhm) sind direkt an den Datenleitungen am EEPROM 
dran nach 3,3V. Hatte vorher 4,7kOhm drin gehabt. Als Pins verwende ich 
GPIO4(SDA) und GPIO5(SCL)

Ich hatte das ganze bevor es in eine Platine umgewandelt wurde und der 
ESP8266 als Standalone zum Einsatz kommt, alles mal mit einem Streckbett 
und einer NodeMCU aufgebaut jedoch anstatt der MCP7940N die M 
Version(Ohne Battrie Backup Anschluss) im PDIP Variante verwendet und 
ein ST24C08 statt 32Kbit EEPROM. Da war diese Problem nicht aufgetreten.

Hat jemand ne Idee woran das liegen könnte.

Mfg

von Felix N. (felix_n888)


Angehängte Dateien:

Lesenswert?

Hier noch mal ein zwei Bilder vom I2C-Bus mit meinem Logikanalyzer.

Nach der Programmierung läuft der Bus erstmal problemlos, RTC und EEPROM 
lassen sich ohne Problem ansprechen.

Ich habe die Backup batterie der RTC entfernt, sobald also man den USB 
Stecker zieht ist alles Spannungslos.

Wenn man den ESP via Taster am RST pin zurücksetzt fängt das ganze Spiel 
an. Wenn man scheinbar den richtigen Moment erwischt passt nichts und 
alles läuft wie es soll. Kommt der Reset aber wohl in dem Moment wo die 
RTC Daten an den ESP sendet scheint die wohl den BUS einzufrieren. 
Zumindest bleibt danach dann SDA auf Low.

Aus diesem Zustand krieg ich den Bus dann auch nicht mehr raus egal wie 
oft ich die Reset Taste drücke. Erst wenn ich die Platine komplett 
stromlos mache und kurz warte bis alle Spannungen weg sind und die 
wieder mit Strom versorge läuft wieder alles bis zum nächsten Reset 
scheinbar. Wenn die Backup Batterie mit drin ist für die RTC bleibt der 
BUS auch nachdem die Platine stromlos war in diesem Zustand. SCL geht 
dann zwar mit auf LOW aber sobald die Strom drauf kommt geht nur SCL auf 
HIGH. SDA bleibt weiterhin auf LOW. Erst wenn man die Batterie entfernt 
und alles Stromlos ist geht SDA auch wieder mit auf HIGH.

Ich kann mir dieses Verhalten nicht erklären. Es ist nicht das erste mal 
das ich die MCP7940 RTC einsetze und ich hatte nie solche Problem damit 
gehabt auch nicht im Resetfall. Bis jetzt hab ich diese allerdings nur 
am AVR/STM32 mit einer "echten" I2C Schnittstelle verwendet.

Kann das vielleicht ein Problem mit der Software Implementierung der I2C 
Schnittstelle(Wire Library) sein?

: Bearbeitet durch User
von K. S. (the_yrr)


Lesenswert?

Felix N. schrieb:
> aber sobald die Strom drauf kommt geht nur SCL auf HIGH. SDA bleibt
> weiterhin auf LOW. Erst wenn man die Batterie entfernt und alles
> Stromlos ist geht SDA auch wieder mit auf HIGH.

die RTC weiß nichts von deinem reset und wartet geduldig, bis du den 
rest der Daten abholst. Theoretisch sollte clock stretching bei I2C 
unterstützt werden, hier halt wohl beliebig lange. Außer er I2C Teil der 
RTC ist ohne VCC nur mit Batterie auch abgeschaltet, aber das entnimm 
besser dem Datenblatt.


Edit:
Versuch mal am 9 clock Pulse mit SDA high, das sollte den Rest des Bytes 
raustakten. SDA high für NACK, danach ein Stop. Das IMMER nach einem 
Reset, weil dein Bus auch zufällig auf SDA high stecken bleiben kann, 
siehst du dann nur halt nicht.

Besser wäre natürlich kein harter Reset.

: Bearbeitet durch User
von Chris K. (kathe)


Lesenswert?

https://www.nxp.com/docs/en/user-guide/UM10204.pdf

3.1.16 Bus clear
In the unlikely event where the clock (SCL) is stuck LOW, the 
preferential procedure is
to reset the bus using the HW reset signal if your I2C devices have HW 
reset inputs. If the I2C devices do not have HW reset inputs, cycle 
power to the devices to activate the mandatory internal Power-On Reset 
(POR) circuit.
If the data line (SDA) is stuck LOW, the controller should send nine 
clock pulses. Thedevice that held the bus LOW should release it sometime 
within those nine clocks. If not, then use the HW reset or cycle power 
to clear the bus.

von Felix N. (felix_n888)


Lesenswert?

K. S. schrieb:
> die RTC weiß nichts von deinem reset und wartet geduldig, bis du den
> rest der Daten abholst

Hallo, ja das habe ich mir auch schon gedacht.

K. S. schrieb:
> Theoretisch sollte clock stretching bei I2C
> unterstützt werden, hier halt wohl beliebig lange.

Ich muss sagen das ich nicht genau weiß wie das mit der Arduino Library 
geht. Es gibt die Option Wire.setClockStretchLimit(uint32_t); aber ob 
das genau das richtige ist?

K. S. schrieb:
> Außer er I2C Teil der
> RTC ist ohne VCC nur mit Batterie auch abgeschaltet, aber das entnimm
> besser dem Datenblatt.

So wie ich das Datenblatt verstanden wird sobald VDD nicht verfügbar ist 
auf VBAT umgeschaltet um "Timekeeping" zu machen damit die Zeit erhalten 
bleibt. Das I2C Interface scheint wohl mit abgeschaltet zu werden. Bei 
meinen anderen Projekten hatte ich ich immer den MCP7940 in der M 
version also ohne den VBAT pin da hatte ich dann eine separate Schaltung 
dran gebaut die zwischen VCC und VBAT umschaltet und dann den MCP speist 
da war das I2C Interface dann immer dauerhaft aktiv.

K. S. schrieb:
> Versuch mal am 9 clock Pulse mit SDA high, das sollte den Rest des Bytes
> raustakten

Muss jetzt sagen kenne mich mit dem I2C Bus jetzt nicht im Detail aus. 
Wie mache ich das? SCL/SDA auf Output setzten dann in einer Schleife die 
Pulse erzeugen okay aber mit welcher Frequenz oder ist das egal?
1
    pinMode(5, OUTPUT); //SCL
2
    pinMode(4, OUTPUT); //SDA
3
    
4
    for(int i = 0; i < 9; i++) {     //9 clock pulse @ 500Hz  
5
      digitalWrite(5, LOW);              
6
      delay(1); 
7
      digitalWrite(5, HIGH);              
8
      delay(1); 
9
    }
10
11
    digitalWrite(5, LOW); //SCL Low
12
    delay(1);
13
    digitalWrite(4, LOW); //SDA Low
14
    delay(1);
15
    digitalWrite(5, HIGH); //SCL High
16
    delay(2);
17
    digitalWrite(4, HIGH); //SDA High

Bin mir aber absolut nicht sicher ob das so richtig ist wie du das 
meinst. Hab mal den Codeteil angehängt.

K. S. schrieb:
> Besser wäre natürlich kein harter Reset.

Wenn ich das gewusst hätte das es hier dann Probleme gibt hatte ich das 
anderes gemacht. Nur lässt sich das ganze leider nicht mehr ändern :(

Mfg

von D. J. (basteldag)


Lesenswert?

Wie versorgest du den Speicher und die RTC ? habe die Erfahrung gemacht, 
das der LDO auf dem ESP schwachbrüstig ist. Erst nach dem ich die 3,3V 
separat erzeugte , waren Störungen weg.
Ach so und außerdem das Datenblatt von der RTC(PIN7) nicht beachtet.

"3.4 Multifunction Pin (MFP)
This is an output pin used for the alarm and square
wave output functions. It can also serve as a general
purpose output pin by controlling the OUT bit in the
CONTROL register.
The MFP is an open-drain output and requires a pull-up
resistor to Vcc (typically 10 k). This pin may be left
floating if not used."

: Bearbeitet durch User
von Felix N. (felix_n888)


Lesenswert?

D. J. schrieb:
> Wie versorgest du den Speicher und die RTC ? habe die Erfahrung gemacht,
> das der LDO auf dem ESP schwachbrüstig ist.

Hallo, damit das jetzt nicht falsch verstanden wird, ich verwende nicht 
die NodeMCU! Der ESP sitzt alleine auf einer eigenen Platine genauso wie 
die RTC und das EEPROM. Getestet, bevor ich die Platine anfertigen 
lasse, hatte ich mit der NodeMCU auf einem Steckbrett.

Die RTC & EEPROM sowie auch der ESP8266 werden aus einem LM1117 3.3V LDO 
gespeist der seine Eingangsspannung(+5V) entweder von einem USB-C 
Anschluss bezieht oder von einem LM2596 Step-Down Wandler. Entsprechende 
Pufferung mittels Elkos hab ich vorgesehen. Auch hat der ESP bzgl. 
Langzeitstabilität direkt ein 100uF Elko bekommen.

D. J. schrieb:
> Erst nach dem ich die 3,3V
> separat erzeugte , waren Störungen weg.

Störungen hab ich ja nicht. Direkt nachdem Power-Up funktioniert ja 
alles wie es soll nur sobald ein Reset ausgelöst wird bleibt der Bus 
hängen da von der RTC noch nicht alle Daten gesendet wurden.

D. J. schrieb:
> Ach so und außerdem das Datenblatt von der RTC(PIN7) nicht beachtet.

???

D. J. schrieb:
> This pin may be left
> floating if not used."

Habe für den MFP pin keine Verwendung also ist er nicht beschaltet 
worden.

K. S. schrieb:
> Außer er I2C Teil der
> RTC ist ohne VCC nur mit Batterie auch abgeschaltet, aber das entnimm
> besser dem Datenblatt.

Hab nochmal genau angeschaut. In Kapital 4.1.1.5 des Datenblatt des 
MCP7940N steht als Notiz

"The I2C interface is disabled while operating from the backup power 
supply"

Chris K. schrieb:
> If the data line (SDA) is stuck LOW, the controller should send nine
> clock pulses.

Hmm okay. Das ist ja das was K.S auch schon vorgeschlagen hatte. Ich 
kann das aber erst heute Nachmittag testen ob das funktioniert.

Ich habe allerdings mal ein bisschen weiter gesucht und mit dem Problem 
scheine ich wohl nicht alleine zu sein. Entsprechend gabs bzgl. dieses 
Problem auch schon andere Beiträge.

Hier hat einer eine Lösung vorgeschlagen mit der DS1307 RTC:

https://github.com/esp8266/Arduino/issues/1025
http://www.forward.com.au/pfod/ArduinoProgramming/I2C_ClearBus/index.html

Konnte bis jetzt aber auch davon noch nichts testen. Werde ich heute 
Nachmittag machen. Melde mich nochmal.

Mfg

von Peter D. (peda)


Lesenswert?

Felix N. schrieb:
> Wenn der Bus dann mal nicht funktioniert konnte ich feststellen das die
> Datenleitung(SDA) dauerhaft auf LOW gezogen wird während SCL auf HIGH
> ist.

Ja, dann wurde wohl der ESP resettet, während er gerade Daten von dem 
RTC abgeholt hat.
Vor dem Ansprechen des I2C sollte der ESP erstmal prüfen, ob beide 
Leitungen auf high sind und im Fehlerfall bis zu 9 Pulse auf SCL 
erzeugen, bis SDA auf high ist.

Siehe I2C-Spezifikation:

"If the data line (SDA) is stuck LOW, the controller should send nine 
clock pulses. The device that held the bus LOW should release it 
sometime within those nine clocks."

https://www.nxp.com/docs/en/user-guide/UM10204.pdf

von D. J. (basteldag)


Lesenswert?

Felix N. schrieb:
> Habe für den MFP pin keine Verwendung also ist er nicht beschaltet
> worden.

Sollte aber, ist nicht gut. Es sei denn, es ist ein Ausgang.

von Felix N. (felix_n888)


Lesenswert?

Peter D. schrieb:
> Vor dem Ansprechen des I2C sollte der ESP erstmal prüfen, ob beide
> Leitungen auf high sind und im Fehlerfall bis zu 9 Pulse auf SCL
> erzeugen, bis SDA auf high ist.

Hallo nochmal eine kurze Rückmeldung.

Ich konnte das ganze gestern Abend testen, die erzeugten 9 Pulse auf der 
SCL Leitung haben dazu geführt das der MCP7940N die SDA Leitung wieder 
freigibt.

Ich musste danach die Pins noch wieder als INPUT konfigurieren und 
konnte dann anschließend wieder mit Wire.begin() den Bus neu 
initialisieren danach gab es keine Probleme mehr mit dem Bus.

Egal wie oft man den ESP resettet. Auch konnte die RTC Batterie nun drin 
bleiben. Funktioniert so wie ich es von meinen anderen Projekten kenne.

Habe mich aber für die Funktion von den oberen Link entschieden da dort 
ja doch ein paar mehr Fälle abgehandelt werden und entsprechend 
Statuscodes zurückgegeben werden. Wenn der Bus danach nicht frei ist 
hält die Anwendung jetzt an und gibt eine Fehlernachricht auf dem Matrix 
Display aus.

In der Hinsicht danke für eure Hilfe.

Eine Frage hätte ich noch aus Interesse, hier handelte es sich ja wohl 
um ein Softwareproblem da das I2C Interface in Software realisiert 
wurde. Wie ist das bei "echten" I2C Interfaces also die als Hardware 
Baustein im Controller vorhanden sind wie beim AVR/STM32 oder ESP32? 
Machen die sowas automatisch während der Initialisierung? Ich meine wenn 
ich jetzt ein Reset am AVR über den Resetpin auslöse und der AVR die 
Uhrzeit gerade abfragt via I2C weiß die RTC das ja auch nicht das ein 
Reset am AVR gekommen ist.

Ich meine die Konstellation aus MCP7940(RTC) + M24C32(EEPROM) und 
INA219(Stromsensor) hatte ich bei meinem letzten Projekt verwendet dort 
kam als CPU ein ATMega1284P zum Einsatz welcher ja ein echtes TWI 
Hardware Interface hat und dort gabs keine Probleme wenn man ein 
HW-Reset am AVR ausgelöst hat mit dem I2C Bus.

D. J. schrieb:
> Sollte aber, ist nicht gut. Es sei denn, es ist ein Ausgang.

Zu Pin 7 im Datenblatt steht ja das es ein Ausgangspin für Alarm und 
Rechteckfunktion ist und das er als steuerbaren Ausgang mit dem OUT-Bit 
im Control register gesteuert werden kann.

Es steht auch drin das dieser Pin als Open-Drain ausgeführt ist und ein 
Pullup Widerstand benötigt damit er funktioniert. Aber auch das dieser 
Pin offen gelassen werden kann wenn er nicht benötigt wird.

Unter 5.5 Output Configurations steht zum MFP Pin auch noch:

"If none of the output functions are being used, the MFP can safely be 
left floating."

Sehe kein Grund ihn zu beschalten wenn ich ihn nicht brauche. Ich hab 
ihn auch noch nie gebraucht und auch noch ne beschaltet hat bis jetzt 
noch nie Probleme gemacht.

Mfg

von Peter D. (peda)


Lesenswert?

Felix N. schrieb:
> Wie ist das bei "echten" I2C Interfaces also die als Hardware
> Baustein im Controller vorhanden sind wie beim AVR/STM32 oder ESP32?
> Machen die sowas automatisch während der Initialisierung? Ich meine wenn
> ich jetzt ein Reset am AVR über den Resetpin auslöse und der AVR die
> Uhrzeit gerade abfragt via I2C weiß die RTC das ja auch nicht das ein
> Reset am AVR gekommen ist.

Bei den alten Philips-MCs mit HW-I2C (P80C552 .. P89C668) wurde das 
berücksichtig, d.h. das HW-I2C erzeugt automatisch die Pulse auf SCL:

"If the SDA line is obstructed by another device on the bus (e.g., a 
slave device out of bit synchronization), the problem can be solved by 
transmitting additional clock pulses on the SCL line (see Figure 14). 
The SIO1 hardware transmits additional clock pulses when the STA flag is 
set, but no START condition can be generated because the SDA line is 
pulled LOW while the I2C bus is considered free. The SIO1 hardware 
attempts to generate a START condition after every two additional clock 
pulses on the SCL line. When the SDA line is eventually released, a 
normal START condition is transmitted, state 08H is entered, and the 
serial transfer continues."

Zumindest die älteren AVRs und 89C51 von Atmel/Michrochip kacken aber 
gnadenlos ab. Da muß man das HW-I2C abschalten und die SCL-Pulse zu Fuß 
machen.

Daß das mit dem RTC passiert, liegt wohl daran, daß Du ihn ständig 
ausliest, den EEPROM aber nur selten. Daher ist es wahrscheinlich, daß 
ein CPU-Reset dazwischen haut.

Ich benutze als RTC den RX8010SJ, der disabled sich automatisch nach 1s:
"When accessing this device, all communication from transmitting the 
start condition to transmitting the stop condition after access should 
be completed within 0.95 seconds. If such communication requires 0.95 
seconds or longer, the I2C bus interface is reset by the internal bus 
timeout function."

: Bearbeitet durch User
von D. J. (basteldag)


Lesenswert?

Sorry für meine Aussage zum Pin7. Ich hatte hier ein nocht komplettes 
Datenblatt (schlechte Kopie) wo nicht ersichtbar, das es ein Ausgang 
ist. Neue Suche im Netz fand ich was gescheiteres. Also sorry für meine 
Aussage.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.