Skip to Content

MPU6050 3-Axis Accelerometer And 3-Axis GyroSensor With Arduino

MPU6050 3-Axis Accelerometer And 3-Axis GyroSensor With Arduino

En este artículo, aprenderás a utilizar un módulo MPU6050. El MPU6050 es un acelerómetro de 3 ejes y un girosensor de 3 ejes.

Te ayuda a construir cámaras de autobalanceo, robots o incluso un dron.

Estos girosensores se utilizan habitualmente en una amplia gama de productos.

Los girosensores de un smartphone ayudan en los mapas de navegación, en la toma de fotografías panorámicas, en la detección del uso activo del móvil, en los juegos, en la detección de caídas, etc.

Los sensores giroscópicos de los dispositivos portátiles, como los relojes, pueden ayudar a controlar los pasos, la actividad del sueño, etc.

Te explicaré cómo utilizar el girosensor MPU6050 con Arduino.

Cubriremos las etiquetas de los pines y la descripción, las especificaciones críticas del MPU6050 y las conexiones de hardware necesarias. 

En las secciones posteriores, recorreremos un ejemplo de código Arduino y veremos cómo utilizar eficientemente un MPU6050 con Arduino.

Comencemos.

Componentes necesarios para construir el proyecto Arduino y MPU6050

Componentes de hardware 

Software

Makerguides.com participa en el Programa de Asociados de Amazon Services LLC, un programa de publicidad de afiliados diseñado para proporcionar un medio para que los sitios ganen honorarios de publicidad mediante la publicidad y los enlaces a productos en Amazon.com.

Fundamentos de un sensor MPU6050

Veamos este diagrama de un módulo MPU6050.

Módulo MPU6050

Puede ver los siguientes aspectos numerados en el diagrama:

  1. Regulador de voltaje: convierte la entrada de 5 V del Arduino UNO en 3,3 V. Los 3,3 V son la tensión de alimentación del CI MPU6050
  2. Opción de conector Bergstick - Puede acceder a las líneas I2C, Interrupción, configuración de direcciones y alimentación en estas líneas. 
  3. MPU6050 IC - MPU6050 es un IC de 24 pines. Puedes localizar el pin 1 del CI con la ayuda de un pequeño punto. La imagen de arriba indica el punto en la parte superior izquierda del CI.
  4. LED de indicación de alimentación
  5. Agujeros de montaje

El módulo MPU6050 tiene ocho pines. La siguiente tabla describe los ocho pines presentes en el módulo MPU.

Sl. NoEtiqueta de la clavijaDescripción de la clavija
1VCCEntrada de 5 V. Puedes conectar 5 V en el Arduino UNO a la VCC
2GNDConexión a tierra
3SCLLínea de reloj serie I2C
4SDAI2C Línea de datos en serie
5XDALínea de datos I2C Master (para conectar sensores externos)
6XCLLínea de reloj maestro I2C (para conectar sensores externos)
7AD0Dirección I2C Esclavo LSB. Puedes conectarlo a Low o High. Por lo tanto, usted puede tener dos direcciones I2C para MPU6050 ICs en su placa
8INTInterrumpir la entrada digital

Interfaz digital

Se puede acceder a los registros y a la memoria del MPU6050 mediante I2C. La velocidad máxima del bus I2C soportada es de 400 kHz. 

La dirección esclava del MPU6050 es 0b110100x, donde x puede ser cero o uno.

Por lo tanto, las dos direcciones posibles son 0b1101000 y 0b1101001.

El valor de x es el nivel lógico presente en el pin de entrada AD0, como se muestra en la tabla siguiente. 

Nivel lógico del pin AD0Dirección I2C de 7 bits del MPU6050
Bajo1101000
Alta1101001

Cómo correlacionar la orientación de los ejes

Utiliza el diagrama de abajo para entender la orientación de los ejes de la sensibilidad. También te da la polaridad de la rotación.

Cómo correlacionar la orientación de los ejes

Fíjate en la marca del pin número uno.

Especificaciones del acelerómetro del MPU6050

