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?
>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?
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
>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.
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.
Wie ist denn die Anordnung verkabelt? Deine mpu Platine enthält einen ldo. Der ist je nach Versorgung nicht so glücklich...
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.
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.
> 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.
>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.
> 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.
>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.
Mittlerweile habe ich endlich die Sourcen des I2C-Treibers in Micropython gefunden: https://github.com/micropython/micropython/blob/master/extmod/machine_i2c.c
Hier das I2C-Signal mit 400kHz in höherer Auflösung und das I2C Timing des MPU6050.
Wenn ich einen 12pF Kondensator von SCL zu GND auf der ESP-Seite einfüge, geht der Micropythontreiber auch ...
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.
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
>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.
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?
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
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)
|
> 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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.