Bắt Đầu với GY-87 10DOF MPU6050 HMC5883L BMP180: Hướng Dẫn Chi Tiết cho Người Mới

Module GY-87 là một bo mạch nhỏ gọn, tích hợp nhiều cảm biến, thường được gọi là IMU (Inertial Measurement Unit) 10 bậc tự do (10-DOF). Đây là một module rất phổ biến trong các dự án điện tử, robot, flycam (drone) và các hệ thống định vị nhờ khả năng cung cấp một lượng lớn dữ liệu chỉ trên một bo mạch duy nhất.

Các Cảm Biến Tích Hợp

MPU-6050: Chuyển động 6-DOF

Gia tốc kế: Đo gia tốc tuyến tính (X, Y, Z).

Con quay hồi chuyển: Đo tốc độ xoay (X, Y, Z).

QMC5883L: Từ trường 3-DOF

Từ kế: Hoạt động như một la bàn số, đo từ trường.

BMP180: Khí áp & Nhiệt độ

Khí áp kế: Đo áp suất để ước tính độ cao.

Nhiệt kế: Đo nhiệt độ môi trường.

Chi Tiết Sơ Đồ Chân (Pinout)

Sơ đồ chân của module GY-87
Tên Chân Chức Năng
VCC_INNguồn cấp chính - 5V
3.3VNguồn cấp phụ - 3.3V (Thường là ngõ ra)
GNDNối đất (Ground)
SCLChân xung nhịp I2C (Serial Clock)
SDAChân dữ liệu I2C (Serial Data)
FSYNCNgõ vào đồng bộ (Thường không sử dụng)
INTAChân ngắt từ MPU6050 (Thường không sử dụng)
DRDYChân báo dữ liệu sẵn sàng (Thường không sử dụng)

Bước 1: Cài Đặt & Kết Nối

Cài Đặt Thư Viện Cần Thiết

Mở Arduino IDE, vào Tools > Manage Libraries... và tìm kiếm, cài đặt các thư viện sau:

  1. Adafruit MPU6050 (Khi được hỏi, chọn "Install all" để cài các thư viện phụ thuộc).
  2. Adafruit Unified Sensor
  3. QMC5883LCompass
  4. Adafruit BMP085 Library

Sơ Đồ Kết Nối Với Arduino

Sơ đồ kết nối GY-87 với Arduino Uno
Kết nối cơ bản:
  • GY-87 VCC_IN → Arduino 5V
  • GY-87 GND → Arduino GND
  • GY-87 SCL → Arduino SCL (hoặc A5 trên Uno R3)
  • GY-87 SDA → Arduino SDA (hoặc A4 trên Uno R3)

Bước 2: Kiểm Tra Kết Nối (Scan I2C)

Sử dụng code này để kiểm tra kết nối và tìm địa chỉ I2C của tất cả cảm biến.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <QMC5883LCompass.h>

// Initialize sensor objects
Adafruit_MPU6050 mpu;
Adafruit_BMP085 bmp;
QMC5883LCompass compass;

void setup() {
  Wire.begin();

  Serial.begin(9600);
  while (!Serial); // Leonardo: wait for Serial Monitor
  Serial.println("\nI2C Scanner");

    Serial.println("\nI2C Scanner for GY-87");
  Serial.println("---------------------");

  // Initialize the MPU-6050 to enable bypass mode
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip. Cannot enable bypass.");
    Serial.println("Scanning with bypass disabled...");
  } else {
    Serial.println("MPU6050 found. Enabling I2C Bypass mode...");
    // Enable I2C bypass to allow access to the magnetometer
    mpu.setI2CBypass(true);
    delay(100); // Give it a moment to settle
    Serial.println("Bypass enabled. Starting scan...");
  }
}

void loop() {
  int nDevices = 0;

  Serial.println("Scanning...");

  for (byte address = 1; address < 127; ++address) {
    // The i2c_scanner uses the return value of
    // the Wire.endTransmission to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    byte error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.print(address, HEX);
      Serial.println("  !");

      ++nDevices;
    } else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  } else {
    Serial.println("done\n");
  }
  delay(5000); // Wait 5 seconds for next scan
}

Bước 3: Đọc Dữ Liệu Cảm Biến

Code này đọc và hiển thị dữ liệu từ tất cả cảm biến lên Serial Monitor.

