Руководство по подключению и использованию датчика MPU-9265 с 9 степенями свободы (DOF): гироскоп, акселерометр и компас.
MPU-9250 — это инерциальный измерительный блок, включающий в себя 3-осевой гироскоп, 3-осевой акселерометр и 3-осевой компас, обеспечивая 9-осевое отслеживание движения. Он используется в робототехнике, дронах, мобильных устройствах и игровых контроллерах для ориентации и стабилизации. Устройство поддерживает интерфейсы I2C и SPI, питается от 3.3В.
Включение интерфейса I2C
sudo raspi-config
Перейдем в раздел Intefrace options
Затем в I2C
Включим I2C
Перезагрузимся
sudo reboot
Подключение MPU-9265 к Raspberry Pi
Подключим
- VCC MPU-9265 к 3.3V на Raspberry Pi.
- GND MPU-9265 к GND на Raspberry Pi.
- SDA MPU-9265 к GPIO2 (SDA) на Raspberry Pi.
- SCL MPU-9265 к GPIO3 (SCL) на Raspberry Pi.
Проверка подключения устройства
После включения I2C и подключения датчика, можно проверить, распознается ли оно системой.
sudo i2cdetect -y 1
Вы увидите таблицу с адресами устройств. Устройство подключено по адресу 68 (0x68).
Установка библиотек
Установим библиотеку smbus2
pip install smbus2
Импорт библиотек и определение адресов
import smbus2 as smbus
import time
# Адреса устройств
MPU_ADDRESS = 0x68
MAG_ADDRESS = 0x0C
# Регистры MPU
PWR_MGMT_1 = 0x6B
ACCEL_XOUT_H = 0x3B
GYRO_XOUT_H = 0x43
# Регистры компаса AK8963
MAG_CNTL1 = 0x0A
MAG_ST1 = 0x02
MAG_XOUT_L = 0x03
MAG_ST2 = 0x09
- smbus2: Библиотека для работы с шиной I2C.
- time: Для управления задержками в программе.
- Адреса устройств:
MPU_ADDRESS
— I2C-адрес MPU-9265.MAG_ADDRESS
— I2C-адрес компаса AK8963- Регистры для управления и чтения данных с сенсоров.
Функция чтения 16-битных данных с поддержкой знаковых чисел
def read_word_2c(addr, device_address=MPU_ADDRESS):
try:
high = bus.read_byte_data(device_address, addr)
low = bus.read_byte_data(device_address, addr + 1)
val = (high << 8) + low
if val >= 0x8000:
return -((65535 - val) + 1)
else:
return val
except Exception as e:
print(f"Ошибка при чтении данных с адреса {device_address:#x}, регистр {addr:#x}: {e}")
return 0
Эта функция читает два байта данных начиная с указанного регистра и преобразует их в 16-битное знаковое число. Если произошла ошибка чтения, выводится сообщение об ошибке и возвращается 0
.
Получение данных акселерометра
def get_accel_data():
x = read_word_2c(ACCEL_XOUT_H)
y = read_word_2c(ACCEL_XOUT_H + 2)
z = read_word_2c(ACCEL_XOUT_H + 4)
return {'x': x, 'y': y, 'z': z}
Функция читает данные акселерометра по осям X, Y и Z, начиная с регистра ACCEL_XOUT_H
, и возвращает их в виде словаря.
Получение данных гироскопа
def get_gyro_data():
x = read_word_2c(GYRO_XOUT_H)
y = read_word_2c(GYRO_XOUT_H + 2)
z = read_word_2c(GYRO_XOUT_H + 4)
return {'x': x, 'y': y, 'z': z}
Аналогично акселерометру, эта функция получает данные гироскопа по осям X, Y и Z.
Получение данных компаса
def get_mag_data():
try:
# Проверяем, готовы ли данные
st1 = bus.read_byte_data(MAG_ADDRESS, MAG_ST1)
if st1 & 0x01:
mag_bytes = bus.read_i2c_block_data(MAG_ADDRESS, MAG_XOUT_L, 7)
x = (mag_bytes[1] << 8) | mag_bytes[0]
y = (mag_bytes[3] << 8) | mag_bytes[2]
z = (mag_bytes[5] << 8) | mag_bytes[4]
if x >= 0x8000:
x = -((65535 - x) + 1)
if y >= 0x8000:
y = -((65535 - y) + 1)
if z >= 0x8000:
z = -((65535 - z) + 1)
st2 = mag_bytes[6]
if not (st2 & 0x08):
return {'x': x, 'y': y, 'z': z}
return {'x': None, 'y': None, 'z': None}
except Exception as e:
print(f"Ошибка при чтении компаса: {e}")
return {'x': None, 'y': None, 'z': None}
Эта функция проверяет готовность данных компаса к чтению. Если данные готовы (st1 & 0x01
), она считывает блок данных, объединяет байты для получения значений по осям X, Y и Z, учитывая знаковость чисел. Затем проверяется статус st2
для подтверждения корректности данных. Если все прошло успешно, функция возвращает словарь с измеренными значениями магнитного поля по осям; в противном случае возвращаются значения None
для каждой оси.
Инициализация компаса
def init_mag():
try:
# Сброс компаса
bus.write_byte_data(MAG_ADDRESS, MAG_CNTL1, 0x01)
time.sleep(0.1) # Ждем завершения сброса
# Установка в режим непрерывных измерений 100Hz
bus.write_byte_data(MAG_ADDRESS, MAG_CNTL1, 0x16)
time.sleep(0.1) # Ждем завершения настройки
except Exception as e:
print(f"Ошибка при инициализации компаса: {e}")
Функция сначала сбрасывает настройки компаса, а затем устанавливает его в режим непрерывных измерений с частотой 100 Гц.
Основная функция программы
def main():
try:
# Пробуждаем MPU-9265
bus.write_byte_data(MPU_ADDRESS, PWR_MGMT_1, 0)
# Инициализация компаса
init_mag()
while True:
accel_data = get_accel_data()
gyro_data = get_gyro_data()
mag_data = get_mag_data()
print(f"Accelerometer: {accel_data}")
print(f"Gyroscope: {gyro_data}")
if mag_data['x'] is not None:
print(f"Compass: {mag_data}")
else:
print("Compass: Данные не готовы или ошибка чтения")
time.sleep(1)
except KeyboardInterrupt:
print("Завершение программы")
finally:
bus.close()
- Пробуждение MPU-9265: Отправляется команда пробуждения сенсора путем записи
0
в регистрPWR_MGMT_1
. - Инициализация компаса: Вызывается функция
init_mag()
. - Бесконечный цикл: В цикле программа считывает данные акселерометра, гироскопа и компаса каждую секунду и выводит их на экран.
- Обработка прерывания: При нажатии
Ctrl+C
программа корректно завершает работу. - Закрытие шины I2C: В блоке
finally
шина I2C закрывается, освобождая ресурсы.
Результат работы программы
Полный код
Полный код доступен в репозитории на Гитхабе.