MPU-6050 (GY-521) Arduino Tutorial

Ciao a tutti, eccomi di nuovo qui con un nuovo tutorial molto interessante. In questo tutorial vi mostrerò il funzionamento di un accelerometro/giroscopio con un Arduino UNO. In particolare utilizzerò un sensore InvenSense MPU-6050

Il sensore InvenSense MPU-6050 contiene, in un singolo integrato, un accelerometro MEMS a 3 assi ed un giroscopio MEMS a 3 assi. Con lo giroscopio possiamo misurare l’accelerazione angolare di un corpo su di un proprio asse, mentre con l’accelerometro possiamo misurare l’accelerazione di un corpo lungo una direzione. È molto preciso, in quanto ha un convertitore ADC (da analogico a digitale) da 16 bit per ogni canale. Inoltre cattura i canali x, y e z contemporaneamente. Il sensore può essere utilizzato tramite il protocollo di comunicazione standard I²C, quindi facile da interfacciare con arduino.

Il sensore MPU-6050 non è nemmeno costoso, forse è il più economico sul mercato, soprattutto in considerazione del fatto che combina un accelerometro e un giroscopio. Su Amazon è possibile trovare diverse breakout board ad un ottimo prezzo:

Ecco alcune caratteristiche del sensore MPU-6050:

  • Chip con Convertitore AD a 16 bit Integrato
  • Range di misura giroscopio: ±250, 500, 1000 e 2000°/s
  • Range di misura accelerometro: +2, +4 , +8 , +16 g
  • Interfaccia: I²C
  • Alimentazione: da 3V a 5V

Potete trovare il datasheet del MPU-6050 QUI.

Per le mie prove ho acquistato un modulo GY-521 in modo d’avere il sensore MPU-6050 già pronto per l’utilizzo. Ecco lo schema elettrico del modulo GY-521 per chi volesse costruirselo da solo:

Ora passiamo al tutorial vero e proprio andando a vedere come utilizzare questo modulo con un Arduino Uno.

Lista del materiale:

Schema di collegamento

Breadboard

GY-521Arduino Uno
VCC3.3V
GNSGND
SCLA5
SDAA4

N.B. : Lo schema ed i collegamenti sono indicati solo per Arduino Uno, ma il tutorial è valido anche per tutte le altre boards di Arduino. L’unica cosa che cambia nei collegamenti sono i 2 pin I2C, ovvero SDA e SCL (Es. su Arduino Uno il pin SCL si trovare sul pin A5 mentre su Arduino Mega si trova sul pin 20). Basta consultare il datasheet o fare delle ricerche su google per trovare gli ingressi I2C della propria board.

Ora passiamo allo sketch di verifica, si tratta di uno scanner i2c in modo da verificheremo se il nostro modulo GY-521 è stato collegato correttamente ad Arduino.

#include <Wire.h>

