Artículos recientes

Novedades

Tutorial MPU6050, Acelerómetro y Giroscopio

Tutorial MPU6050, Acelerómetro y Giroscopio

EL MPU6050 es una unidad de medición inercial o IMU (Inertial Measurment Units) de 6 grados de libertad (DoF) pues combina un acelerómetro de 3 ejes y un giroscopio de 3 ejes. Este sensor es muy utilizado en navegación, goniometría, estabilización, etc.

En este tutorial revisaremos los principios generales de acelerómetros y giroscopios, luego estudiaremos el sensor MPU6050 con mayor detalle y finalmente implementaremos ejemplos del MPU6050 con Arduino.

Aceleración y acelerómetros

La aceleración es la variación de la velocidad por unidad de tiempo es decir razón de cambio en la velocidad respecto al tiempo:

a=dV/dt

Así mismo la segunda ley de Newton indica que en un cuerpo con masa constante, la aceleración del cuerpo es proporcional a la fuerza que actúa sobre él mismo:

a=F/m

Este segundo concepto es utilizado por los acelerómetros para medir la aceleración. Los acelerómetros internamente tienen un MEMS(MicroElectroMechanical Systems) que de forma similar a un sistema masa resorte permite medir la aceleración.

                 MEMs acelerometro

Con un acelerómetro podemos medir esta aceleración, teniendo en cuenta que a pesar que no exista movimiento, siempre el acelerómetro estará sensando la aceleración de la gravedad.

Con el acelerómetro podemos hacer mediciones indirectas como por ejemplo si integramos la aceleración en el tiempo tenemos la velocidad y si la integramos nuevamente tenemos el desplazamiento, necesitando en ambos casos la velocidad y la posición inicial respectivamente.

 

Velocidad Angular y giroscopio

La velocidad angular es la tasa de cambio del desplazamiento angular por unidad de tiempo, es decir que tan rápido gira un cuerpo alrededor de su eje:

 velocidad angular

Los giroscopios utilizan un MEMS (MicroElectroMechanical Systems)  para medir la velocidad angular usando el efecto Coriolis   

Con un giroscopio podemos medir la velocidad angular, y si se integra la velocidad angular con respecto al tiempo se obtiene el desplazamiento angular (posición angular si se sabe dónde se inició el giro)

 

Módulo Acelerómetro y giroscopio MPU6050

Módulo MPU6050, Acelerómetro, Giroscopio I2C

EL módulo Acelerómetro MPU tiene un giroscopio de tres ejes con el que podemos medir velocidad angular y un acelerómetro también de 3 ejes con el que medimos los componentes X, Y y Z de la aceleración.

La dirección de los ejes está indicado en el módulo el cual hay que tener en cuenta para no equivocarnos en el signo de las aceleraciones.

 

 Ejes del MPU6050

 

La comunicación del módulo es por I2C, esto le permite trabajar con la mayoría de microcontroladores. Los pines SCL y SDA tienen una resistencia pull-up en placa para una conexión directa al microcontrolador o Arduino.

Tenemos dos direcciones I2C para poder trabajar:

Pin AD0

Dirección I2C

AD0=HIGH  (5V)

0x69

AD0=LOW  (GND o NC)

0x68

El pin ADDR internamente en el módulo tiene una resistencia a GND, por lo que si no se conecta, la dirección por defecto será 0x68.

El módulo tiene un regulador de voltaje en placa de 3.3V, el cual se puede alimentar con los 5V del Arduino.

 

Librería Para el PMU6050

En este tutorial trabajaremos con la librería desarrollada por Jeff Rowberg, la librería se descargar en:

https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050

Esta librería trabaja con una librería adicional para la comunicación I2C:

https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/I2Cdev

Para trabajar los siguientes ejercicios es necesario instalar las librerías en el IDE Arduino.

 

Conexiones entre Arduino y el MPU6050

Las conexiones son del modo I2C estándar:

MPU6050

Arduino Uno, Nano, Mini

Arduino Mega, DUE

Arduino Leonardo

  VCC

5V

5V

5V

  GND

GND

GND

GND

  SCL

A5

21

3

  SDA

A4

20

2

 

Conexines MPU6050 y Arduino

Ej.1: Realizar mediciones del MPU6050:

En este ejemplo realizaremos lecturas tanto del acelerómetro como del giroscopio.

El sketch para este ejercicio:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro y giroscopio en los ejes x,y,z
int ax, ay, az;
int gx, gy, gz;

void setup() {
  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
}

void loop() {
  // Leer las aceleraciones y velocidades angulares
  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);

  //Mostrar las lecturas separadas por un [tab]
  Serial.print("a[x y z] g[x y z]:\t");
  Serial.print(ax); Serial.print("\t");
  Serial.print(ay); Serial.print("\t");
  Serial.print(az); Serial.print("\t");
  Serial.print(gx); Serial.print("\t");
  Serial.print(gy); Serial.print("\t");
  Serial.println(gz);

  delay(100);
}

Repasemos las funciones de la librería utilizada en este ejercicio.

Inicialmente como se indico es necesario incluir las siguientes 3 librerías

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

Posteriormente crear la variable u objeto para el MPU6050, que en nuestro caso tiene el nombre de: “sensor”

MPU6050 sensor;

En este caso la dirección I2c es 0x68, pero si deseamos trabajar con otra dirección debemos modificar la linea anterior:

MPU6050 sensor(0x69);

Posteriormente en el void loop() inicializamos tanto la comunicación I2C como el MPU6050 y en nuestro caso la comunicación serial puesto que la usaremos más adelante:

  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

Al inicializar el sensor, los rangos por defecto serán:

- acelerómetro -2g a +2g

- giroscopio: -250°/sec a +250°/sec

Teniendo en cuenta que la resolución de las lecturas es de 16 bits por lo que el rango de lectura es de -32768 a 32767.

En el void loop() realizamos las lecturas y las guardamos en sus variables respectivas, esto se hace con las siguientes funciones:

  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);


La primera función lee la aceleración de los componentes x-y-z como parámetro, es necesario dar la dirección de las variables como argumento, para lo que se usa: &variable.

La segunda función realiza la lectura de la velocidad angular y guarda las lecturas en sus respectivas variables.

Finalmente enviamos por el puerto serial los datos leídos.

Si ubicamos el sensor en posición horizontal obtendremos medidas similares a los que mostramos a continuación.

Lecturas del MPU6050

  

Conforme movamos el sensor los componentes de aceleración irán cambiando en función del ángulo del sensor, puesto que la gravedad siempre es paralela al eje "Z" y se descompondrá en las componentes x-y-z del sensor.

  

Ej.2: Calibrando nuestro MPU6050

En este ejemplo realizaremos la calibración del MPU6050, esto es necesario ya que el sensor MPU6050 probablemente no se encuentre 100% en una posición horizontal, esto debido a que el sensor al ser soldado en el módulo puede estar desnivelado agregando un error en cada componente. De igual forma cuando instalemos el módulo en nuestro proyecto, puede estar desnivelado a pesar que a simple vista lo notemos correctamente nivelado.