Rango de escala completaAFS_SEL = 0±2 g
AFS_SEL = 1±4 g
AFS_SEL = 2±8 g
AFS_SEL = 3±16 g
Tolerancia de calibración inicial±3 %
Salida Tasa de datosProgramable4 a 1000 Hz
Tolerancia de calibración inicial (salida cero-G)Ejes X e Y±50 mg
Eje Z±80 mg

Especificaciones del giroscopio del MPU6050

Rango de escala completaFS_SEL = 0±250 °/s
FS_SEL = 1±500 °/s
FS_SEL = 2±1000 °/s
FS_SEL = 3±2000 °/s
Sensibilidad Factor de escala Tolerancia±3 %
Tiempo de puesta en marcha del giroscopio30 ms
Velocidad de salida de datos4 a 8000 Hz

Enlaces importantes:

Registros del MPU6050:

 Mapa de registros y descripciones de MPU-6000 y MPU-6050 Revisión 4.2

Hoja de datos del MPU6050:

Especificación del producto MPU-6000 y MPU-6050 Revisión 3.4

Instrucciones paso a paso para conectar un MPU6050 con un Arduino UNO

En esta sección, repasaremos las conexiones entre Arduino UNO y el módulo girosensor MPU6050.

Empecemos.

Cómo conectar el módulo sensor MPU6050 con Arduino UNO

Las conexiones son sencillas y llevan menos tiempo. 

Paso 1: Comience con la conexión GND.

Comienza con la conexión GND

Conecta el pin GND del sensor MPU6050 al pin GND del Arduino. Empieza siempre con las conexiones GND. 

Paso 2: Conectar la línea de reloj I2C

Conecte la línea de reloj I2C

El reloj I2C del Arduino es el pin A5. Conecta el pin A5 del UNO al pin SCL del sensor MPU6050.

Si estás usando Arduino Mega, conecta el pin 21 del Mega al pin SCL del sensor. 

Paso 3: Conectar la línea de datos I2C.

Conectar la línea de datos I2C

Los datos I2C en el Arduino son el pin A4. Conecta el pin A4 del UNO al pin SDA del sensor MPU6050.

Si estás usando el Arduino Mega, conecta el pin 20 del Mega al pin SDA del sensor. 

Paso 4: Conecte la línea de 5 V.

Conecte la línea de 5 V

Conecta los 5 V del Arduino UNO al VCC del sensor MPU6050. El módulo del sensor MPU6050 tiene un convertidor de 5 V a 3,3 V integrado.

Enhorabuena. Ya has completado las conexiones entre el Arduino UNO y el sensor MPU6050.

Proyectos simples de Arduino en MPU6050 y Arduino UNO

Proyectos simples de Arduino en MPU6050 y Arduino UNO

Proyecto MPU6050 1:

Este sketch de Arduino leerá los datos del sensor de la MPU y los imprimirá en el terminal serie.

// Basic demo for accelerometer readings from Adafruit MPU6050
 
#include "Adafruit_MPU6050.h"
#include "Adafruit_Sensor.h"
#include "Wire.h"
 
Adafruit_MPU6050 mpu;
 
void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
 
  Serial.println("Adafruit MPU6050 test!");
 
  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");
 
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_2000_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }
 
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }
 
  Serial.println("");
  delay(100);
}
 