/*
  This Arduino code is designed to work with the GY-87 IMU (Inertial Measurement Unit) module, 
  which is a multi-sensor module containing three individual sensors: MPU6050 (Accelerometer and Gyroscope), 
  QMC5883L Magnetometer, and BMP180 (Barometric Pressure and Temperature). The code initializes these 
  sensors and continuously prints their readings to the Serial Monitor.
  
  Board: Arduino Uno R4
  Component: GY-87 IMU Module
  Library: https://github.com/adafruit/Adafruit_MPU6050  (Adafruit MPU6050 by Adafruit)
           https://github.com/mprograms/QMC5883LCompass  (QMC5883LCompass by MPrograms)
           https://github.com/adafruit/Adafruit-BMP085-Library  (Adafruit BMP085 Library by Adafruit)
*/

// Include required libraries
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <QMC5883LCompass.h>

// Initialize sensor objects
Adafruit_MPU6050 mpu;
Adafruit_BMP085 bmp;
QMC5883LCompass compass;

void setup() {
  // Initialize the serial communication with a baud rate of 115200
  Serial.begin(9600);

  // Initialize the MPU6050 sensor (accelerometer and gyroscope)
  initializeMPU6050();

  // Enable I2C bypass on MPU6050 to directly access the QMC5883L magnetometer
  mpu.setI2CBypass(true);

  // Initialize the QMC5883L magnetometer sensor
  initializeQMC5883L();

  // Initialize BMP180 barometric sensor
  initializeBMP180();
}


void loop() {
  // Print MPU6050 data
  printMPU6050();

  // Print QMC5883L data
  printQMC5883L();

  // Print BMP180 data
  printBMP180();
  delay(500);
}

void initializeQMC5883L() {

  compass.init();

  // compass.setCalibrationOffsets(-336.00, -179.00, 47.00);
  // compass.setCalibrationScales(1.05, 0.94, 1.02);

}

void printQMC5883L() {

  Serial.println();
  Serial.println("QMC5883L ------------");

	int x, y, z, a;
	char myArray[3];
	
	compass.read();
  
	x = compass.getX();
	y = compass.getY();
	z = compass.getZ();
	
	a = compass.getAzimuth();

	compass.getDirection(myArray, a);
  
	Serial.print("X: ");
	Serial.print(x);

	Serial.print(" Y: ");
	Serial.print(y);

	Serial.print(" Z: ");
	Serial.print(z);

	Serial.print(" Azimuth: ");
	Serial.print(a);

	Serial.print(" Direction: ");
	Serial.print(myArray[0]);
	Serial.print(myArray[1]);
	Serial.println(myArray[2]);

  Serial.println("QMC5883L ------------");
  Serial.println();
}


void initializeMPU6050() {
  // Check if the MPU6050 sensor is detected
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1)
      ;  // Halt if sensor not found
  }
  Serial.println("MPU6050 Found!");

  // set accelerometer range to +-8G
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);

  // set gyro range to +- 500 deg/s
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);

  // set filter bandwidth to 21 Hz
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  Serial.println("");
  delay(100);
}

void printMPU6050() {

  Serial.println();
  Serial.println("MPU6050 ------------");

  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("MPU6050 ------------");
  Serial.println();
}

void initializeBMP180() {
  // Start BMP180 initialization
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP180 sensor, check wiring!");
    while (1)
      ;  // Halt if sensor not found
  }
  Serial.println("BMP180 Found!");
}

void printBMP180() {
  Serial.println();
  Serial.println("BMP180 ------------");
  Serial.print("Temperature = ");
  Serial.print(bmp.readTemperature());
  Serial.println(" *C");

  Serial.print("Pressure = ");
  Serial.print(bmp.readPressure());
  Serial.println(" Pa");

  // Calculate altitude assuming 'standard' barometric
  // pressure of 1013.25 millibar = 101325 Pascal
  Serial.print("Altitude = ");
  Serial.print(bmp.readAltitude());
  Serial.println(" meters");

  Serial.print("Pressure at sealevel (calculated) = ");
  Serial.print(bmp.readSealevelPressure());
  Serial.println(" Pa");
  Serial.println("BMP180 ------------");
  Serial.println();
}

Ứng Dụng Thực Tế

  • Flycam (Drones) và Máy bay mô hình: Giữ thăng bằng, tự động ổn định vị trí, định hướng.
  • Robot tự hành: Giữ thăng bằng cho robot 2 bánh, định vị trong nhà, điều hướng.
  • Thiết bị theo dõi chuyển động (Motion Tracking)
  • Hệ thống định vị quán tính (INS)
  • Trạm thời tiết mini

Nhận xét

Mới hơn Cũ hơn