Para solucionar este problema, se puede configurar en el módulo MPU6050 OFFSETS y de esta forma compensar los errores que podamos tener.


El sketch para realizar la calibración es el siguiente:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro y giroscopio en los ejes x,y,z
int ax, ay, az;
int gx, gy, gz;

//Variables usadas por el filtro pasa bajos
long f_ax,f_ay, f_az;
int p_ax, p_ay, p_az;
long f_gx,f_gy, f_gz;
int p_gx, p_gy, p_gz;
int counter=0;

//Valor de los offsets
int ax_o,ay_o,az_o;
int gx_o,gy_o,gz_o;

void setup() {
  Serial.begin(57600);   //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");

  // Leer los offset los offsets anteriores
  ax_o=sensor.getXAccelOffset();
  ay_o=sensor.getYAccelOffset();
  az_o=sensor.getZAccelOffset();
  gx_o=sensor.getXGyroOffset();
  gy_o=sensor.getYGyroOffset();
  gz_o=sensor.getZGyroOffset();
  
  Serial.println("Offsets:");
  Serial.print(ax_o); Serial.print("\t"); 
  Serial.print(ay_o); Serial.print("\t"); 
  Serial.print(az_o); Serial.print("\t"); 
  Serial.print(gx_o); Serial.print("\t"); 
  Serial.print(gy_o); Serial.print("\t");
  Serial.print(gz_o); Serial.print("\t");
  Serial.println("nnEnvie cualquier caracter para empezar la calibracionnn");  
  // Espera un caracter para empezar a calibrar
  while (true){if (Serial.available()) break;}  
  Serial.println("Calibrando, no mover IMU");  
  
}

void loop() {
  // Leer las aceleraciones y velocidades angulares
  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);

  // Filtrar las lecturas
  f_ax = f_ax-(f_ax>>5)+ax;
  p_ax = f_ax>>5;

  f_ay = f_ay-(f_ay>>5)+ay;
  p_ay = f_ay>>5;

  f_az = f_az-(f_az>>5)+az;
  p_az = f_az>>5;

  f_gx = f_gx-(f_gx>>3)+gx;
  p_gx = f_gx>>3;

  f_gy = f_gy-(f_gy>>3)+gy;
  p_gy = f_gy>>3;

  f_gz = f_gz-(f_gz>>3)+gz;
  p_gz = f_gz>>3;

  //Cada 100 lecturas corregir el offset
  if (counter==100){
    //Mostrar las lecturas separadas por un [tab]
    Serial.print("promedio:"); Serial.print("t");
    Serial.print(p_ax); Serial.print("\t");
    Serial.print(p_ay); Serial.print("\t");
    Serial.print(p_az); Serial.print("\t");
    Serial.print(p_gx); Serial.print("\t");
    Serial.print(p_gy); Serial.print("\t");
    Serial.println(p_gz);

    //Calibrar el acelerometro a 1g en el eje z (ajustar el offset)
    if (p_ax>0) ax_o--;
    else {ax_o++;}
    if (p_ay>0) ay_o--;
    else {ay_o++;}
    if (p_az-16384>0) az_o--;
    else {az_o++;}
    
    sensor.setXAccelOffset(ax_o);
    sensor.setYAccelOffset(ay_o);
    sensor.setZAccelOffset(az_o);

    //Calibrar el giroscopio a 0º/s en todos los ejes (ajustar el offset)
    if (p_gx>0) gx_o--;
    else {gx_o++;}
    if (p_gy>0) gy_o--;
    else {gy_o++;}
    if (p_gz>0) gz_o--;
    else {gz_o++;}
    
    sensor.setXGyroOffset(gx_o);
    sensor.setYGyroOffset(gy_o);
    sensor.setZGyroOffset(gz_o);    

    counter=0;
  }
  counter++;
}


El programa básicamente está modificando constantemente los offset intentando eliminar el error con la medida real que deseamos, en esta caso ax=0,ay=0,az=1g y gx=0,gy=0,gz=0.

Inicialmente leemos los offsets actuales y esperamos que el usuario envía un carácter por el puerto serie.
Antes de enviar el carácter es necesario ubicar el sensor en posición horizontal y evitar moverlo durante la calibración, dicha posición será nuestro nivel para futuras mediciones.

Después de enviar el carácter el programa realiza las lecturas tanto del acelerómetro como del giroscopio, usando un filtro estabilizamos un poco las lecturas y cada 100 lecturas comprobamos si los valores son cercanos a los valores que deseamos leer, dependiendo de esto se aumenta o disminuye los offsets. Esto hará que las lecturas filtradas converjan a:

-aceleración: p_ax=0 , p_ay=0 , p_az=+16384

-Velocidad angular: p_gx=0 , p_gy=0 , p_gz=0

Cuando en el monitor serial se observen valores cercanos a los anteriores debemos desconectar o reiniciar nuestro Arduino. Con esto el MPU6050 quedará configurado con el último offset calculado en el programa de calibración.

A continuación mostramos la salida del monitor serial después de enviar el carácter y esperar que los valores se acerquen a: 0 0 +16384 0 0 0 

 Calibracion MPU6050

  

Cuando tengamos estos valores debemos reiniciar el Arduino o simplemente cerrar y abrir el monitor serial. Posteriormente podemos volver a cargar el primer ejemplo para probar las lecturas con los nuevos offsets.

 

Ej.3: Escalado de lecturas

En este ejemplo vamos a escalar las lecturas a valores con las unidades de aceleración y velocidad angular.

Primero tenemos que saber los rangos con los que está configurado nuestro MPU6050, dichos rangos pueden ser 2g/4g/8g/16g para el acelerómetro y 250/500/1000/2000(°/s) para el giroscopio.

Para este ejemplo trabajaremos con los rangos por defecto (2g y 250°/s):

Variable

valor mínimo

valor central

valor máximo

Lectura MPU6050

-32768

0

+32767

Aceleración

-2g

0g

+2g

Velocidad angular

-250°/s

0°/s

+250°/s

Para escalar simplemente debemos usar una ecuación para convertir el valor leído en un valor de aceleración o velocidad angular.

A continuación se muestra el sketch con la ecuación correspondiente para escalar los valores:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro y giroscopio en los ejes x,y,z
int ax, ay, az;
int gx, gy, gz;

void setup() {
  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
}

void loop() {
  // Leer las aceleraciones y velocidades angulares
  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);
  float ax_m_s2 = ax * (9.81/16384.0);
  float ay_m_s2 = ay * (9.81/16384.0);
  float az_m_s2 = az * (9.81/16384.0);
  float gx_deg_s = gx * (250.0/32768.0);
  float gy_deg_s = gy * (250.0/32768.0);
  float gz_deg_s = gz * (250.0/32768.0);
  //Mostrar las lecturas separadas por un [tab]
  Serial.print("a[x y z](m/s2) g[x y z](deg/s):\t");
  Serial.print(ax_m_s2); Serial.print("\t");
  Serial.print(ay_m_s2); Serial.print("\t");
  Serial.print(az_m_s2); Serial.print("\t");
  Serial.print(gx_deg_s); Serial.print("\t");
  Serial.print(gy_deg_s); Serial.print("\t");
  Serial.println(gz_deg_s);

  delay(100);
}
 

