CircuitPython, Adafruit Feather RP2040 και I2C

Το RP2040 διαθέτει δύο ελεγκτές I2C - καλό για παράδειγμα, όταν θέλετε να τρέξετε δύο συσκευές I2C με την ίδια διεύθυνση I2C.

Στη δοκιμαστική μου εγκατάσταση, έχω μια πλακέτα μικροελεγκτή Adafruit Feather RP2040 και έχω συνδέσει δύο από τα Πλακέτες διάσπασης BME688 - μία με χρήση των ακροδεκτών SCL + SDA και μία με χρήση των A1 (για SCL) + A0 (για SDA).

Χρησιμοποιώ το CircuitPython στην έκδοση 7.0.0, το οποίο μπορείτε να κατεβάσετε από εδώ.

Επιπλέον, έχω εγκαταστήσει όλες τις βιβλιοθήκες της Adafruit στο αρχείο lib στο φάκελο Feather RP2040. (Το Feather RP2040 έχει αρκετό χώρο στο Flash για να το επιτρέψει αυτό)

Μπορείτε να κατεβάσετε αυτές τις βιβλιοθήκες στο Adafruit CircuitPython Bundle εδώ. (Κατέβασα adafruit-circuitpython-bundle-7.x-mpy-20211123.zip)

Σημείωση: για να εγκαταστήσετε αυτές τις βιβλιοθήκες απλά αντιγράψτε τις στο φάκελο lib στο "δίσκο" του CIRCUITPY που είναι τοποθετημένος στον υπολογιστή σας. Φυσικά θα πρέπει να αντιγράψετε μόνο τις βιβλιοθήκες, όχι τα παραδείγματα και άλλα πράγματα.

Το μεγάλο πλεονέκτημα στη χρήση των υλικών της Adafruit είναι ότι λαμβάνετε έναν τόνο παραδειγμάτων που καλύπτουν πολλά δημοφιλή τσιπ και μπορείτε πολύ εύκολα να ξεκινήσετε με αυτά. Υπάρχουν πράγματα όπως η οδήγηση μιας κάρτας microSD με χρήση SPI, η ανάγνωση ενός RTC και η ανάγνωση από τον αισθητήρα BME680.

Δοκιμή I2C στο CircuitPython

Έχω την ακόλουθη ρύθμιση, καθώς θέλω να οδηγήσω δύο συσκευές ανεξάρτητα η μία από την άλλη (οι οποίες τυχαίνει να έχουν τις ίδιες διευθύνσεις σε αυτή την περίπτωση):

Feather RP2040 και δύο Πλακέτες διάσπασης BME688

Σημειώστε ότι οι πλακέτες BME688 περιλαμβάνουν ήδη Pullups για SDA και SCL. (Χρειάζεστε pullups για τα SDA και SCL).

Σημείωση 2: Η πλακέτα διάσπασης BME688 έχει τη δυνατότητα αλλαγής της διεύθυνσης, οπότε αυτό το σενάριο προορίζεται για σκοπούς επίδειξης.

Για να οδηγήσω διαδοχικά και τα δύο σύνολα ακροδεκτών (για να ανακαλύψω τις συσκευές), χρησιμοποιώ τον ακόλουθο κώδικα:

print("Σάρωση SCL / SDA")
i2c = busio.I2C(board.SCL, board.SDA)
# μια σάρωση
i2c.try_lock()
print(i2c.scan())
i2c.unlock()
i2c.deinit()

print("Σάρωση A0 / A1")
si2c = busio.I2C(board.A1, board.A0)
# μια σάρωση
si2c.try_lock()
print(si2c.scan())
si2c.unlock()

Σημείωση: το i2c.deinit() είναι το κλειδί για να δουλέψει αυτό το συγκεκριμένο παράδειγμα! (επειδή τα SCL / SDA και A0 / A1 έχουν και τα δύο το ίδιο περιφερειακό υλικό I2C - βλ. παρακάτω).

Αυτό θα πρέπει να βγάλει τα ακόλουθα:

Σάρωση SCL / SDA
[119]
Σάρωση A0 / A1
[119]

Εδώ, το 119 είναι δεκαδικό για δεκαεξαδικό 0x77 - η οποία είναι η διεύθυνση της πλακέτας BME688 στην προεπιλεγμένη κατάσταση.

Και οι δύο πίνακες εμφανίζονται διαδοχικά στις μεμονωμένες σαρώσεις.

Το πρόβλημα είναι ότι θέλουμε να τα χρησιμοποιήσουμε ταυτόχρονα.

Εκτέλεση δύο διαύλων I2C ταυτόχρονα στο Adafruit Feather RP2040

Το CircuitPython υποστηρίζει και οι δύο ελεγκτές υλικού (SDA0/SCL0 και SDA1/SCL1). Δεν χρειάζεται να ρυθμίσετε καμία διαμόρφωση (ποιον ελεγκτή θέλετε να χρησιμοποιήσετε ή πώς να κάνετε mux τις ακίδες) - αυτό το αναλαμβάνει το busio για εσάς.

Θα πρέπει να προσέξετε, ωστόσο, ποιες ακίδες θα χρησιμοποιήσετε, καθώς οι ακίδες θα παρέχουν μόνο ένα από αυτούς τους διαύλους σε κάθε περίπτωση, και αν τύχει να επιλέξετε αντικρουόμενους ακροδέκτες, θα έχετε ValueError: I2C σε χρήση .