void setup() {
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop() {
  byte error, address;
  int nDevices;

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

  nDevices = 0;
  for (address = 1; address < 127; address++ ) {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    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("Unknow 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
}

Dopo aver caricato lo sketch su Arduino bisogna aprire il Monitor Seriale presente sull’Arduino IDE. Se uscirà il seguente messaggio allora tutto è stato collegato correttamente:

Mentre se apparirà il seguente messaggio, sicuramente c’è stato un errore nei collegamenti:

Bene! Se la verifica è andata bene non ci resta che proseguire il tutorial e provare le funzionalità del sensore MPU-6050, ovvero la lettura dei 3 assi (X, Y, Z) del giroscopio, dell’accelerometro e per finire anche la misurazione della temperatura in gradi celsius (°C).

Prima di tutto bisogna caricate il seguente sketch sulla board arduino:

// MPU-6050 Short Example Sketch
#include<Wire.h>

const int MPU = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop() {
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 14, true); // request a total of 14 registers
  AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  Serial.print("Accelerometer: ");
  Serial.print("X = "); Serial.print(AcX);
  Serial.print(" | Y = "); Serial.print(AcY);
  Serial.print(" | Z = "); Serial.println(AcZ);
  
  //equation for temperature in degrees C from datasheet
  Serial.print("Temperature: "); Serial.print(Tmp / 340.00 + 36.53); Serial.println(" C ");

  Serial.print("Gyroscope: ");
  Serial.print("X = "); Serial.print(GyX);
  Serial.print(" | Y = "); Serial.print(GyY);
  Serial.print(" | Z = "); Serial.println(GyZ);
  Serial.println(" ");
  delay(333);
}

Dopodiché aprendo il Monitor Seriale dovrebbero comparire i valori degli assi X, Y, Z dell’accelerometro, giroscopio e della temperatura in °C come nell’immagine seguente:

Quest’ultimo sketch è abbastanza semplice da comprendere, soprattutto se si ha una buona base di programmazione ed un pò di esperienza con arduino. Sulle variabili AcX, AcY, AcZ = accelerometro; Tmp = temperatura; GyX, GyY, GyZ = giroscopio; vengono memorizzati i valori degli assi X, Y, Z. In questo modo sarà possibile gestire questi valori come meglio si vuole, così come mostrerò tra breve.

Progetto: Gestione di due Servomotori utilizzando un modulo GY-521

Questo progetto è un esempio pratico per mostrarvi come sia abbastanza semplice interfacciare il modulo GY-521 con Arduino ed utilizzarlo per una specifica applicazione.  Utilizzerò solo i valori degli assi dell’accelerometro e calcolerò gli angoli Pitch e Roll (come descritto nel mio tutorial) per far ruotare i due servomotori da 0° a 179° in base alla posizione dell’accelerometro. Prima di proseguire consiglio la visione del seguente video.

Lista della spesa

Schema di collegamento

Breadboard

Come si può notare dallo schema elettrico ho alimentato i due servomotori con un’alimentazione esterna da 5V. Questo perchè i miei servo insieme consumano più di 500 mA. Inoltre, 500 mA è anche la corrente massima erogabile da una classica porta USB 2.0. Ora passiamo allo sketch da caricare su Arduino

// MPU6050 & Servo
// https://www.giuseppecaccavale.it/
// Giuseppe Caccavale

#include <SPI.h>
#include <Wire.h>
#include <Servo.h>
#define MPU 0x68  // I2C address of the MPU-6050

Servo ServoX, ServoY;
double AcX, AcY, AcZ;
int Pitch, Roll;

void setup() {
  Serial.begin(9600);
  ServoX.attach(8);
  ServoY.attach(9);
  init_MPU(); // Inizializzazione MPU6050
}

void loop()
{
  FunctionsMPU(); // Acquisisco assi AcX, AcY, AcZ.

  Roll = FunctionsPitchRoll(AcX, AcY, AcZ);   //Calcolo angolo Roll
  Pitch = FunctionsPitchRoll(AcY, AcX, AcZ);  //Calcolo angolo Pitch

  int ServoRoll = map(Roll, -90, 90, 0, 179);
  int ServoPitch = map(Pitch, -90, 90, 179, 0);

  ServoX.write(ServoRoll);
  ServoY.write(ServoPitch);


  Serial.print("Pitch: "); Serial.print(Pitch);
  Serial.print("\t");
  Serial.print("Roll: "); Serial.print(Roll);
  Serial.print("\n");

}

void init_MPU() {
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  delay(1000);
}

//Funzione per il calcolo degli angoli Pitch e Roll
double FunctionsPitchRoll(double A, double B, double C) {
  double DatoA, DatoB, Value;
  DatoA = A;
  DatoB = (B * B) + (C * C);
  DatoB = sqrt(DatoB);

  Value = atan2(DatoA, DatoB);
  Value = Value * 180 / 3.14;

  return (int)Value;
}

//Funzione per l'acquisizione degli assi X,Y,Z del MPU6050
void FunctionsMPU() {
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // request a total of 14 registers
  AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
}

Spero vi sia piaciuto questo tutorial, in ogni caso vi ringrazio per la lettura. Se avete problemi non esitate a lasciare un commento. A presto, ciao! 🙂

Download archivio con l’intero progetto.