Los valores que tenemos ahora ya están escalados a unidades de aceleración y velocidad angular. En nuestro caso hemos convertido la aceleración a valores en m/s^2 por lo que se reemplazó el valor de g=9.81, si se desea trabajar en unidades "g" no es necesario este último paso.

Si el sensor está en posición horizontal se debe obtener mediciones cercanas a 9.8 m/s^2 (aceleración de la gravedad terrestre) en la componente z de la aceleración.

 MPU6050 escalado

 

 

Ej.4: Calculando el ángulo de inclinación con el acelerómetro del MPU6050

Si tenemos en cuenta que la única fuerza que actúa sobre el sensor es la fuerza de la gravedad. Entonces los valores que obtenemos en las componentes del acelerómetro corresponden a la gravedad y los ángulos de la resultante serán la inclinación del plano del sensor, puesto que la gravedad siempre es vertical.

Para entenderlo mejor, asumiremos que estamos en un plano X-Z e inclinamos el MPU6050 un ángulo θ, dicho ángulo se calcula de la siguiente forma:

angulo de inclinacion 2D
 
Lo anterior nos sirve para calcular el ángulo en un plano 2D, pero para calcular los ángulos de inclinación en un espacio 3D tanto en X como en Y usamos las siguientes formulas:

 ecuacion angulo inclinacion 3D

 

Tener en cuenta que estamos calculando el ángulo de inclinación, si deseáramos el ángulo de rotación es decir por ejemplo el ángulo que rota el eje x en su mismo eje, entonces en las formulas necesitamos cambiar el ay por el ax y viceversa.

El sketch para calcular los ángulos de inclinación es el siguiente:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro  en los ejes x,y,z
int ax, ay, az;

void setup() {
  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
}

void loop() {
  // Leer las aceleraciones 
  sensor.getAcceleration(&ax, &ay, &az);
  //Calcular los angulos de inclinacion:
  float accel_ang_x=atan(ax/sqrt(pow(ay,2) + pow(az,2)))*(180.0/3.14);
  float accel_ang_y=atan(ay/sqrt(pow(ax,2) + pow(az,2)))*(180.0/3.14);
  //Mostrar los angulos separadas por un [tab]
  Serial.print("Inclinacion en X: ");
  Serial.print(accel_ang_x); 
  Serial.print("tInclinacion en Y:");
  Serial.println(accel_ang_y);
  delay(10);
}

 

A continuación mostramos los resultados al tener inclinado el MPU6050 aproximadamente 45° con respecto a X:

angulo con acelerometro MPU6050

 

Esto funciona solo si la única aceleración presente es la gravedad, pero si movemos rápidamente el MPU y sin realizar ninguna inclinación el ángulo que obtenemos con el programa anterior varía, generándonos errores para estos casos.

 

Ej.5: Calculando el ángulo de rotación usando el giroscopio del MPU5060


Como se explicó al inicio el giroscopio nos entrega la velocidad angular, y para calcular el ángulo actual necesitamos integrar la velocidad y conocer el ángulo incial. Esto lo hacemos usando la siguiente formula:

ecuacion de derivada giroscopio MPU6050

Tener en cuenta que cuando nos referimos a θx nos referimos al ángulo que gira el eje X sobre su propio eje. En la siguiente imagen se observa que la velocidad angular es perpendicular al plano de rotación.

rotacion MPU

 

Para calcular los ángulos de rotación tanto en el eje X como en Y usamos el siguiente sketch:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro y giroscopio en los ejes x,y,z
int gx, gy, gz;

long tiempo_prev, dt;
float girosc_ang_x, girosc_ang_y;
float girosc_ang_x_prev, girosc_ang_y_prev;

void setup() {
  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
  tiempo_prev=millis();
}



void loop() {
  // Leer las velocidades angulares 
  sensor.getRotation(&gx, &gy, &gz);
  
  //Calcular los angulos rotacion:
  
  dt = millis()-tiempo_prev;
  tiempo_prev=millis();
  
  girosc_ang_x = (gx/131)*dt/1000.0 + girosc_ang_x_prev;
  girosc_ang_y = (gy/131)*dt/1000.0 + girosc_ang_y_prev;

  girosc_ang_x_prev=girosc_ang_x;
  girosc_ang_y_prev=girosc_ang_y;

  //Mostrar los angulos separadas por un [tab]
  Serial.print("Rotacion en X:  ");
  Serial.print(girosc_ang_x); 
  Serial.print("tRotacion en Y: ");
  Serial.println(girosc_ang_y);

  delay(100);
}
 

Con este programa al girar aumentará o disminuirá el ángulo en función del sentido de giro del MPU

angulo rotacion giroscopio MPU6050

 

Tomar nota que la medida no es exacta incluso cuando no se mueve, el ángulo varía, o si se gira cierto ángulo y luego se regresa a la posición original el ángulo que medimos no es el inicial, esto se debe a que al integrar la velocidad angular y sumar el ángulo inicial hay un error producto de la mala medición del tiempo o del ruido en la lectura del MPU, el error por más pequeño que sea, se va acumulando en cada iteración y creciendo, este error es conocido como DRIFT.

Para disminuir el drift existen varios métodos, la mayoria aplica filtros para eliminar el ruido de las lecturas del sensor. También se pueden usar otros sensores como magnetómetros o acelerómetros y con los ángulos calculados con estos mejorar el cálculo del giroscopio.

Uno de los mejores filtros para eliminar el drift es el filtro Kalman, pero se necesita una buena capacidad de procesamiento computacional, haciéndolo difícil implementar en Arduino.

Otro filtro muy usado es el filtro de complemento, que mostramos a continuación:

 

Ej.6: Implementando un filtro de Complemento: acelerómetro + giroscopio

El filtro de complemento o en inglés "Complementary Filter" es uno de los más usados por su fácil implementación, combina el ángulo calculado por el giroscopio  y el ángulo calculado por el acelerómetro.

La necesidad de combinar ambas lecturas es que si solo trabajámos con el acelerómetro, este es susceptible a las aceleraciones producto del movimiento del MPU o a fuerzas externas, pero en tiempos largos el ángulo no acumula errores. A diferencia que si trabajamos solo con el giroscopio si bien este no es susceptible a fuerzas externas, con el tiempo el drift es muy grande y nos sirve solo para mediciones de tiempos cortos.

La ecuación para calcular el ángulo usando el filtro de complemento es: 

ecuacion filtro de complemento

De esta forma el ángulo del acelerómetro  está pasando por un filtro pasa bajos, amortiguando las variaciones bruscas de aceleración; y el ángulo calculado por el giroscopio tiene un filtro pasa altos teniendo gran influencia cuando hay rotaciones rápidas. Podemos probar también con otros valores diferentes a 0.98 y 0.02 pero siempre deben de sumar 1.

