Продолжаем осваивать различные модули Raspberry Pi, так вот сегодня пришла очередь разобрать работу с шиной I2C. Не будем ходить вокруг да около, а сразу же перейдем к делу. И начнем с постановки задачи, которую будем решать в этой статье.
Итак, возьмем какое-нибудь устройство, работающее по I2C и подключим его к Raspberry Pi. У меня под рукой обнаружилась такая плата с 9-осевым датчиком MPU-9250:
Вполне подойдет для экспериментов. Естественно, выбор именно этого устройства не накладывает никаких ограничений на работу с шиной. То есть все, что мы сегодня разберем на примере MPU-9250 актуально и для любых других устройств, подключенных по I2C.
Схема подключения выглядит следующим образом:
При работе с I2C обязательно нужны подтягивающие резисторы, которые подтягивают линии SDA и SCL к напряжению питания:
В моем случае эти резисторы уже распаяны на плате с MPU-9250, так что дополнительных действий не требуется. На этом с подключением заканчиваем и переходим к программной части статьи.
Включение I2C на Raspberry Pi.
Первым делом нам следует включить интерфейс I2C. Для этого воспользуемся утилитой для конфигурации Raspberry Pi - raspi-config. Вводим в терминале команду:
sudo raspi-config
Далее переходим в пункт Interfacing options и включаем I2C:
После этого необходимо перезапустить плату:
sudo reboot
Альтернативным способом включения I2C является редактирование файла /boot/config.txt. В файле находим и раскомментируем строку:
dtparam=i2c_arm=on
После чего аналогичным образом перезапускаем плату. При следующем включении модуль I2C будет активирован. Оба этих способа можно использовать, подключившись к плате по SSH.
Работа с I2C через консоль.
Для I2C, как и для других модулей платы, существуют разные варианты и методы использования. И начнем мы с применения команд непосредственно в консоли, в чем нам поможет пакет i2c-tools. Устанавливаем командой:
sudo apt-get install -y i2c-tools
После успешной установки мы можем использовать команду i2cdetect для просмотра доступных шин I2C:
i2cdetect -l
Результат выполнения в моем случае выглядит так:
Из вывода команды следует, что у нас активирована шина i2c-1, которую мы и будем использовать. Для новых версий плат Raspberry Pi всегда по умолчанию используется именно i2c-1. Для более старых же модификаций, например Raspberry Pi Model B с оперативной памятью 256 МБ, будет использована шина i2c-0.
Двигаемся дальше, следующая команда, которую мы рассмотрим:
sudo i2cdetect -y 1
Цифра 1 здесь как раз и относится к тому, что мы будем работать с шиной i2c-1. Кроме того, используем ключ -y. По умолчанию команда i2cdetect ожидает подтверждения от пользователя прежде, чем вмешиваться в работу шины, а ключом -y мы даем ей добро на работу с I2C без дополнительного разрешения.
Итак, вывод этой команды может быть таким:
Здесь мы видим все подключенные к I2C устройства и их адреса. Поскольку я подключил датчик MPU-9250, адрес которого - 0x68, то его мы тут и обнаружили:
Кроме того, пакет i2c-tools включает в себя ряд других команд для работы с шиной, в частности:
- i2cdump - позволяет прочитать значения всех регистров подключенного к шине устройства. Например:
i2cdump -y 1 0x68
Здесь мы снова указываем номер шины (1), а также адрес устройства, регистры которого хотим проанализировать (0x68). Здесь выделено одно значение, а именно 0x71, соответствующее регистру с адресом 0x75. Из документации на датчик мы можем определить, что именно такое значение и должно быть у этого регистра.
- i2cget - чтение значения конкретного регистра определенного устройства. Конечно, же рассмотрим пример:
i2cget -y 1 0x68 0x75
Считываем значение все того же регистра с адресом 0x75 и проверяем, верное ли значение выдает команда:
- i2cset - запись определенного значения в регистр устройства. И снова не обходимся без примера:
i2cset -y 1 0x68 0x1A 0x03
Здесь мы последовательно указываем - номер шины, адрес устройства, адрес регистра и значение, которое будет записано в этот регистр. В данном случае записываем в регистр с адресом 0x1A значение 0x03.
На этом завершаем работу с I2C через консоль, мы рассмотрели все основные и необходимые операции и переходим к работе с I2C при помощи Python.
Работа с I2C на Python.
Для работы с шиной I2C необходимо установить пакет python-smbus:
sudo apt-get install -y python-smbus
По традиционной схеме создаем файл, в котором и будем писать код для работы с I2C, назовем файл, к примеру, i2c_test.py. Ну и для наглядной демонстрации прочитаем значение все того же регистра с адресом 0x75 и сравним результаты. Собственно, пишем минимально необходимый для этого код:
from smbus import SMBus bus = SMBus(1) data = bus.read_byte_data(0x68, 0x75) print(hex(data)) bus.close()
Давайте разберем, что тут происходит, поэтапно. Делаем import библиотеки:
from smbus import SMBus
Открываем использующуюся у нас шину i2c-1:
bus = SMBus(1)
И, наконец, читаем значение регистра, выводим его на экран и заканчиваем работу с I2C:
data = bus.read_byte_data(0x68, 0x75) print(hex(data)) bus.close()
Первый аргумент функции - адрес устройства, второй - адрес регистра. Запускаем выполнение кода:
python i2c_test.py
И в результате видим верное значение регистра:
А это говорит нам о том, что код сработал абсолютно верно. Напоследок, рассмотрим некоторые другие функции библиотеки smbus, которые можно использовать по своему усмотрению:
Функция | Описание |
---|---|
long read_byte(int addr) | Чтение байта данных |
long write_byte(int addr, char val) | Запись байта данных |
long read_byte_data(int addr, char cmd) | Чтение значения регистра |
long write_byte_data(int addr, char cmd, char val) | Запись значения в регистр |
long[] read_block_data(int addr, char cmd) | Чтение блока данных (до 32-х байт) из регистра |
write_block_data(int addr, char cmd, long vals[]) | Запись блока данных в регистр |
long read_word_data(int addr, char cmd) | Чтение слова (2-х байт) из регистра |
long write_word_data(int addr, char cmd, int val) | Запись слова (2-х байт) в регистр |
На этом заканчиваем обзор работы с шиной I2C для Raspberry Pi, на очереди - интерфейс SPI, который будем запускать в следующей статье.