Acelerómetro y Giroscópio

Tutorial Arduino: Acelerómetro – Giróscopo MPU6050

Buenos días amigos técnologos, en nuestra entrada de hoy hablaremos de uno de los acelerómetros/giróscopos más usados del mercado, el MPU6050. Este es el acelerómetro giróscopo más usado para robots balancines, gimbal, drones…

En las prácticas que propondremos en nuestro tutorial, veremos como captar los datos brutos del sensor y posteriormente estos datos los convertiremos en ángulos que usaremos en nuestra programación.

Material necesario

Arduino uno leantecArduino UNO R3
aclerometro mpu6050 arduino MPU 6050
Cables protoboard leantecCables

Conozcamos el MPU6050

El MPU6050 es un sensor de movimiento el cual es capaz de medir la aceleración y el giro en los tres ejes del movimiento (x,y,z) con una precisión bastante considerable.

El MPU6050, tiene un conversor ADC de 16 bits, este conversor, convierte los datos a un valor digital y envía dichos datos a Arduino mediante I2C.

Prácticas propuestas

Para entender mejor el funcionamiento de sensor, vamos a realizar dos prácticas; en la primera, representaremos por el monitor serial de Arduino los valores brutos recogidos por el acelerómetro y el giróscopo. En la segunda convertiremos estos valores en ángulos.

Pero antes tenemos que hacer las conexiones pertinentes:

Esquema de conexión

Código

En esta práctica tenemos dos códigos, el codígo 1 representa los valores brutos recogidos por el MPU, el código dos representa por el monitor serial los ángulos.

Código 1

//Incluimos la librería para I2C
#include <Wire.h>
 
//Definimos la direccion I2C del MPU
#define MPU 0x68
 
//Definimos los ratios de conversión
#define A_R 16384.0
#define G_R 131.0
 
//Definimos la conversion de radianes a grados 180/PI
#define RAD_A_DEG = 57.295779
 
//El MPU da los valores en enteros de 16 bits
//Declaramos memorias para los valores brutos
int16_t AcX; 
int16_t AcY; 
int16_t AcZ;
int16_t GyX; 
int16_t GyY;
int16_t GyZ;
 
//Declaramos cadena de caracteres para los ángulos
float Acc[2];
float Gy[2];
float Angle[2];

void setup()
{
//Inicializamos el I2C y el puerto serie
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(9600);
}

void loop()
{
   //Leemos los valores del Acelerometro
   Wire.beginTransmission(MPU);
   Wire.write(0x3B); //Pedimos el registro 0x3B - corresponde al AcX
   Wire.endTransmission(false);
   Wire.requestFrom(MPU,6,true); //A partir del 0x3B, se piden 6 registros
   AcX=Wire.read()<<8|Wire.read(); //Cada valor ocupa 2 registros
   AcY=Wire.read()<<8|Wire.read();
   AcZ=Wire.read()<<8|Wire.read();
 
   //Leemos los valores del Giroscopio
   Wire.beginTransmission(MPU);
   Wire.write(0x43);
   Wire.endTransmission(false);
   Wire.requestFrom(MPU,4,true); //A diferencia del Acelerometro, solo se piden 4 registros
   GyX=Wire.read()<<8|Wire.read();
   GyY=Wire.read()<<8|Wire.read();
    
   /Mostramos los valores por el monitor serial
   Serial.print("Acelerometro bruto X: "); Serial.println(AcX);
   Serial.print("Acelerometro bruto Y: "); Serial.println(AcY); 
   Serial.print("Acelerometro bruto Z: "); Serial.println(AcZ);
   Serial.print("Giroscopo bruto Y: "); Serial.println(GyX);
   Serial.print("Giroscopo bruto X: "); Serial.println(GyY);
   Serial.print("Giroscopo bruto Y: "); Serial.println(GyZ);
 
   //Esperamos 1 segundo para poder visualizarlo en el monitor serial 
   delay(1000); 
}

Pantallazo monitor serial

monitor serial mpu6050
Aquí podemos apreciar los valores brutos del MPU.

Código 2

//Incluimos la librería para I2C
#include <Wire.h>
 
//Definimos la direccion I2C del MPU
#define MPU 0x68
 
//Definimos los ratios de conversión
#define A_R 16384.0
#define G_R 131.0
 
//Definimos la conversion de radianes a grados 180/PI
#define RAD_A_DEG = 57.295779
 