a continuación mostramos el sketch para realizar esta tarea:

// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo 
// del estado de AD0. Si no se especifica, 0x68 estará implicito
MPU6050 sensor;

// Valores RAW (sin procesar) del acelerometro y giroscopio en los ejes x,y,z
int ax, ay, az;
int gx, gy, gz;

long tiempo_prev;
float dt;
float ang_x, ang_y;
float ang_x_prev, ang_y_prev;

void setup() {
  Serial.begin(57600);    //Iniciando puerto serial
  Wire.begin();           //Iniciando I2C  
  sensor.initialize();    //Iniciando el sensor

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
}

void loop() {
  // Leer las aceleraciones y velocidades angulares
  sensor.getAcceleration(&ax, &ay, &az);
  sensor.getRotation(&gx, &gy, &gz);
  
  dt = (millis()-tiempo_prev)/1000.0;
  tiempo_prev=millis();
  
  //Calcular los ángulos con acelerometro
  float accel_ang_x=atan(ay/sqrt(pow(ax,2) + pow(az,2)))*(180.0/3.14);
  float accel_ang_y=atan(-ax/sqrt(pow(ay,2) + pow(az,2)))*(180.0/3.14);
  
  //Calcular angulo de rotación con giroscopio y filtro complemento  
  ang_x = 0.98*(ang_x_prev+(gx/131)*dt) + 0.02*accel_ang_x;
  ang_y = 0.98*(ang_y_prev+(gy/131)*dt) + 0.02*accel_ang_y;
  
  
  ang_x_prev=ang_x;
  ang_y_prev=ang_y;

  //Mostrar los angulos separadas por un [tab]

  Serial.print("Rotacion en X:  ");
  Serial.print(ang_x); 
  Serial.print("tRotacion en Y: ");
  Serial.println(ang_y);

  delay(10);
}

 

Ahora si movemos el MPU6050 rápidamente sin rotar, la variación del ángulo será mínima, además el drift se elimina y solo se nota en tiempos cortos.

Filtro complemento con MPU6050

 

 

  

Pueden adquirir los materiales usados en este tutorial en nuestra tienda:

Arduino Uno R3

Módulo MPU6050, Acelerómetro, Giroscopio I2C

