9 степеней свободы: подключение MPU-9265 к Raspberry Pi — HmHm.WTF

9 степеней свободы: подключение MPU-9265 к Raspberry Pi

Руководство по подключению и использованию датчика 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

Схема подключения MPU-9265 к Raspberry Pi

Схема подключения 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

Функция чтения 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 = -((6

Эта функция проверяет готовность данных компаса к чтению. Если данные готовы (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()
  1. Пробуждение MPU-9265: Отправляется команда пробуждения сенсора путем записи 0 в регистр PWR_MGMT_1.
  2. Инициализация компаса: Вызывается функция init_mag().
  3. Бесконечный цикл: В цикле программа считывает данные акселерометра, гироскопа и компаса каждую секунду и выводит их на экран.
  4. Обработка прерывания: При нажатии Ctrl+C программа корректно завершает работу.
  5. Закрытие шины I2C: В блоке finally шина I2C закрывается, освобождая ресурсы.

Результат работы программы

Результат работы скрипта mpu9265.py

Полный код

Полный код доступен в репозитории на Гитхабе.