void loop() {
 
  /* 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("");
  delay(500);
}

Proyecto MPU6050 2: 

Aquí tenemos otro interesante proyecto de Arduino. Este sketch de Arduino leerá los datos del sensor MPU y controlará la rotación de una imagen 3D en una pantalla OLED.

Proyecto MPU6050

También tienes una opción para leer la temperatura desde el sensor MPU6050. En función de la temperatura, se controla el color del LED conectado al Arduino.

LED conectado al Arduino

Enlace

// Example sketch for the MPU-6050.
//
// Version 1, 9 August 2021, by Koepel with help from Wokwi community.
// Based on:
//   (1)
//     3D_Cube for Arduino OLED module by Colin Ord, 9/1/2015
//     A port of my (Colin Ord) original JustBasic Cube_3D demo to the Arduino Uno using U8G library.
//     http://colinord.blogspot.com/2015/01/arduino-oled-module-with-3d-demo.html
//     (no known copyrights)
//
//   (2)
//     MPU-6050 Short Example Sketch
//     By Arduino User JohnChi
//     August 17, 2014
//     Public Domain
//     https://playground.arduino.cc/Main/MPU-6050/#short
//
//   (3)
//     The Adafruit GFX library with the SSD1306 driver.
//
 
#include "Wire.h"
#include "Adafruit_SSD1306.h"
#include "Adafruit_GFX.h"
#include "Adafruit_NeoPixel.h"
 
Adafruit_SSD1306 display(128, 64);   // 128 pixels width, 64 pixels height
 
#define LED_PIN   6
#define LED_COUNT 1
Adafruit_NeoPixel neoPixel( LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
 
const int mpuAddress = 0x68;          // I2C address of the MPU-6050
 
float xByGyro, yByGyro, zByGyro;      // Global variables for the rotation by gyro
 
// Set the origin in the middle of the display
const int xOrigin = 64;
const int yOrigin = 32;
 
const float viewDistance = 150.0;     // higher for less perspective, lower for more.
 
// Vertices for a cube
// A cube has 8 corners and each coordinate has x,y,z values.
#define NUM_VERTICES 8
const int cube_vertex[NUM_VERTICES][3] =
{
  { -20, -20,  20 },     // x, y, z
  {  20, -20,  20 },
  {  20,  20,  20 },
  { -20,  20,  20 },
  { -20, -20, -20 },
  {  20, -20, -20 },
  {  20,  20, -20 },
  { -20,  20, -20 }
};
 
// The wirefram is to display the lines on the OLED display
// It contains the corners of the shape in 2D coordinates
int wireframe[NUM_VERTICES][2];
 
void setup()
{
  Serial.begin( 115200);
 
  Wire.begin();
 
  // Initialize the OLED display and test if it is connected.
  if( !display.begin( SSD1306_SWITCHCAPVCC, 0x3C))
  {
    Serial.println(F( "SSD1306 allocation failed"));
    for(;;);                                   // halt the sketch if error encountered
  }
 
  // Initialize the MPU-6050 and test if it is connected.
  Wire.beginTransmission( mpuAddress);
  Wire.write( 0x6B);                           // PWR_MGMT_1 register
  Wire.write( 0);                              // set to zero (wakes up the MPU-6050)
  auto error = Wire.endTransmission();
  if( error != 0)
  {
    Serial.println(F( "Error, MPU-6050 not found"));
    for(;;);                                   // halt the sketch if error encountered
  }
 
  // Initialize the NeoPixel
  neoPixel.begin();
}
 
void loop()
{
  Wire.beginTransmission( mpuAddress);
  Wire.write( 0x3B);                   // Starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission( false);        // No stop condition for a repeated start
 
  // The MPU-6050 has the values as signed 16-bit integers.
  // There are 7 values in 14 registers.
  int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
 
  Wire.requestFrom( mpuAddress, 14);   // request a total of 14 bytes
  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)
 
  // The acceleration is directly mapped into the angles.
  // That is rather artificial.
  // The combined gravity could be used for an angle, while ignoring the strength.
  //
  // The gyro sets the rotation speed.
  // The angle created by the rotation speed is added to the angle by the accelerometer.
  //
  // The conversion from the sensor values to the rotation is just a value
  // that makes it look good on display.
 
  float xByAccel = (float) AcX * 0.0001;      // static angle by accelerometer
  float yByAccel = (float) AcY * 0.0001;
  float zByAccel = (float) AcZ * 0.0001;
 
  xByGyro += (float) GyX * 0.00001;           // moving angle by gyro
  yByGyro += (float) GyY * 0.00001;
  zByGyro += (float) GyZ * 0.00001;
 
  float x = xByAccel + xByGyro;               // combine both angles
  float y = yByAccel + yByGyro;
  float z = zByAccel + zByGyro;
 
  // Keep the radians in range (although the cos/sin functions accept every value)
  if( x < 0.0)
    x += 2.0 * M_PI;
  else if( x > 2.0 * M_PI)
    x -= 2.0 * M_PI;
  if( y < 0.0)
    y += 2.0 * M_PI;
  else if( y > 2.0 * M_PI)
    y -= 2.0 * M_PI;
  if( z < 0.0)
    z += 2.0 * M_PI;
  else if( z > 2.0 * M_PI)
    z -= 2.0 * M_PI;
 
  // Draw 3D picture
  for (int i = 0; i < NUM_VERTICES; i++)
  {
    // Rotate Y
    float rotx = cube_vertex[i][2] * sin(y) + cube_vertex[i][0] * cos(y);
    float roty = cube_vertex[i][1];
    float rotz = cube_vertex[i][2] * cos(y) - cube_vertex[i][0] * sin(y);
 
    // Rotate X
    float rotxx = rotx;
    float rotyy = roty * cos(x) - rotz * sin(x);
    float rotzz = roty * sin(x) + rotz * cos(x);
 
    // Rotate Z
    float rotxxx = rotxx * cos(z) - rotyy * sin(z);
    float rotyyy = rotxx * sin(z) + rotyy * cos(z);
    float rotzzz = rotzz;
 
    // Add depth perspective
    rotxxx *= viewDistance / (viewDistance + rotzz);
    rotyyy *= viewDistance / (viewDistance + rotzzz);
 
    // Bring to middle of screen
    rotxxx += (float) xOrigin;
    rotyyy += (float) yOrigin;
 
    // Store new vertices values for wireframe drawing
    wireframe[i][0] = (int) rotxxx;
    wireframe[i][1] = (int) rotyyy;
    wireframe[i][2] = (int) rotzzz;
  }
  draw_wireframe();
 
 
  // Set the color of the NeoPixel according to the temperature
  // Temperature by the MPU-6050 is -40 to 85.
  // According to the datasheet:
  //   Temperature in Celsius = (raw_value / 340) + 36.53
  // The Hue range for the NeoPixel is the full uint16_t range.
  float Celsius = ((float) Tmp / 340.00) + 36.53;
  float hue = (Celsius + 40.0) / 125.0 * 65535.0;
  uint32_t rgbcolor = neoPixel.ColorHSV( (uint16_t) hue);
  neoPixel.setPixelColor( 0, rgbcolor);
  neoPixel.show();                        // update new values to NeoPixel
}
 
void draw_wireframe(void)
{
  // Start with a empty buffer
  display.clearDisplay();
 
  // A cube has 8 points and 12 sides.
  // The wireframe contains the 8 points, and the 12 lines are drawn here.
  display.drawLine( wireframe[0][0], wireframe[0][1], wireframe[1][0], wireframe[1][1], SSD1306_WHITE);
  display.drawLine( wireframe[1][0], wireframe[1][1], wireframe[2][0], wireframe[2][1], SSD1306_WHITE);
  display.drawLine( wireframe[2][0], wireframe[2][1], wireframe[3][0], wireframe[3][1], SSD1306_WHITE);
  display.drawLine( wireframe[3][0], wireframe[3][1], wireframe[0][0], wireframe[0][1], SSD1306_WHITE);
 
  display.drawLine( wireframe[4][0], wireframe[4][1], wireframe[5][0], wireframe[5][1], SSD1306_WHITE);
  display.drawLine( wireframe[5][0], wireframe[5][1], wireframe[6][0], wireframe[6][1], SSD1306_WHITE);
  display.drawLine( wireframe[6][0], wireframe[6][1], wireframe[7][0], wireframe[7][1], SSD1306_WHITE);
  display.drawLine( wireframe[7][0], wireframe[7][1], wireframe[4][0], wireframe[4][1], SSD1306_WHITE);
 
  display.drawLine( wireframe[0][0], wireframe[0][1], wireframe[4][0], wireframe[4][1], SSD1306_WHITE);
  display.drawLine( wireframe[1][0], wireframe[1][1], wireframe[5][0], wireframe[5][1], SSD1306_WHITE);
  display.drawLine( wireframe[2][0], wireframe[2][1], wireframe[6][0], wireframe[6][1], SSD1306_WHITE);
  display.drawLine( wireframe[3][0], wireframe[3][1], wireframe[7][0], wireframe[7][1], SSD1306_WHITE);
 
  // Extra cross face on one side
  display.drawLine( wireframe[1][0], wireframe[1][1], wireframe[3][0], wireframe[3][1], SSD1306_WHITE);
  display.drawLine( wireframe[0][0], wireframe[0][1], wireframe[2][0], wireframe[2][1], SSD1306_WHITE);
 
  // Write the new picture to the display
  display.display();
}

Preguntas frecuentes sobre el MPU6050 y los proyectos Arduino

He respondido a las preguntas más frecuentes sobre el MPU6050.

Si tiene alguna otra pregunta, no dude en publicarla en la sección de comentarios. 

1) ¿Para qué se utiliza el MPU6050?

El MPU6050 controla la velocidad de rotación de los ejes X, Y y Z. El MPU6050 también proporciona un acelerómetro en los tres ejes.

Por lo tanto, puede utilizar el MPU6050 como un girosensor. El MPU6050 también tiene un sensor de temperatura interno. 

Puede encontrar sensores MPU6050 en controladores HMI, teléfonos móviles, wearables, herramientas de navegación, cámaras de drones, etc. 

2) ¿Qué produce el MPU6050?

El MPU6050 emite la posición actual del sensor. La salida de datos del MPU6050 se indica a continuación.

  • Velocidad de rotación angular X, Y y Z en grados por segundo
  • Valor de la aceleración de los ejes X, Y y Z en unidades "g".
  • Datos del sensor de temperatura

3) ¿Cómo hacer que el MPU6050 funcione con Arduino?

El MPU6050 se comunica con el Arduino a través de líneas I2C. El MPU6050 proporciona todas las medidas a través de registros.

Arduino puede leer los registros internos de MPU6050 a través de I2C y obtener las mediciones periódicamente. 

Tienes que conectar la línea SDA de I2C, la línea de datos de I2C y un GPIO de Arduino como pin de entrada de interrupción.

El CI MPU6050 realiza todo el procesamiento y filtrado de la señal y proporciona los datos digitales finales. Por lo tanto, facilita la parte del software. 

3) ¿Qué precisión tiene el sensor de temperatura del MPU6050?

El MPU6050 dispone de un sensor de temperatura integrado cuya precisión es de ±1 grado. La precisión de ± 1 grado es para todo el rango de funcionamiento de -40 a +85 °C.

Conclusión

En este artículo, conocimos los fundamentos del módulo MUP6050 y comprendimos todas las especificaciones y características necesarias que ofrece.

Después construimos un proyecto de ejemplo que probamos utilizando el código de Arduino. 

El MPU6050 es un dispositivo de seguimiento de movimiento realmente versátil. Encontrará muchas aplicaciones en sus proyectos posteriores.

Estoy seguro de que te entusiasma utilizar el MPU6050 en tus siguientes proyectos de Arduino. 

Si tiene sugerencias para mejorar el artículo, escríbalas en la sección de comentarios.

Me ayudará a mejorar el artículo, lo que beneficiará a todos nuestros lectores.

Será fantástico saber en qué proyectos estáis trabajando en los que estáis involucrando un MPU6050.

Comparta sus artículos en la sección de comentarios. Disfrutaremos leyendo las nuevas ideas de proyectos.

No olvides compartir el artículo con tus amigos y entusiastas de Arduino.

bill Smith

Monday 11th of March 2024

Issues I find of interest (from my experienes). 1) Filtering of the outputs so they are not so widely fluctuating. 2) My Temperatures always read very High... not sure why. 3) More information on the Accelerometer and itgs usage.