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 a0x69. 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.