View Categories

Акселерометр MPU6050

MPU6050 – трёх осевой осевой датчик ускорения (акселерометр) и угловой скорости (гироскоп). Используется для получения информации о положении в пространстве, движении, в системах инерциальной навигации, также может быть использован как высокочувствительный датчик вибрации и удара. Микросхема гораздо умнее, чем кажется на первый взгляд: там есть встроенный процессор, который можно программировать.

В наборе GyverKIT Aliexpress
START
Купить

Характеристики датчика:

  • Питание: 2.3.. 3.5V
  • Диапазон ускорений: от ±2g до ±16g
  • Диапазон угловых скоростей: от ±250 град/с до ±2000 град/с
  • Интерфейс: I2C

На модуле выведены:

  • VCC и GND: питание 3.. 5V (на модуле стоит стабилизатор)
  • SDA и SCL: вывод шины I2C для связи с МК
  • XDA и XCL: позволяют подключать к модулю другие датчики (например, магнитометр)
  • AD0: выбор адреса. Никуда не подключен: 0x68, подтянут к VCC – 0x69
  • INT: пин прерывания готовности (поведение настраивается в программе)

Подключение к Arduino #

Модуль подключается по шине I2C, выведенной на пины:

  • Arduino: SDA – A4, SCL – A5
  • Wemos: SDA – D2, SCL – D1

Программирование #

По работе с датчиком у меня есть отдельная большая статья

Напрямую #

#include <Wire.h>

#define MPU_ADDR 0x68
#define MPU_PWR_MGMT_1 0x6B
#define MPU_ACCEL_XOUT_H 0x3B

// включить mpu
void MPU_init() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(MPU_PWR_MGMT_1);
  Wire.write(0);
  Wire.endTransmission();
}

// запросить данные
bool MPU_read(int data[7]) {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(MPU_ACCEL_XOUT_H);
  Wire.endTransmission(false);

  if (Wire.requestFrom(MPU_ADDR, 14) == 14) {
    for (byte i = 0; i < 7; i++) {
      data[i] = (Wire.read() << 8) | Wire.read();
    }
    return true;
  }
  return false;
}

void setup() {
  Serial.begin(115200);
  Wire.begin();
}

void loop() {
  int data[7];

  if (MPU_read(data)) {
    // здесь data:
    // [accX, accY, accZ, temp, gyrX, gyrY, gyrZ]
    // acc - ускорение, gyr - угловая скорость, temp - температура (raw)
    for (byte i = 0; i < 7; i++) {
      Serial.print(data[i]);
      Serial.print('\t');
    }
    Serial.println();
  } else {
    Serial.println("MPU read error");
  }

  delay(100);
}

Библиотеки #

С модулем можно работать при помощи библиотеки от i2cdev: качаем весь архив, из него достаём Arduino/I2Cdev и Arduino/MPU6050, кладём себе в папку с библиотеками.

Получаем сырые значения по осям
// Простой пример с получением и выводом ускорений и угловых скоростей в порт
#include <I2Cdev.h>
#include <MPU6050.h>
MPU6050 mpu;

void setup() {
  Wire.begin();
  Serial.begin(115200);
  mpu.initialize();
  // состояние соединения
  Serial.println(mpu.testConnection() ? "MPU6050 OK" : "MPU6050 FAIL");
  delay(1000);
}

void loop() {
  int16_t ax, ay, az;
  int16_t gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  Serial.print(ax); Serial.print('\t');
  Serial.print(ay); Serial.print('\t');
  Serial.print(az); Serial.print('\t');
  Serial.print(gx); Serial.print('\t');
  Serial.print(gy); Serial.print('\t');
  Serial.println(gz);
  delay(5);
}
Получаем углы поворота
// Более сложный пример, получаем отфильтрованные углы по трём осям
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
MPU6050 mpu;

uint8_t fifoBuffer[45];         // буфер

void setup() {
  Serial.begin(115200);
  Wire.begin();
  //Wire.setClock(1000000UL);   // разгоняем шину на максимум

  // инициализация DMP
  mpu.initialize();
  mpu.dmpInitialize();
  mpu.setDMPEnabled(true);
}

void loop() {
  static uint32_t tmr;
  if (millis() - tmr >= 11) {  // таймер на 11 мс (период готовности значений)
    if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
      // переменные для расчёта (ypr можно вынести в глобал)
      Quaternion q;
      VectorFloat gravity;
      float ypr[3];

      // расчёты
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

      // выводим результат в радианах (-3.14, 3.14)
      Serial.print(ypr[0]); // вокруг оси Z
      Serial.print(',');
      Serial.print(ypr[1]); // вокруг оси Y
      Serial.print(',');
      Serial.print(ypr[2]); // вокруг оси X
      Serial.println();
      // для градусов можно использовать degrees()

      tmr = millis();   // сброс таймера
    }
  }
}

Полезные страницы #

Подписаться
Уведомить о
guest

1 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх