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. También se utiliza para la estabilización de drones.
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.
Con un acelerómetro podemos medir esta aceleración, teniendo en cuenta que a pesar que no exista movimiento, siempre el acelerómetro estará midiendo 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 lo rápido que gira un cuerpo alrededor de su eje:
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
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.
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.
En Arduino UNO se puede conectar del modo siguiente.
En un ESP32 las conexiones serán las que se muestran a continuación.
Se puede programar en SteamakersBlocks de forma sencilla tal como se muestra a continuación
En el desplegable se muestran todas las opciones de los valores que puede proporcionar el acelerómetro.
Cálculo del módulo de la aceleración
El acelerómetro mide la aceleración en tres ejes:
aₓ → adelante / atrás
aᵧ → derecha / izquierda
a𝓏 → arriba / abajo
Aparte de medir la aceleración en cada uno de esos ejes también resulta importante conocer la resultante de la suma de esas tres aceleraciones. Esto lo conseguimos hallando la raíz cuadrada de la suma de los cuadrados de cada una de las tres aceleraciones.
Si el acelerómetro se encuentra en reposo sus sensores solamente están afectados por la aceleración de la gravedad. En una situación ideal si su posición fuese totalmente horizontal, solamente el sensor que indique la aceleración en el eje vertical habría de medir un valor similar al de la aceleración de la gravedad, pero si está ligeramente inclinado la aceleración de la gravedad afecta a los sensores de los tres ejes.
En reposo el valor de la aceleración total ha de ser un valor similar al de la aceleración de la gravedad (9,8 m/s2). En caída libre este valor será cercano a cero.
En el caso de un acelerómetro instalado en un CANSAT durante el lanzamiento la aceleración puede alcanzar entre 2 y 6 g, dependiendo del empuje del cohete. Durante el descenso, justo después de separarse del cohete, en caída libre el valor de la aceleración estará cerca de 0 g. Cuando el paracaídas se abre, existe un pico de aceleración que puede llegar a 2 g o más durante fracciones de segundo. Una vez el paracaídas está abierto y la caída es estable las lecturas suelen oscilar entre 0,8 g y 1,2 g, con pequeñas variaciones. En el momento del impacto contra el suelo, durante un breve instante, la aceleración puede alcanzar un valor negativo de 2 a 5 g dependiendo del tipo de superficie sobre la que se impacte, el viento y otras condiciones.
A continuación se muestra un programa que realiza esta integración de aceleraciones.
Cálculo del ángulo de inclinación del acelerómetro 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:
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:
Hay que tener en cuenta que estamos calculando el ángulo de inclinación, si deseáramos el ángulo de rotación es decir 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 programa del IDE de Arduino 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 se muestran los resultados al tener inclinado el MPU6050 aproximadamente 45° con respecto a X:
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 en estos casos.
Cálculo del ángulo de rotación del giroscopio MPU5060
El giroscopio proporciona directamente el valor de la velocidad angular, y para calcular el ángulo actual necesitamos integrar la velocidad y conocer el ángulo inicial. Esto lo hacemos usando la siguiente formula:
Se ha de 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.
Para calcular los ángulos de rotación tanto en el eje X como en Y se puede usar el siguiente programa:
// 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.
Se ha de tener en cuenta 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 mayoría 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 se muestra a continuación:
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 trabajamos 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:
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 se muestra el programa 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.
















No hay comentarios:
Publicar un comentario