79 Comments

    • Avatar
      Alexander Ortiz
      jul 5, 2016

      Disculpa podrias explicarme el porque del uso de las ecuaciones, es decir te entiendo float accel_ang_x=atan(ax/sqrt(pow(ay,2) + pow(az,2))) ya que lo describiste pero porque multiplicas por esto(180.0/3.14); te lo agradeceria si me respondieras de urgencia un saludo!

      • Avatar
        Naylamp
        jul 5, 2016

        Alexander, La ecuación atan() nos devuelve el resultado en radianes, se multiplica por (180/pi) para convertir el ángulo en grados sexagesimales.

    • Avatar
      Alexander Ortiz
      jul 5, 2016

      Gracias por el dato, pero que valores me vote el sensor, es decir el .getRotation() que valores me dan, me quede con esa duda!

      • Avatar
        Naylamp
        jul 5, 2016

        Las funciones getAcceleration() y getRotation() te devuelven valores de -32768 a 32767 (16bits), que corresponden de -2g a 2g y de -250°/sec a +250°/sec respectivamente si están en su rango por defecto, esto se explica mejor en el ejemplo 3. Cuando calculamos el ángulo con el acelerómetro no necesitamos escalar pues estos se dividen, pero si observas cuando trabajamos con el giroscopio allí si lo escalamos (valor/131).

    • Avatar
      Andrés
      jul 31, 2016

      Hola! Excelente explicación! Me aclaró muchas cosas que tenía en duda... Quería hacerte una pregunta, tenés idea como es el algoritmo de cálculo cuando le agregamos un magnetómetro al sistema? Y así también poder calcular la rotación en Z? Muchas gracias!

      • Avatar
        Naylamp
        ago 2, 2016

        Hola Andrés, para trabajar con un magnetómetro los cálculos son similares, con la diferencia que sensamos el campo magnético de la tierra para orientarnos, puedes revisar nuestro tutorial del Magnetómetro HMC5883L para más información.

    • Avatar
      eduardo arndt
      ago 25, 2016

      Hola, gran tutorial para entender el funcionamiento de la MPU 6050, pero estoy teniendo problemas con algo. Sería cómo conducir LEDs de los valores de ángulo medido en el Ejemplo 6?

      • Avatar
        Naylamp
        ago 26, 2016

        Hola Eduardo, cuantos leds y que tipo de efecto quieres manjar en función del ángulo. Por ejemplo si quieres manejar 10 leds puede usar la función map: nLed = map(angulo, -90, 90, 1, 10); Y luego con un Switch() activar los leds correspondiente.

    • Avatar
      GUSTAVO
      sep 14, 2016

      Hola tengo una duda cuando muevo la IMU6050 en el eje X a 178 grados este llega a ese valor pero lo dejo en esa posición y este empieza a descender hasta 1 no se supone que debe quedar en ese angulo?? igual con el eje Y

      • Avatar
        Naylamp
        sep 21, 2016

        Hola Gustavo, Lo que está pasando es que el giroscopio te mide los 178° pero converge a -1 que es el valor del acelerómetro, esto porque el código y las formulas están para trabajar en un rango de -90 y 90, esto para el acelerómetro. Si deseas trabajar en el rango de -180 y 180 tienes que usar: atan2 (y, x) // atan(y/x) , esto tomara en cuenta el signo, a esto agrega condiciones, pues de todas formas se anula el signo al trabajar con los cuadrados.

    • Avatar
      lucas
      oct 7, 2016

      Hola, simplemente quería felicitarte y agradecerte por la explicación. Muchas gracias!

    • Avatar
      pedro
      oct 9, 2016

      Hola que tal, excelente explicación... me nace una duda (olaja me puedas ayudar), me gustaría por medio de dos sensores MPU controlar dos servomotores de manera independiente en el plano (x y); es decir, por medio del registro del cambio angular (mpu), poder reflejarlo en cada uno de los servos, la idea es simularlo en un tipo de manipulador.gracias.

      • Avatar
        Naylamp
        oct 14, 2016

        Hola Pedro, va a depender con que movimiento quieres controlar el servo, por ejemplo si quieres controlar con la inclinación, solo escala el Angulo x o y de -90:90 a valores de 0:180 y envíalo al motor.

    • Avatar
      Nestor
      oct 11, 2016

      Buenas Noches (hora Venezuela) tengo un problema, ejecuto el Sketch para la calibración y me arroja que los offset son -1044 -303 1284 0 0 0 y envio el caracter para que inicie la calibración y parte con estos valores promedio: -4966 -26278 12484 -31 -371 -34 luego de pasado unos minutos llega a los valores que uno espera y realizo el reinicio, la desconexión del cable usb o cierro el monitor serial cargo Sketch para ver si la calibración funciona y me devuelve estos valores: a[x y z](m/s2) g[x y z](deg/s): -0.53 -19.62 9.34 -0.65 -2.07 -0.18 Ese proceso lo he realizado ya una 10 veces y solo una me funcionó pero perdió la cubrición. por favor necesito ayuda.

      • Avatar
        Naylamp
        oct 14, 2016

        Hola Néstor, puede ser que tu MCU esté trabajando con otro rango, el tutorial esta echo para trabajar con +/- 2g y 250 deg/s , si no guarda la calibración puedes solucionarlo configurando los offset al inicio de cada programa.

    • Avatar
      Jose
      oct 14, 2016

      Hola. ¿En la parte de la inclinación eso sería (x y y) Roll y pitch?, ¿Pero para yaw, la rotación en z como se determinaría?

      • Avatar
        Naylamp
        oct 28, 2016

        Estimado José, X y Y podrías trabajarlo como Roll y pitch pero dependiendo de la poción del MPU. Para el caso de Yaw lo puedes determinar con el giroscopio pero vas a tener un error acumulativo(Drift). Lo correcto es usar un magnetómetro o brújula digital.

    • Avatar
      Jose
      oct 14, 2016

      Hola. ¿En la parte de la inclinación eso sería (x y y) Roll y pitch?, ¿Pero para yaw, la rotación en z como se determinaría?

    • Avatar
      emmanuel
      oct 17, 2016

      no me aparecen las mediciones en el monitor serie nose porque... alguna ayuda????

      • Avatar
        Naylamp
        oct 28, 2016

        Verifica que la velocidad del monitor serie sea la misma que la que configuras en el código, verifica también que se haya cargado el programa. Para descartar que sea un error de conexión, al inicio, después de Serial.begin, envía algún texto por el monitor serial. Saludos

    • Avatar
      Norber
      oct 18, 2016

      Hola Naylamp. Estoy llevando acabo un proyecto de fin de carrera y el tutorial me ha servido de mucho, gracias. Sin embargo, mi objetivo es hallar la velocidad velocidad lineal de un objeto de 35 cm de radio al que va sujeto el modulo MPU6050, por lo tanto una vez que tengo los grados por segundo(máximo 2000 en este caso, ya que necesito el rango máximo) lo paso a rad/s y sabiendo el radio ( v = w · R = 34,91 · 0,35 = 12,21 m/s) obtengo una cifra en metros segundo demasiado baja, necesito mayor rango de velocidad y un mayor rango de valores de movimiento ya que al agitarlo rápidamente ya me da los valores máximos (32.768 valores) lo cual debe estar mal ya que yo no puedo alcanzar esas velocidades, simplemente agitando el mpu, me resulta extraño. Por ello se me plantea, en primer lugar, aumentar el rango de valores a 32 bits (2.147.483.647 valores) y así tener un mayor rango de velocidades y un mayor rango en el limite de movimiento del modulo, creo que esta podría ser la solución, no se si estoy en lo cierto. Resumiendo, en la librería MPU6050.h necesito establecer los valores a 32 bits. He estado probando a cambiar el tipo de entero, pero no me da resultado. Que debería hacer? Si sigues vivo después de leer el tocho =), te agradecería que me ayudaras.

      • Avatar
        Naylamp
        oct 28, 2016

        Estimado Norber, para cambiar el rango del giroscopio 2000°/s debes usar mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_2000); esto en el void setup() después de inicializar el modulo. La resolución del MPU es de 16bits y no se puede cambiar. También puedes medir la aceleración centrípeta (aceleración normal) con el acelerómetro y despejar la velocidad lineal.

    • Avatar
      Miguel
      oct 20, 2016

      Hola buenas noches, ojalá me pudieras apoyar con una idea. Necesito sensar con está IMU cuando un objeto se cae. No sé de que manera pudiera hacerlo, creo que sería de forma parecida a saber si va hacia delante o hacia atrás

      • Avatar
        Naylamp
        oct 28, 2016

        Estimado Miguel, el MPU sensa aceleraciones y velocidades angulares, y puedes detectar cualquier movimiento que influya en esas variables. Si es caída libre la aceleración no va a cambiar, pero si cuando topa el suelo, allí abría una desaceleración, ese cambio de aceleración podrías interprétalo como que el MPU ha caído al suelo, Si cuando el objeto cae y tiene rotación también puedes sensar las velocidades angulares e interprétalas como caída.

    • Avatar
      Eli Diaz
      oct 26, 2016

      Excelente información!!! Para implementar mi proyecto, debo de implementar las siguientes etapas: 1. Calibración. Se hace sólo una vez? O tengo que calibrar el MPU6050 cada vez que lo encienda (Incluir la calibración como parte de la programación). 2. Filtro. El filtro complementario lo utilizo para eliminar errores o disminuir perturbaciones. En el ultimo sketch que presentas se determina la rotación en X y la rotación en Y. No me queda claro como utilizo estos dos ultimos valores para obtener valores de aceleración filtrados. 3. Escalado de lecturas y procesamiento

      • Avatar
        Naylamp
        oct 28, 2016

        Eli, La calibración solo es necesario hacerla una vez. EL filtro complemento en si es para combinar el acelerómetro y el giroscopio. Si solo utiliza el acelerómetro para determinar el ángulo, cualquier aceleración generada por un desplazamiento va generar errores en el ángulo. En cambio sí solo uso el giroscopio va a ver un error acumulativo por causa de la integración de w. Este filtro se utiliza cunado queremos sensar el ángulo pero el MPU está en constante movimiento (Drones, robots móviles, etc). Si el PMU siempre va a estar fijo puedes solo tomar el vector de la aceleración de la gravedad para determinar los ángulos.

    • Avatar
      keybis
      oct 28, 2016

      porqué se escala dividiendo el valor en 131? osea de donde sale ese 131? ya que estoy usando es una beaglebone black en lugar de arduino me interesa saber de donde sale ese valor, igual me funciona más o menos, me sirvió en parte para lo que necesito de forma perfecta, pero igual me gustaría saber de donde sale esa constante, muchas gracias por subir y permitir ver ese tutorial.

      • Avatar
        Naylamp
        oct 28, 2016

        Estimado Keyvis , 131 es el factor de conversión: w= Lectura*(250/32768) = lectura*(1/131)

    • Avatar
      jose
      nov 30, 2016

      buenas noches me puede explicar que debo modificar al codigo del filtro complementario y obtener las lecturas de giro en z con variaciones minimas de error?

      • Avatar
        Naylamp
        dic 1, 2016

        Hola José, en el filtro de complemento usamos los ángulos obtenidos del acelerómetro, y estos se limitan a X y Y, puesto que una rotación en Z el acelerómetro no lo detectará pues usamos la gravedad para determinar el ángulo. Para esto es mejor usar un Magnetómetro.

    • Avatar
      Cristhian Santel Morales
      dic 17, 2016

      hola hermano tengo problema con lo que me sale en el monitor serial....sabes a que se debe y gracia

      a[x y z] g[x y z]:t272t-74t16394t3t-4t0
      a[x y z] g[x y z]:t284t-98t16390t-12t-33t-3
      a[x y z] g[x y z]:t262t-34t16428t71t81t-14
      a[x y z] g[x y z]:t214t-30t16484t-41t-67t-1
      a[x y z] g[x y z]:t232t-48t16392t-12t-17t-8
      a[x y z] g[x y z]:t320t-34t16430t1t-7t-7
      a[x y z] g[x y z]:t228t2t16494t-44t-81t-6
      a[x y z] g[x y z]:t250t-18t16426t-9t-26t-4
      a[x y z] g[x y z]:t334t-12t16402t-1t-21t-12
      a[x y z] g[x y z]:t308t-10t16402t-7t-16t-3
      a[x y z] g[x y z]:t316t-32t16396t10t14t-4
      a[x y z] g[x y z]:t266t-46t16410t-3t-23t4
      a[x y z] g[x y z]:t240t-100t16478t1t-8t-4
      a[x y z] g[x y z]:t226t-10t16398t7t9t-10
      a[x y z] g[x y z]:t280t-56t16394t7t-18t-3
      a[x y z] g[x y z]:t240t-20t16448t-33t-61t-1
      a[x y z] g[x y z]:t294t-6t16416t3t-12t-12
      a[x y z] g[x y z]:t314t-22t16320t10t5t-4
      a[x y z] g[x y z]:t312t-38t16424t3t-7t-11
      a[x y z] g[x y z]:t286t-28t16424t47t71t-7
      a[x y z] g[x y z]:t288t-18t16408t-26t-49t-11
      a[x y z] g[x y z]:t202t-82t16388t32t46t-2
      a[x y z] g[x y z]:t276t-48t16354t13t8t-17

      • Avatar
        Naylamp
        dic 23, 2016

        Hola Cristian, tus resultados son correctos, si te refieres a la “t” es porque te está faltando digitar el \, en lugar de “t” se debe enviar un "\t" que es un tab, si persiste el problema usa mejor un doble espacio " ".

    • Avatar
      aridai Ramirez
      dic 18, 2016

      hola hermano...tengo una duda en el ejemplo 6 por que cambias de signo a "ax" ,,gracias ojala me ayudes float accel_ang_x=atan(ay/sqrt(pow(ax,2) + pow(az,2)))*(180.0/3.14); float accel_ang_y=atan(-ax/sqrt(pow(ay,2) + pow(az,2)))*(180.0/3.14);

    • Avatar
      oscar roberto
      ene 9, 2017

      hola soy nuevo en esto pero si solo quisiera saver la aceleracion lineal

      • Avatar
        Naylamp
        feb 1, 2017

        Hola Oscar si solo necesitas la aceleración son las que se obtienen en el ejemplo 3. allí obtenemos la aceleración lineal y velocidad angular, teniendo en cuanta que en la aceleración también se está midiendo la aceleración de la gravedad.

    • Avatar
      Adrán Ricárdez
      ene 12, 2017

      ¿Por qué división del gx sobre 131? gracias

      • Avatar
        Naylamp
        feb 1, 2017

        Estimado Adrán , 131 es el factor de conversión: w= Lectura*(250/32768) = lectura*(1/131)

    • Avatar
      Rodrigo
      feb 9, 2017

      Hola, oye como puedo iniciar 2 sensores al mismo tiempo. Como defino la dirección con tus ejemplos?

      • Avatar
        Naylamp
        feb 17, 2017

        Hola Rodrigo, con el pin AD0 del MPU puedes cambiar la dirección, en el programa tienes que instanciar con la dirección respectiva:
        MPU6050 sensor1(0x68)
        MPU6050 sensor2(0x69)

    • Avatar
      Oscar Flo
      mar 21, 2017

      Muy buenas tardes. Antes que nada muchas gracias por compartir tu conocimiento y explicarlo tan detalladamente. estoy tratando de portar tu script a la plataforma NodemCU con lenguaje Lua. Dado que hay bastante información para hacer trabajar este sensor con Arduino y muy poca para el ESP8266 o NodeMCU, me he dado a la tarea de interpretar los scripts que se exponen por internet para digerir, comprender y después escribir desde cero código en Lua. En tu explicación, que de nuevo te agradezco por el tiempo y esfuerzo, me ha generado dos dudas, la primera tiene que ver con la utilización de la librería del MPU6050.cpp y MPU6050.h, el autor de la librería lee y escribe en registros que no están definidos o mostrados en las guías del mapeo de los registros del giroscopio, a menos no en las nuevas, para ser específicos, para el acelerómetro los registros 0x06, 0x08 y 0x0A (X,Y,Z) y para el giroscopio 0x13, 0x15 y 0x17 (X,Y,Z) según el archivo MPU6050.h y por lo que entiendo, tal parece que solo se lee y escribe en un solo registro de 8 bits o 1 Byte cada valor para cada eje de offset, siendo que en el mismo archivo de cabecera MPU6050.h, indica se componen de dos Bytes sumados para cada valor para los offsets (16 bits) o Low y High, como en la lectura propia de los valores en "crudo" del acelerómetro y giroscopio.La segunda duda y la que más me rompe la cabeza es la explicación del filtro:

      // Filtrar las lecturas
      f_ax = f_ax-(f_ax>>5)+ax;
      p_ax = f_ax>>5;

      f_ay = f_ay-(f_ay>>5)+ay;
      p_ay = f_ay>>5;

      f_az = f_az-(f_az>>5)+az;
      p_az = f_az>>5;

      f_gx = f_gx-(f_gx>>3)+gx;
      p_gx = f_gx>>3;

      f_gy = f_gy-(f_gy>>3)+gy;
      p_gy = f_gy>>3;

      f_gz = f_gz-(f_gz>>3)+gz;
      p_gz = f_gz>>3;

      No entiendo el por que de hacer un bitshift a la derecha en ambos casos, la resta de este valor y mucho menos el por que para el acelerómetro 5 bits de desplazamiento y en el giroscopio solo 3, quiero entender que se realiza un promedio de N valores leídos en "crudo", para tomar la media de estos pero no logro comprender la lógica del script.Espero y tengas el tiempo y la amabilidad de aclararme estas dudas con las que me encuentro detenido para hacer la portación de tu código a otra plataforma.
      Saludos desde México.

    • Avatar
      Oscar Flores
      mar 21, 2017

      Muy buenas tardes. Para empezar muchas gracias por el tiempo y el esfuerzo en este tutorial, es de gran ayuda. Estoy tratando de portar tu código en Arduino a la plataforma NodeMCU con lenguaje Lua para obtener de igual manera los ángulos X y Y de la tarjeta. Viendo tu código me surgen dos dudas principales:
      1.- Por que en el código se usan, a través de la librería MPU6050.cpp y MPU6050.h, tanto la lectura como escritura a registros que no aparecen en los documentos recientes del fabricante, más específicamente para el acelerómetro los registros 0x06, 0x08 y 0x0A para X,Y y Z, y los registros 0x13, 0x15 y 0x17 para el giroscipio. Y aun más extraño el que se grabe a esos registros como si se tratara de registros de 1 Byte u 8 bits, siendo que se indica en el archivo MPU6050.h, que son registros compuestos de 16 bits o 2 Bytes.
      2. La segunda y la que más me he roto la cabeza por entender es la parte del filtro de las lecturas en "crudo" tanto para acelerómetro como para el giroscopio. Quiero entender que lo que se hace es un promedio de N lecturas para sacar un valor medio, para después ir restando hasta llegar al valor deseado de offset, pero no comprendo por que se realiza un bitshift de 5 posiciones para uno y de 3 para otro y por que se restan estos valores.
      Espero y tengas el tiempo para contestar estas dudas que me tienen detenido con el desarrollo para portar a otra plataforma tu código.
      Saludos desde México.

      • Avatar
        Naylamp
        mar 23, 2017

        Hola Oscar, con respecto a lo primero, efectivamente los registros de los offset ya no se especifican en la documentación, pero si se está haciendo una correcta escritura y lectura, la función getXAccelOffset() en el archivo MPU6050.cpp usa la función readBytes() y aquí se leen 2 bytes y la función setXAccelOffset() usa la funcion writeWord() con esto escribe los 2 bytes, de igual manera sucede en los otros ejes y en el giroscopio. Con respecto a lo segundo el bitshift se usa en lugar de una división entre 2^n, por ejemplo: f_gz>>3 equivale a f_gz/8 de esta forma la ecuación para sacar el promedio es: p_gz = (f_gz-f_gz/8+gz)/8, y equivale al promedio de 8 lecturas, para el caso de la aceleración usamos un bitshift de 5 (un promedio de 32) puesto que es una variable de mayor ruido y variación.

    • Avatar
      David
      abr 5, 2017

      Disculpe, si se quisiera implementar en una FPGA programada mediante VHDL, como se haría el código que tienen las librerías? o cual es la función de las mismas?

    • Avatar
      Karina
      abr 6, 2017

      Hola, si quiero pasar los datos que obtuve a excel para graficarlos, ¿cómo podría hacerlo? Gracias

      • Avatar
        Naylamp
        abr 30, 2017

        Hola Karina, lo más simple sería almacenarlo los datos en una archivo en una SD y posteriormente importar desde Excel el archivo. En el ejemplo 4 de nuestro Tutorial Arduino y memoria SD se muestra como abrir los datos desde Excel.

    • Avatar
      Cristina
      abr 11, 2017

      Excelente tutorial, Felicitaciones!! Quería preguntar si es posible calcular el desplazamiento en los ejes x,y,z. Entiendo que el MPU tiene un centro de gravedad y respecto de él se calculan las inclinaciones ¿estoy en lo cierto? Ahora bien, quisiera poder calcular el desplazamiento de este centro de gravedad. Se me ocurre que podría tomar la velocidad lineal e integrarla dos veces para obtener la posición. Es posible calcular esta integral? Desde ya muchas gracias. Saludos!!

      • Avatar
        Naylamp
        abr 30, 2017

        Hola Cristina, sería similar a nuestro ejemplo 5, en donde a partir de la velocidad angular, integramos para obtener el desplazamiento angular. En tu caso tomarías la aceleración lineal, e integrarías dos veces para obtener el desplazamiento lineal. Integra de la misma forma que lo hacemos en el ejemplo 5. Pero al igual que mencionamos en el ejemplo, vas a tener un error con respecto a la posición inicial, error que se va a ir acumulando conforme pase el tiempo.

    • Avatar
      luis morales
      abr 16, 2017

      excelente tu tutorial felicitaciones y gracias por tu esfuerzo. el tamaño del sensor increíble lo que hace.

    • Avatar
      Brayan
      abr 21, 2017

      Porque en la parte de millis q es para calcular el dt lo divides entre 1000 si te da un valor en milisegundos xq lo divides entre 1000 que seria como si fuera microsegundos, no lo entiendo :(

      • Avatar
        Naylamp
        abr 30, 2017

        Hola Brayan, la división es para obtener un valor en segundos, por ejemplo 5000 ms lo dividimos entre 1000 nos da 5 segundos.

    • Avatar
      Cesar
      may 20, 2017

      Excelente explicación ... una consulta si utilizo las librerías para hacer un dispositivo tengo que tener derechos de autor ? ...

    • Avatar
      Yilber
      jun 12, 2017

      Hola como hago para trabajar el MPU 6050 para medir fuerza g que sean mayores a 2g es decir necesito medir fuerzas g comprendidas entre 5 y 7 g

      • Avatar
        Naylamp
        jun 23, 2017

        Hola Yiber, Por defecto el rango es de +/-2g en tu caso tienes que cambiar el rango a +/-8g para configurar el rango del acelerómetro usa la función setFullScaleAccelRange(MPU6050_ACCEL_FS_8) después de inicializar el MPU.

    • Avatar
      charlie
      jun 17, 2017

      hola amigo, quisiera saber si se puede conectar el Acelerómetro directa a la computadora y usarlo desde la pc directamente

      • Avatar
        Naylamp
        jun 23, 2017

        Hola Charlie, no es posible, el modulo se comunica por I2C, necesitas un microcontrolador como por ejemplo un Arduino que tenga una interfaz USB para usarlo como intermediario entre la PC y el sensor.

    • Avatar
      Mafer Vizcaino
      jun 26, 2017

      Hola, quisiera saber que tengo que modificar para trabajar con el rango de 180 a -180Gracias y buen dia

    • Avatar
      Allinger
      jul 14, 2017

      Amigos quisiera saber como leer la temperatura del sensor mpu6050

      • Avatar
        Naylamp
        jul 29, 2017

        Hola Luis, el módulo usado tiene un regulador de 3.3V Hola, para leer la temperatura usa: temp=sensor.getTemperature() el resultado es un int16 con al temperatura, si no logras obtener la temperatura agrega la siguiente línea en el setup: sensor.setTempSensorEnabled(true)

    • Avatar
      Jesus Amador
      ago 13, 2017

      Hola que tal, tengo una duda en cuanto al filtro utilizado, que es exactamente lo que hace?f_ax = f_ax-(f_ax>>5)+ax; p_ax = f_ax>>5;podrías explicar un poco? Gracias.

      • Avatar
        Naylamp
        ago 29, 2017

        Hola Jesus, El bitshift se usa en lugar de una división entre 2^n, por ejemplo: f_ax >>5 equivale a f_ax /32 , Las dos líneas que mencionas equivale a: p_ax = (f_ax-f_ax/32+ax)/32 esto es el promedio de 32 lecturas.

    • Avatar
      Anthony
      ago 28, 2017

      Excelente tutorial no tendrán alguno de armado de un Drone!!!

    • Avatar
      Danny
      sep 10, 2017

      disculpa como puedo determinar el angulo de rotacion en Z??

      • Avatar
        Antonio
        mar 15, 2018

        Buenas, yo tambien estoy interesado en conocer el ángulo de rotación enZ, ¿alguien sabría decirnos?

    • Avatar
      Elias Cepeda
      sep 25, 2017

      Hola, muy buen tutorial. Veo que as respondido varias preguntas y entregas tu tiempo en hacer eso (para todos los que opinan con sus respuestas tambien les va esto :v ) y me parece muy bueno de tu parte. Estoy siguiendo este tutorial y queria algo de orientacion ha mas de la que me brinda google en la implementacion de este modulo con arduino y un mini drone de 4 motores, mi pregunta es: ¿habria alguna funcion como la de los led (map:led) para poder realizar mi labor con los motores de un mini drone?

    • Avatar
      ERNEST
      nov 21, 2017

      Buenos días, primero de todo darte la gracias por este tutorial esta muy bien explicado. en segundo lugar quería comentarte mi error, bueno no es un error en si. a la hora de hacer la calibración del sensor, no he conseguido llegar a valores cercanos al 0 como tu dices, eso me hace que al hacer la conversión en el eje Z tenga una aceleración de 10-11 m/s2.tengo el sensor en horizontal y sujeto para que no se mueva. mi pregunta es : el tiempo del calibrado es muy extenso? o tendría que ver resultados cercanos al cero en pocos minutos? en caso de no obtenerlos que solución me recomendaría.muchas gracias.

    • Avatar
      yilber
      nov 26, 2017

      Hola amigo, como podria yo aplicarle FFT a mis datos de aceleracion o como podria yo enviar mis datos a excel he usado estos pero no me sale. void setup(){ … // Configura captura de datos con Parallax_DAQ // Mostrará en Excel: Tiempo|ACC_X|ACC_Y|ACC_Z|GYRO_X|GYRO_Y|GYRO_Z| // ... | ... | ... | ... | ... | ... | ... | // ... | ... | ... | ... | ... | ... | ... | // Serial.println("CLEARDATA"); Serial.println("LABEL, TIME, ACC_X,ACC_Y,ACC_Z,GYRO_X,GYRO_Y,GYRO_Z"); … } Parte incluida en el bucle continuo: void loop(){ … // Print the raw values. // Serial.print(F("DATA, TIME, ")); Serial.print(acc_gyro.value.acc_x, DEC); Serial.print(F(", ")); Serial.print(acc_gyro.value.acc_y, DEC); Serial.print(F(", ")); Serial.print(acc_gyro.value.acc_z, DEC); Serial.print(F(", ")); Serial.print(acc_gyro.value.gyro_x, DEC); Serial.print(F(", ")); Serial.print(acc_gyro.value.gyro_y, DEC); Serial.print(F(", ")); Serial.print(acc_gyro.value.gyro_z, DEC); Serial.println(F(", "));

    • Avatar
      Rafael
      dic 3, 2017

      Saludos Naylamp, primero que nada muchas gracias por el aporte, es muy útil y completo, excelente. Quisiera me puedas ayudar con mi consulta: Implementé el control del movimiento de un motor de pasos con el MPU de forma automática, cuando conecto el Arduino a la PC para poder ver en el monitor serial y hacer que funcione el proyecto todo va muy bien, pero cuando lo hago funcionar sin conectar a la PC, es decir conectando el Arduino desde una fuente continua, no arranca. He descartado una serie de posibles fallas llegando a que el MPU no le manda datos al Arduino a no ser que arranque el monitor serial. ¿Como puedo corregir esto?

    • Avatar
      Vicente
      feb 23, 2018

      Hola muy buen trabajo. Me ha servido de mucho y he podido entender y comprender gran parte de tus enseñanzas. Tengo una pregunta: Cuando he cargado el código y he abierto el serial ploter, puedo ver la evolución de los parámetros, sin embargo, el valor del eje Z, se desplaza con el tiempo y siempre crece de forma bastante rápida, es decir, en unos 15 segundos crece desde 0 hasta 50 (supongo que grados) en la escala de la izquierda. El desplazamiento lo puedo corregir girando el eje Z en el plano horizontal en el sentido del reloj. ? Me puedes indicar a que puede ser debido este desplazamiento. Gracias por todo.

    • Avatar
      Antonio
      mar 15, 2018

      Buenas, estoy interesado en conocer el ángulo de rotación en Z, ¿alguien sabría decirme como?

    • Avatar
      Thais
      abr 1, 2018

      ¿cómo puedo utilizar de 0 a 180 grados en el eje x?

    • Avatar
      Germán Alberto
      abr 21, 2018

      Señores Naylamp Mechatronics Cordial saludo Muchas gracias por la información sobre el sensor MPU6050. ¿Qué intervalo de tiempo hay entre uno y otro paquete de datos con la información generada por el sensor? Si quiero salvar esta información en una memoria SD haciendo uso de un datalogger, ¿Cuál sería el intervalo de tiempo mínimo para hacerlo? En un datalogger la unidad de tiempo real va de segundo en segundo. ¿Cómo hago para conseguir registrar datos en intervalos menores a un segundo? Gracias

    • Avatar
      esteban
      may 16, 2018

      lo amo

    • Avatar
      DAVID LANCHEROS
      jun 21, 2018

      ME SALE ERROR EN ESTAS LINEAS sensor.getAcceleration(&ax, &ay, &az); sensor.getRotation(&gx, &gy, &gz);

    • Avatar
      Xavier
      jul 10, 2018

      Excelente tutorial.Solamente te recomedaría NO usar variables globales indiscriminadamente. Las a's y las g's funcionan perfectamente como variables locales.Me permití modificar un poco el código de tu primer ejemplo:// Librerias I2C para controlar el mpu6050 // la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h #include "I2Cdev.h" #include "MPU6050.h" #include "Wire.h"// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo // del estado de AD0. Si no se especifica, 0x68 estará implicito MPU6050 sensor;bool connected{ false };void setup() { Serial.begin(57600); //Iniciando puerto serial Wire.begin(); //Iniciando I2C sensor.initialize(); //Iniciando el sensorif (sensor.testConnection()) { Serial.println("Sensor iniciado correctamente"); connected = true; } else { Serial.println("Error al iniciar el sensor"); connected = false; } }void loop() { if( connected ){ int ax, ay, az; int gx, gy, gz; // two's complement (aka, signed int) // pp 29, https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf sensor.getAcceleration(&ax, &ay, &az); sensor.getRotation(&gx, &gy, &gz);Serial.print("a[x y z] r[x y z]:t"); Serial.print(ax); Serial.print("t"); Serial.print(ay); Serial.print("t"); Serial.print(az); Serial.print("t"); Serial.print(gx); Serial.print("t"); Serial.print(gy); Serial.print("t"); Serial.println(gz); } else{ Serial.println( "No sensor found!" ); } delay(100); }

Leave a Reply

* Name:
* E-mail: (Not Published)
   Website: (Site url withhttp://)
* Comment: