Forum: Mikrocontroller und Digitale Elektronik ESP8266 Micropython : I2C


von chris (Gast)


Lesenswert?

Da mir der Download auf den ESP zu langsam geht, will ich vermehrt auf 
Micropython setzen.

Ich habe einen MPU6050 über I2C angeschlossen.
https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython

Aber leider gibt es Probleme: Während ein Code-Beispiel aus der Arduino 
IDE direkt funktioniert, meldet sich der Sensor unter Micropython erst, 
wenn ich den Logik-Analysator zum debuggen anhänge.

Hat schon mal jemand ein ähnliches Problem mit I2C unter Micropython 
gehabt?

von Weinga U. (weinga-unity)


Lesenswert?

Pull-Up Widerstände drinnen?

Lg.

von Stefan F. (Gast)


Lesenswert?

Oder es fehlt eine GND Verbindung.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

>Pull-Up Widerstände drinnen?
Ich verwende das typische MPU6050 BreakOut-Board ( s.o. )
und hoffe den richtigen Schaltplan gefunden zu haben. Dort sind die 
PullUps auf dem Board.

>Oder es fehlt eine GND Verbindung.
Das habe ich "durchgepieped".

Wie gesagt: Arduino Treiber funktioniert auf Anhieb, Micropython nur mit 
angehängten LA-Leitungen.

Im Micropythontreiber gibt es einen Test:

>>>from machine import I2C, Pin
>>>import mpu6050
>>>i2c = I2C(scl=Pin(5), sda=Pin(4))
>>>accelerometer = mpu6050.accel(i2c)
>>>accelerometer.val_test()

Der Test steigt nach einer weile aus, was aber auch als Kommentar im 
Treiber zu finden ist:
https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython/blob/master/mpu6050.py

Kann es sein, dass die I2C-Schnittstelle in Micropython ziemlich 
unsauber programmiert ist?
Weiß jemand, wo der Source-Code zu finden ist?

von bingo (Gast)


Lesenswert?

Der alte Fehler bei I2C: 4k7 sind als Pullup für 3.3V viel zu hoch. Ich 
würde deutlich weniger nehmen, evtl. bis unter 1k.

Weiteres siehe www.ti.com/lit/an/slva689/slva689.pdf

von chris (Gast)


Angehängte Dateien:

Lesenswert?

>Der alte Fehler bei I2C: 4k7 sind als Pullup für 3.3V viel zu hoch. Ich
>würde deutlich weniger nehmen, evtl. bis unter 1k.

Hört sich gut an. Zum Test habe ich mal 3.3K Widerstände auf der 
ESP-Seite gegen ESP3.3V gehängt. Ergebnis: geht nicht mehr.

Das Bild im Anhang zeigt die Signale des LA ohne weitere Widerstände ( 
laut Datenblatt ist die Adresse des MPU6050 0x68. Der LA zeigt das ACK 
aber bei der doppelten Adresse 0xD0 ).

VCC des MPU6050 hängt am Pin VIN des ESP ( gemessen VIN=4.27 V ). Der 
ESP wird über das USB-Kabel versorgt.

Gegen die Theorie der zu niedrigen Widerstände spricht, dass es mit dem 
Arduino-Treiber direkt funktioniert. Das würde eher auf unterschiedliche 
Timings der Treiber hin deuten.

von chris (Gast)



Lesenswert?

Hier die Signale des LA, wenn die 3.3K gegen 3.3V des ESP geschaltet 
sind.
Die Signale werden vom LA noch gut erkannt, der MPU6050 antwortet aber 
nicht mehr.

von Max D. (max_d)


Lesenswert?

Wie ist denn die Anordnung verkabelt? Deine mpu Platine enthält einen 
ldo. Der ist je nach Versorgung nicht so glücklich...

von Stefan F. (Gast)


Lesenswert?

Die Adresse ist immer 7 Bit, gefolgt von dem Read/Write Bit.

0x68 = 1101000

Wenn du da jetzt noch das letzte Bit für die Steuerung der Datenrichtung 
(Read/Write) dran hängst, kommst du auch 0xD0 oder 0xD1. Das ist der 
Wert, der dein Logic Analyzer anzeigt.

Also soweit alles richtig.

Eine analoge Messung der Signalqualität wäre hier hilfreicher.

Was die Timings angeht: Kontrolliere mal die Setup und hold Zeiten, der 
SDA Leitung.

Setup: Die kürzeste Zeit zwischen dem Ändern des SDA Pegel und der 
steigenden Takt-Flanke.
Hold: Die kürzeste Zeit zwischen der fallenden Takt-Flanke und der 
nächsten Änderung des SDA Signals.

Vergleiche, ob sie mit dem Datenblatt überein stimmen. Auf den ersten 
Blick erscheinen mit die Hold-Zeiten auffällig kurz.

