Guía Definitiva del MPU6050: Acelerómetro y Giroscopio con I2C y C++

La medición precisa del movimiento y la orientación es un pilar fundamental en la robótica móvil, la estabilización de cámaras y los sistemas IoT. El MPU6050 es una Unidad de Medición Inercial (IMU) de 6 ejes que combina un acelerómetro de 3 ejes y un giroscopio de 3 ejes en un formato miniatura.

En este artículo técnico, analizaremos su diagrama de pines (pinout), el funcionamiento del protocolo de comunicación I2C y un código optimizado en C++ para leer los datos crudos y transformarlos en magnitudes físicas reales.

1. Arquitectura y Pinout del MPU6050

El módulo MPU6050 se comunica con microcontroladores como Arduino, ESP32 o ESP8266 mediante el bus I2C. A continuación se detalla la función de cada uno de sus pines principales:

  • VCC: Alimentación de energía. La mayoría de los módulos comerciales incorporan un regulador interno, por lo que admite tanto 3.3V como 5V.
  • GND: Tierra común del circuito.
  • SCL (Serial Clock Line): Línea de reloj del bus I2C.
  • SDA (Serial Data Line): Línea de datos del bus I2C.
  • XDA / XCL: Pines auxiliares I2C diseñados para conectar magnetómetros externos (configuración de 9 ejes). En la mayoría de proyectos estándar se dejan desconectados.
  • AD0 (Slave Address LSB): Pin de selección de dirección I2C. Si se conecta a GND, la dirección hexadecimal del dispositivo es 0x68. Si se conecta a VCC (3.3V), la dirección cambia a 0x69. Esto es vital si necesitas usar dos MPU6050 en el mismo bus.
  • INT (Interrupt): Pin de interrupción por hardware, útil para indicar al microcontrolador que hay nuevos datos listos para ser leídos sin saturar el ciclo principal.

2. El Bus I2C y la Comunicación por Registros

El protocolo I2C (Inter-Integrated Circuit) utiliza únicamente dos cables (SDA y SCL) para la comunicación bidireccional maestro-esclavo. Para garantizar la estabilidad de la señal a altas frecuencias (400 kHz en Modo Rápido), es altamente recomendable utilizar resistencias de pull-up externas de $4.7\text{ k}\Omega$ en las líneas SDA y SCL hacia VCC, aunque el módulo suele incluir resistencias internas básicas.

Internamente, el MPU6050 almacena las lecturas de sus sensores en registros de 16 bits repartidos en dos registros de 8 bits (parte alta y parte baja). Para obtener el valor final, debemos combinar ambos bytes mediante operaciones de desplazamiento a nivel de bits (bitshifting).

3. Código Optimizado en C++ para Lectura I2C

El siguiente código en C++ utiliza la librería nativa Wire.h para configurar el MPU6050, salir del modo de suspensión y leer continuamente los ejes de aceleración y giroscopio.

#include <Wire.h>

// Dirección I2C estándar del MPU6050 (AD0 conectado a GND)
const int MPU_addr = 0x68; 

// Variables globales para almacenar los datos crudos
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

void setup() {
  // Inicializar comunicación Serial y bus I2C
  Serial.begin(115200);
  Wire.begin();
  
  // Despertar al MPU6050 (por defecto inicia en modo sleep)
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B); // Registro de administración de energía (PWR_MGMT_1)
  Wire.write(0);    // Establecer en cero para despertar el dispositivo
  Wire.endTransmission(true);

  Serial.println("Inicialización del MPU6050 completada.");
}

void loop() {
  // Solicitar los registros de datos a partir del registro 0x3B (ACCEL_XOUT_H)
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B); 
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true); // Solicitar 14 bytes en total

  // Leer los registros combinando la parte alta (H) y baja (L)
  AcX = Wire.read() << 8 | Wire.read(); // Acelerómeto Eje X
  AcY = Wire.read() << 8 | Wire.read(); // Acelerómetro Eje Y
  AcZ = Wire.read() << 8 | Wire.read(); // Acelerómetro Eje Z
  Tmp = Wire.read() << 8 | Wire.read(); // Sensor de temperatura interno
  GyX = Wire.read() << 8 | Wire.read(); // Giroscopio Eje X
  GyY = Wire.read() << 8 | Wire.read(); // Giroscopio Eje Y
  GyZ = Wire.read() << 8 | Wire.read(); // Giroscopio Eje Z

  // Mostrar resultados por el Monitor Serie formateados
  Serial.print("AcX = "); Serial.print(AcX);
  Serial.print(" | AcY = "); Serial.print(AcY);
  Serial.print(" | AcZ = "); Serial.print(AcZ);
  Serial.print(" | Tmp = "); Serial.print(Tmp / 340.00 + 36.53); // Conversión a °C
  Serial.print(" | GyX = "); Serial.println(GyX);

  delay(500); // Retardo de medio segundo entre lecturas
}

El dominio del protocolo I2C y la gestión directa de registros en el MPU6050 optimizan el uso de memoria RAM y potencia de procesamiento en tus microcontroladores, evitando el uso de librerías pesadas e innecesarias. En próximos tutoriales, profundizaremos en el uso de filtros complementarios y de Kalman para eliminar el ruido y calcular ángulos de inclinación estables.

Dejá un comentario