//El MPU da los valores en enteros de 16 bits
//Declaramos memorias para los valores brutos
int16_t AcX; 
int16_t AcY; 
int16_t AcZ;
int16_t GyX; 
int16_t GyY;
int16_t GyZ;
 
//Declaramos cadena de caracteres para los ángulos
float Acc[2];
float Gy[2];
float Angle[2];

void setup()
{
//Inicializamos el I2C y el puerto serie
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(9600);
}

void loop()
{
   //Leemos los valores del Acelerometro
   Wire.beginTransmission(MPU);
   Wire.write(0x3B); //Pedimos el registro 0x3B - corresponde al AcX
   Wire.endTransmission(false);
   Wire.requestFrom(MPU,6,true); //A partir del 0x3B, se piden 6 registros
   AcX=Wire.read()<<8|Wire.read(); //Cada valor ocupa 2 registros
   AcY=Wire.read()<<8|Wire.read();
   AcZ=Wire.read()<<8|Wire.read();
 
   //Calculamos los angulos Y, X respectivamente.
  Acc[1] = atan(-1*(AcX/A_R)/sqrt(pow((AcY/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
  Acc[0] = atan((AcY/A_R)/sqrt(pow((AcX/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
 
   //Leemos los valores del Giroscopio
   Wire.beginTransmission(MPU);
   Wire.write(0x43);
   Wire.endTransmission(false);
   Wire.requestFrom(MPU,4,true); //A diferencia del Acelerometro, solo se piden 4 registros
   GyX=Wire.read()<<8|Wire.read();
   GyY=Wire.read()<<8|Wire.read();
 
   //Calculamos el angulo del Giroscopio
   Gy[0] = GyX/G_R;
   Gy[1] = GyY/G_R;
 
   //Aplicamos un Filtro Complementario
   Angle[0] = 0.98 *(Angle[0]+Gy[0]*0.010) + 0.02*Acc[0];
   Angle[1] = 0.98 *(Angle[1]+Gy[1]*0.010) + 0.02*Acc[1];
 
   //Mostramos los valores por el monitor serial
   Serial.print("Angle X: "); Serial.println(Angle[0]);
   Serial.print("Angle Y: "); Serial.println(Angle[1]);
   
  //Esperamos 1 segundo para poder visualizarlo en el monitor serial
   delay(1000);
}

Pantallazo monitor serial

monitor serial mpu6050
En este pantallazo vemos los ángulos resultantes despues de hacer los calculos pertienetes con lo valores brutos.
Esperamos que les sea de utilidad y no olviden que en nuestro blog encontrará muchos otros post de su interes.

Etiquetas: , , , ,

7 Comments

  • Daniel dice:

    Hola,
    Estoy realizando un proyecto en el cual necesito medir la inclinación de vehículos de cuatro y dos ruedas para saber cómo se comportan en curvas.
    He realizado la programación con filtro complementario en una placa arduino nano y MPU6050.
    En estático todo correcto, pero con el vehículo en marcha los ángulos medidos se ven afectados por las fuerzas propias de la aceleración del vehículo, frenadas o fuerzas centrífugas en curvas, cimo si de un péndulo se tratase, por lo tanto no mide la inclinación real del vehículo.
    Alguna idea de lo que me puede estar ocurriendo?
    Gracias.

  • Alex dice:

    El código lo entiendo y está mil veces más claro que en otros tutoriales.
    Sin embargo, al cargar el código 1 me arroja constantemente este error:
    ¿Sabes que puede ser?
    Muchas gracias por anticipado

    «Arduino:1.8.3 (Windows 10), Tarjeta:»Arduino/Genuino Uno»

    El Sketch usa 4146 bytes (12%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
    Las variables Globales usan 516 bytes (25%) de la memoria dinámica, dejando 1532 bytes para las variables locales. El máximo es 2048 bytes.
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
    Ha ocurrido un error mientras se enviaba el sketch

    Este reporte podría tener más información con
    «Mostrar salida detallada durante la compilación»
    opción habilitada en Archivo -> Preferencias.»

  • Transductor dice:

    Me alegra ver que el código de mi tutorial sobre MPU-6050 (http://robologs.net/2014/10/15/tutorial-de-arduino-y-mpu-6050/) os ha servido para escribir el vuestro. Aunque se agradecería un poco de atribución.

    Final de línea.

  • Carlos Almeida dice:

    Good morning,
    This tutorial is very good, many thanks for the share. I have a question, is not possible work with the Z Axis?
    Regards
    Carlos Almeida

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *