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 имеет достаточно места на флэш-памяти для этого)

Вы можете загрузить эти библиотеки в Adafruit CircuitPython Bundle здесь. (Я скачал adafruit-circuitpython-bundle-7.x-mpy-20211123.zip)

Примечание: для установки этих библиотек просто скопируйте их в папку lib на "диске" CIRCUITPY, который установлен на вашем компьютере. Конечно, вам придется скопировать только библиотеки, а не примеры и другие материалы.

Большим преимуществом использования материалов Adafruit является то, что вы получаете тонну примеров, которые охватывают многие популярные микросхемы, и вы можете очень легко начать с них. Есть такие вещи, как управление картой microSD с помощью SPI, чтение RTC и чтение с датчика BME680.

Тестирование I2C в CircuitPython

У меня следующая установка, поскольку я хочу управлять двумя устройствами независимо друг от друга (которые в данном случае имеют одинаковые адреса):

Feather RP2040 и два Разрывные платы BME688

Обратите внимание, что наши разрывные платы BME688 уже содержат подтяжки для SDA и SCL. (Вам нужны подтяжки на 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). Вам не нужно задавать конфигурацию (какой контроллер вы хотите использовать, или как объединить пины) - об этом позаботятся busio для вас.

Однако вам следует обратить внимание на то, какие контакты вы используете, поскольку контакты будут обеспечивать только один этих шин в каждом случае, и если вы случайно выберете конфликтующие контакты, вы получите ValueError: Используется периферийное устройство I2C .

Adafruit Feather RP2040 Pinout

Если вы хотите использовать "конфликтующие" контакты, например SCL / SDA (которые имеют SCL1 и SDA1) и A0 / A1 (которые также имеют SCL1 и SDA1), вам нужно будет сделать битбанг одного из портов:

Вот как просканировать эту конфигурацию выводов без вызова deinit():

импортный борт
импортировать busio
импортировать битбангио
# 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 - см. рисунок распиновки Adafruit Feather RP2040 в этой статье).

В случае если вы хотите использовать тот же набор выводов, вы можете использовать bitbangio для "создания" дополнительного программно-управляемого порта I2C. Недостатком этого является более низкая скорость для этого программного порта I2C, а также более высокая загрузка процессора.

RuntimeError: Не найдена подтяжка на SDA или SCL; проверьте проводку

Если вы получите следующую ошибку

RuntimeError: Не найдена подтяжка на SDA или SCL; проверьте проводку

тогда вам следует установить подтягивающие резисторы между 3V3 на плате (вывод 3.3V) и соответственно вашими выводами SDA и SCL. Они необходимы для нормальной работы I2C (устройства подтягивают контакты I2C для связи, по умолчанию / в состоянии простоя на шине высокий уровень) - и не включены в Adafruit Feather RP2040. Они включены во многие периферийные устройства Adafruit, а также в периферийные устройства других компаний (например, опять же, наши собственные Разрывная плата BME688).

Если вы не знаете, что такое подтягивание: это, по сути, резистор между соответствующим выводом (например, SDA) и выводом питания 3,3 В. Он не должен быть очень точным. Начинать следует с резисторов 10 кОм, если это не работает, возможно, попробуйте резистор 1 кОм для более "жесткой" подтяжки.

TimeoutError: Слишком большой промежуток времени

Проверьте, правильно ли подано питание на микросхему, с которой вы хотите поговорить.

Разные заметки

Ссылки / Ресурсы / Ссылки / Дальнейшее чтение

Комментировать