Adafruit Feather RP2040 Pinout

Αν θέλετε να χρησιμοποιήσετε "αντικρουόμενες" ακίδες, για παράδειγμα SCL / SDA (που έχουν SCL1 και SDA1) και A0 / A1 (που έχουν επίσης SCL1 και SDA1), θα πρέπει να κάνετε bitbang μία από τις θύρες:

Δείτε πώς μπορείτε να σαρώσετε αυτή τη διαμόρφωση ακροδεκτών χωρίς να καλέσετε την deinit():

πίνακας εισαγωγής
εισαγωγή busio
εισαγωγή bitbangio
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/bitbangio/index.html

print("Σάρωση SCL / SDA - κύρια I2C")
i2c = busio.I2C(board.SCL, board.SDA)
# μια σάρωση
i2c.try_lock()
print(i2c.scan())
i2c.unlock()
# δεν χρειάζεται να καλέσετε deinit εδώ!
#i2c.deinit()

print("Σάρωση A0 / A1 - δευτερεύον I2C [bitbang!]")
si2c = bitbangio.I2C(board.A1, board.A0)
# μια σάρωση
si2c.try_lock()
print(si2c.scan())
si2c.unlock()

# επίσης δεν χρειάζεται να καλέσουμε deinit εδώ
#i2c.deinit()

Χρησιμοποιούμε bitbangio για την οδήγηση ενός δευτερεύοντος I2C. Στην περίπτωσή μου, το δευτερεύον I2C χρησιμοποιείται για εσωτερικό σκοπό (για μια επέκταση θύρας) και είναι πολύ πιθανό να μπορεί να τα βγάλει πέρα με χαμηλότερη ταχύτητα διασύνδεσης.

Σημείωση: δεν έχετε τη δυνατότητα να επιλέξετε το περιφερειακό I2C το οποίο δρομολογείται στους ακροδέκτες στο λογισμικό - αν χρειάζεστε διαφορετικό περιφερειακό, πρέπει να χρησιμοποιήσετε διαφορετικούς ακροδέκτες.

Αντιμετώπιση σφαλμάτων I2C

ValueError: I2C σε χρήση

Εάν χρησιμοποιείτε busio.I2C και για τις δύο θύρες: Ελέγξτε αν χρησιμοποιείτε ήδη το ίδιο περιφερειακό I2C υλικού - και αν χρειάζεται να επαναπροσδιορίσετε τις ακίδες σας.

Για παράδειγμα, τόσο το SCL και το SDA , όσο και τα A0 και A1 μοιράζονται το ίδιο περιφερειακό υλικό I2C (SCL1 / SDA1 - δείτε την εικόνα pinout του Adafruit Feather RP2040 σε αυτό το άρθρο).

Σε περίπτωση που θέλετε να χρησιμοποιήσετε την ίδια ρύθμιση ακροδεκτών, μπορείτε να χρησιμοποιήσετε το bitbangio για να "δημιουργήσετε" μια πρόσθετη θύρα I2C ελεγχόμενη από το λογισμικό. Το μειονέκτημα αυτού είναι η χαμηλότερη ταχύτητα για αυτή τη θύρα I2C λογισμικού και το υψηλότερο φορτίο της CPU.

RuntimeError: Ελέγξτε την καλωδίωσή σας.

Εάν λάβετε το ακόλουθο σφάλμα

RuntimeError: Ελέγξτε την καλωδίωσή σας.

τότε θα πρέπει να τοποθετήσετε αντιστάσεις pullup μεταξύ του 3V3 στην πλακέτα (το pin 3.3V) και αντίστοιχα των pin SDA και SCL. Αυτά απαιτούνται για την κανονική λειτουργία του I2C (οι συσκευές κατεβάζουν τις ακίδες I2C για να επικοινωνήσουν, η προεπιλεγμένη / αδρανής κατάσταση στο δίαυλο είναι υψηλή) - και δεν περιλαμβάνονται στο Adafruit Feather RP2040. Περιλαμβάνονται σε πολλές περιφερειακές συσκευές της Adafruit, καθώς και σε περιφερειακές συσκευές άλλων εταιρειών (όπως, και πάλι η δική μας Πλακέτα διάσπασης BME688).

Αν δεν ξέρετε τι είναι το pullup: πρόκειται ουσιαστικά για μια αντίσταση μεταξύ του εν λόγω ακροδέκτη (π.χ. SDA) και του ακροδέκτη τροφοδοσίας 3,3 V. Δεν χρειάζεται να είναι τρομερά ακριβής. Θα πρέπει να ξεκινήσετε με αντιστάσεις 10 kOhm, αν αυτό δεν λειτουργεί, δοκιμάστε ενδεχομένως μια αντίσταση 1 kOhm για ένα πιο "σκληρό" pullup.

TimeoutError: Clock stretch too long

Ελέγξτε αν το τσιπ στο οποίο θέλετε να μιλήσετε τροφοδοτείται σωστά.

Διάφορες σημειώσεις

Αναφορές / Πηγές / Σύνδεσμοι / Περαιτέρω ανάγνωση

Αφήστε ένα σχόλιο