CircuitPython, Adafruit Feather RP2040 und I2C

Der RP2040 hat zwei I2C-Controller - gut, wenn man z.B. zwei I2C-Geräte mit der gleichen I2C-Adresse betreiben will.

In meinem Testaufbau habe ich ein Adafruit Feather RP2040 Mikrocontroller-Board und zwei unserer BME688-Breakout-Karten - eine mit den Stiften SCL + SDA und eine mit A1 (für SCL) + A0 (für SDA).

Ich verwende CircuitPython in der Version 7.0.0, die Sie hier herunterladen können.

Außerdem habe ich alle Bibliotheken von Adafruit in der lib Ordner auf dem Feather RP2040. (Der Feather RP2040 verfügt über genügend Speicherplatz auf seinem Flash, um dies zu ermöglichen)

Sie können diese Bibliotheken in der Adafruit CircuitPython Bundle hier. (Ich habe heruntergeladen adafruit-circuitpython-bundle-7.x-mpy-20211123.zip)

HinweisUm diese Bibliotheken zu installieren, kopieren Sie sie einfach in den Ordner "lib" auf dem "Laufwerk" von CIRCUITPY, das sich auf Ihrem Computer befindet. Sie müssen natürlich nur die Bibliotheken kopieren, nicht die Beispiele und andere Dinge.

Der große Vorteil bei der Verwendung von Adafruits Material ist, dass Sie eine Tonne von Beispielen, die viele beliebte Chips abdecken, und Sie können sehr leicht mit ihm beginnen. Es gibt Dinge wie das Ansteuern einer microSD-Karte über SPI, das Auslesen einer RTC und das Auslesen des BME680-Sensors.

I2C in CircuitPython testen

Ich habe die folgende Konfiguration, da ich zwei Geräte unabhängig voneinander ansteuern möchte (die in diesem Fall zufällig die gleichen Adressen haben):

Feather RP2040 und zwei BME688-Breakout-Karten

Beachten Sie, dass unsere BME688-Breakout-Boards bereits Pullups für SDA und SCL enthalten. (Sie benötigen Pullups an SDA und SCL).

Hinweis 2: Unser BME688-Breakout-Board hat die Möglichkeit, die Adresse zu ändern, daher ist dieses Szenario für Demonstrationszwecke gedacht.

Um beide Pinsätze sequentiell zu durchlaufen (um die Geräte zu erkennen), verwende ich den folgenden Code:

print("SCL / SDA abtasten")
i2c = busio.I2C(Karte.SCL, Karte.SDA)
# ein Scan
i2c.try_lock()
print(i2c.scan())
i2c.unlock()
i2c.deinit()

print("A0 / A1 abtasten")
si2c = busio.I2C(Karte.A1, Karte.A0)
# eine Abtastung
si2c.try_lock()
print(si2c.scan())
si2c.unlock()

Anmerkung: Die i2c.deinit() ist der Schlüssel zum Funktionieren dieses speziellen Beispiels! (weil SCL / SDA und A0 / A1 beide die gleiche Hardware-I2C-Peripherie haben - siehe unten).

Dies sollte die folgende Ausgabe ergeben:

Abtastung SCL / SDA
[119]
Abtastung A0 / A1
[119]

Hier ist 119 dezimal für hex 0x77 - was die Adresse unseres BME688-Breakout-Boards im Standardzustand ist.

Beide Tafeln sind nacheinander in den einzelnen Scans zu sehen.

Das Problem ist, dass wir sie gleichzeitig nutzen wollen.

Zwei I2C-Busse gleichzeitig auf dem Adafruit Feather RP2040 betreiben

CircuitPython unterstützt beide Hardware-Controller (SDA0/SCL0 und SDA1/SCL1). Sie müssen keine Konfiguration vornehmen (welcher Controller verwendet werden soll oder wie die Pins gemischt werden sollen) - dies wird von busio für Sie.

Sie müssen jedoch darauf achten, welche Stifte Sie verwenden, da die Stifte nur eine eine dieser Busse in jedem Fall, und wenn Sie zufällig widersprüchliche Pins wählen, erhalten Sie WertFehler: I2C-Peripheriegerät in Gebrauch .

Adafruit Feather RP2040 Pinout

Wenn Sie "kollidierende" Pins verwenden wollen, z.B. SCL / SDA (die SCL1 und SDA1 haben) und A0 / A1 (die auch SCL1 und SDA1 haben), müssen Sie einen der Ports bitbangen:

So scannen Sie diese Pin-Konfiguration, ohne deinit() aufzurufen:

Importtafel
importieren busio
importieren bitbangio
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/bitbangio/index.html

print("SCL / SDA abtasten - Haupt-I2C")
i2c = busio.I2C(Karte.SCL, Karte.SDA)
# ein Scan
i2c.try_lock()
print(i2c.scan())
i2c.unlock()
# hier muss nicht deinit aufgerufen werden!
#i2c.deinit()

print("A0 / A1 scannen - sekundäres I2C [bitbang!]")
si2c = bitbangio.I2C(Karte.A1, Karte.A0)
# ein Scan
si2c.try_lock()
print(si2c.scan())
si2c.unlock()

# wir brauchen hier auch nicht deinit aufrufen
#i2c.deinit()

Wir verwenden bitbangio zur Ansteuerung eines sekundären I2C. In meinem Fall wird das sekundäre I2C für einen internen Zweck verwendet (für einen Port-Expander) und kann wahrscheinlich mit einer niedrigeren Schnittstellengeschwindigkeit auskommen.

Hinweis: Sie können die I2C-Peripherie, die auf die Pins geroutet wird, nicht in der Software auswählen - wenn Sie eine andere Peripherie benötigen, müssen Sie andere Pins verwenden.

Fehlerbehebung bei I2C-Fehlern

WertFehler: I2C-Peripheriegerät in Gebrauch

Wenn Sie busio.I2C für beide Ports verwenden: Prüfen Sie, ob Sie bereits die gleiche Hardware-I2C-Peripherie verwenden - und ob Sie Ihre Pins neu zuordnen müssen.

Zum Beispiel teilen sich sowohl SCL und SDA als auch A0 und A1 die gleiche Hardware-I2C-Peripherie (SCL1 / SDA1 - siehe das Bild der Adafruit Feather RP2040 Pinbelegung in diesem Artikel).

Für den Fall, dass Sie die gleiche Pin-Konfiguration verwenden möchten, können Sie mit bitbangio einen zusätzlichen softwaregesteuerten I2C-Port "erstellen". Der Nachteil dabei ist eine geringere Geschwindigkeit für diesen Software-I2C-Port und eine höhere CPU-Last.

RuntimeError: Kein Pull-Up an SDA oder SCL gefunden; überprüfen Sie Ihre Verdrahtung

Wenn Sie die folgende Fehlermeldung erhalten

RuntimeError: Kein Pull-Up an SDA oder SCL gefunden; überprüfen Sie Ihre Verdrahtung

dann sollten Sie Pullup-Widerstände zwischen 3V3 auf dem Board (dem 3,3V-Pin) und Ihren SDA- bzw. SCL-Pins setzen. Diese sind für den normalen I2C-Betrieb erforderlich (die Geräte ziehen die I2C-Pins herunter, um zu kommunizieren, der Standard-/Idle-Zustand auf dem Bus ist hoch) - und sind nicht auf dem Adafruit Feather RP2040 enthalten. Sie sind bei vielen Adafruit-Peripheriegeräten und bei Peripheriegeräten anderer Firmen enthalten (wie z.B. auch bei unseren eigenen BME688-Breakout-Platine).

Falls Sie nicht wissen, was ein Pullup ist: Dies ist im Wesentlichen ein Widerstand zwischen dem betreffenden Pin (z. B. SDA) und dem 3,3-V-Versorgungspin. Er muss nicht furchtbar genau sein. Sie sollten mit 10 kOhm-Widerständen beginnen, wenn das nicht funktioniert, versuchen Sie es vielleicht mit einem 1 kOhm-Widerstand für einen "steiferen" Pullup.

ZeitüberschreitungFehler: Zeitspanne zu lang

Prüfen Sie, ob der Chip, mit dem Sie sprechen wollen, ordnungsgemäß mit Strom versorgt wird.

Diverse Notizen

Referenzen / Ressourcen / Links / Weiterführende Literatur

Hinterlassen Sie einen Kommentar