Im Grenzbereich spielen hier sicher die konkreten Spannungspegel eine 
Rolle (Ab wann erkennt der MPU Chip High und ab wann erkennt er Low?), 
die du aber nur mit einem analogen Messgerät erfassen kannst.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hier die analogen Signale.
Ein Versuch mit nur 100kHz I2C-Frequenz

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)

bringt keine Besserung.

Der Aufbau ist mit Prototyping Board und ca. 10cm Patchkabeln. Also in 
keiner Weise EMV-fest.

Meine These: Auf den Zuleitungen entstehen bei den Schaltflanken von SCL 
und SDA sehr hochfrequente Schwingungen, die den MPU6050 vielleicht 
fäschlicherweise als STOP-Condition interpretiert.

von Stefan F. (Gast)


Lesenswert?

> sehr hochfrequente Schwingungen

Glaube ich nicht.

Auch in deinem Oszilloskop Bild sehe ich wieder auffällig kurze Hold 
Zeiten.

Stelle das Gerät mal so ein, dass man die zweite fallende Flanke der 
roten Linie (und natürlich auch die blaue dazu) viel detaillierter 
sieht.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

>Stelle das Gerät mal so ein, dass man die zweite fallende Flanke der
>roten Linie (und natürlich auch die blaue dazu) viel detaillierter
>sieht.

Hab's gemacht, aber leider nicht abgespeichert. Die Überschwinger sind 
nicht wirklich riesig.

Aber ich traue nach wie vor dem Micropythontreiber nicht.
Im Bild sieht man den Vergleich der Portscan-Signale vom 
Micropythontreiber zu Arduinotreiber.
Der Arduino geht immer.
Das Signal am Ende des Micropyhtontreibers sieht verdachtig anderst aus.

von Stefan F. (Gast)


Lesenswert?

> Die Überschwinger sind nicht wirklich riesig.

Darum geht es mir nicht. Ich will die Hold-Time sehen. Habe ich doch 
schon mehrfach geschrieben!

Was du da markiert hast ist das ACK Signal.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

>Was du da markiert hast ist das ACK Signal.

Meiner Ansicht nacht ist das eher irgend was nach dem ACK-Signal. Und 
dieses Irgendwas könnte den MPU verwirren. Das ACK-Signal ist laut MPU 
Datenblatt "low-active" ( siehe Bild ).
Dazu muss man nur die Arduino-Signale vergleichen: Dort ist der 
High-Pulse nicht sichtbar. Man sieht aber im LA-Bild, dass dort das 
ACK-Signal beim Arduino Treiber korrekt detektiert wird.

von chris (Gast)


Lesenswert?

Mittlerweile habe ich endlich die Sourcen des I2C-Treibers in 
Micropython gefunden:
https://github.com/micropython/micropython/blob/master/extmod/machine_i2c.c

von chris (Gast)



Lesenswert?

Hier das I2C-Signal mit 400kHz in höherer Auflösung und das I2C Timing 
des MPU6050.

von chris (Gast)


Lesenswert?

Wenn ich einen 12pF Kondensator von SCL zu GND auf der ESP-Seite 
einfüge, geht der Micropythontreiber auch ...

von Karl (Gast)


Lesenswert?

chris schrieb:
> Meine These: Auf den Zuleitungen entstehen bei den Schaltflanken von SCL
> und SDA sehr hochfrequente Schwingungen, die den MPU6050 vielleicht
> fäschlicherweise als STOP-Condition interpretiert.

Meine These: Das ist Übersprechen der Leitungen beim Schalten. Das gibt 
es aber eigentlich erst bei längeren parallel verlaufenden 
SCL-SDA-Leitungen.

Entweder hast Du da ein GND-Problem, oder:

Diese Signale sehen komisch aus. Normalerweise ist die steigende Flanke 
die Ladekurve eines Kondensators, nämlich aus Kabel+Eingangskapazität, 
durch einen Widerstand, nämlich den Pullup.

Hier scheint aber der ESP die Signale aktiv hochzuziehen. Was auch das 
übersprechen erklären würde. Wenn das stimmt, hätte jemand aber I2C 
überhaupt nicht verstanden.

von Wolfgang (Gast)


Lesenswert?

bingo schrieb:
> Der alte Fehler bei I2C: 4k7 sind als Pullup für 3.3V viel zu hoch. Ich
> würde deutlich weniger nehmen, evtl. bis unter 1k.

Und dann kommt der nächste und sagt, dass das zu wenig ist, weil bei den 
I2C-Treiber nur ein Strom von 3mA spezifiziert ist.

Application Report - I2C Bus Pullup Resistor Calculation
http://www.ti.com/lit/an/slva689/slva689.pdf

von chris (Gast)


Lesenswert?

>Hier scheint aber der ESP die Signale aktiv hochzuziehen. Was auch das
>übersprechen erklären würde. Wenn das stimmt, hätte jemand aber I2C
>überhaupt nicht verstanden.

Der Code für I2C sieht für mich so aus, als wenn die Portrichtung 
umgeschaltet wird. Wenn er auf Eingangs steht, sollte er hochohmig sein.

Was micht irritiert ist, dass es mit dem Arduino-Treiber geht.
Wenn ich den 12pF Kondensator einfüge, läuft auch der 
Micropythontreibertest bis jetzt ohne Unterbrechung stabil.

von Karl (Gast)


Lesenswert?

chris schrieb:
> Wenn ich den 12pF Kondensator einfüge

Was nach einem Timingproblem klingt.

Beide Leitungen haben die selbe kapazitive Last? (Tastköpfe, Kabellänge)
Was passiert wenn Du die Taktfrequenz verringerst?
Was passiert wenn Du die Leitungskapazität gleichmäßig erhöhst (je 100pF 
gegen GND)? Gibt es im Oszibild einen exponentiellen Anstieg (Ladekurve) 
der Flanken?
Wie sieht das erste Byte (Adresse) bei beiden Codes aus?

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Langsam komme ich der Sache näher.
Beim Micropythontreiber springt die SCL-Flanke schlagartig auf etwas 
über 1V und läuft dann Kondensatormassig ein. Beim Arduinotreiber ist 
die Flanke schön kontinuierlich.
Es sieht also so aus, als wenn der Mikropythontreiber seinen Ausgang für 
eine sehr kurze Zeit auf Output-High schaltet, was für den I2C verboten 
ist.

Mein Untersuchungen hier beziehen sich auf die aktuelle Firmwareversion
esp8266-20171101-v1.9.3.bin (elf, map) (latest)
von
http://micropython.org/download

von chris (Gast)


Lesenswert?

Die Schlussfolgerung ist also, dass ein Problem im Treiber vorliegt und 
nicht in der Hardware.

Die Funktionen für SCL finden sich hier:

https://github.com/micropython/micropython/blob/master/extmod/machine_i2c.c
1
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
2
    mp_hal_pin_od_low(self->scl);
3
}
4
5
STATIC int mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
6
    uint32_t count = self->us_timeout;
7
8
    mp_hal_pin_od_high(self->scl);
9
    mp_hal_i2c_delay(self);
10
    // For clock stretching, wait for the SCL pin to be released, with timeout.
11
    for (; mp_hal_pin_read(self->scl) == 0 && count; --count) {
12
        mp_hal_delay_us_fast(1);
13
    }
14
    if (count == 0) {
15
        return -MP_ETIMEDOUT;
16
    }
17
    return 0; // success
18
}

Es gibt also ein Funktion, um den SCL-Pin auf 0 zu ziehen. Diese scheint 
korrekt zu funktionieren.
Das Problem muss also in "mp_hal_i2c_scl_release" stecken.

Was das Macro "mp_hal_pin_od_high" machen soll, ist mir nicht ganz klar.
Das ist etwas ärgerlich. Die heutigen Programmierstile sollen so sein, 
dass die Funktion durch ihren Namen ausreichend verständlich beschrieben 
ist:
1
#define mp_hal_pin_od_low(p) do { \
2
        if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); } \
3
        else { gpio_output_set(0, 1 << (p), 1 << (p), 0); } \
4
    } while (0)
5
#define mp_hal_pin_od_high(p) do { \
6
        if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); } \
7
        else { gpio_output_set(1 << (p), 0, 1 << (p), 0); } \
8
    } while (0)

von Stefan F. (Gast)


Lesenswert?

> Hier das I2C-Signal mit 400kHz in höherer Auflösung

Super. Hier kann man eine deutliche Data-Hold Zeit von ca 0,5µS sehen. 
Das ist zwar nicht viel, aber sicher ausreichend, denn das Datenblatt 
verlangt 0µS.

Wenn die beiden Flanken fast Zeitgleich gewesen wären, hätte ich das 
hier moniert.

Bei vielen Mikrocontrollern kann man die Ausgänge als Open-Drain 
initialisieren. Ich meine, dass der ESP8266 das auch kann. In diesem 
Fall bedeutet High, dass der Ausgang hochohmig ist. Danach würde ich mal 
suchen.

von chris (Gast)


Lesenswert?

Also ich habe mal folgendes probiert:

>>> Pin(5,Pin.OUT)
>>> Pin(5,Pin.IN)

Damit ist kein Glitch sichtbar. Das heißt, der Pintreiber selbst wäre 
also geeignet, um den I2C-Bus richtig anzusteuern.

Jetzt habe ich 3 Lösungsmöglichkeiten, den I2C-Bus in Micropython 
zusammen mit dem MPU6050 ans Laufen zu bringen.

1. Kondensator in SCL-Leitung, umd Treiberfehlerglitch wegzubügeln
2. Einen reinen Python-I2C-Bitbangingtreiber schreiben
3. Den Fehler im Treiber lokalieren und das ganze Python neu kompilieren

Ich glaube, ich nehme Nr.1. Das ist zwar unsauber, aber am Einfachsten.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hier als der Software durch Hardware-Reperatur-Hack ;-)

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.