[Iniciando módulos de interacción social]
Saludos, humano. Al habla Transductor. ¿Alguna vez has intentado configurar una IMU con Arduino y obtener lecturas? Si tu respuesta es afirmativa, habrás notado que no es nada fácil. Muchas IMUs utilizan protocolos como I2C o SPI, dan valores extraños, requieren trigonometría… oh, ¿he mencionado ya que las IMUs dan siempre lecturas erróneas?
Si has acabado en esta página es que necesitas un empujón. Sabes que una IMU es un dispositivo electrónico. Y que no se come. Pero ahí se acabó. Probablemente no tienes ni idea de cómo conectarla a Arduino y ya no digamos obtener una lectura decente.
Así pues, has venido al lugar indicado. Transductor va a explicarte cómo conseguir unas lecturas precisas con una IMU MPU-6050 y Arduino. Depuraremos los valores, calcularemos el ángulo de inclinación y filtraremos el ruido con un Filtro Complementario (Complementary Filter).
Pero hay que empezar por el principio. Y el principio es…
Da Theory
Antes de empezar, ¿qué es una IMU? Se trata de un dispositivo capaz de mesurar la fuerza (acceleración) y la velocidad. Genéricamente consta de un Acelerómetro y un Giroscopio. Por lo tanto: una IMU no mesura ángulos. Por lo menos no directamente, requiere algunos cálculos.
El MPU-6050 es una IMU de 6DOF (se lee “6 Degrees Of Freedom“). Esto significa que lleva un acelerómetro y un giroscopio, ambos de 3 ejes (3+3 = 6DOF). Hay IMUs de 9DOF, en este caso también llevan un magnetómetro. Otras pueden tener 5DOF, en cuyo caso el giroscopio sólo mide dos ejes, etc.
El MPU-6050 opera con 3.3 voltios, aunque algunas versiones (como la mía) llevan un regulador que permite conectarla a 5V.
El MPU-6050 utiliza el protocolo de comunicación I2C. En este tutorial no voy a entrar en detalles de cómo funciona este protocolo, pero puedes encontrar más información aquí.
Ya tienes claro lo que es una IMU. Veamos cada una de sus partes.
El acelerómetro
El acelerómetro mide la aceleración. Quién iba a decirlo. La aceleración puede expresarse en 3 ejes: X, Y y Z, las tres dimensiones del espacio. Por ejemplo, si mueves la IMU hacia arriba, el eje Z marcará un cierto valor. Si es hacia delante, marcará el eje X, etc.
Si haces memoria de tus clases de la ESO (o equivalentes), recordarás que la gravedad de la Tierra tiene una aceleración de aprox. 9.8 m/s², perpendicular al suelo como es lógico. Así pues, la IMU también detecta la aceleración de la gravedad terrestre.
¿Esto es un problema? ¡Al contrario, lector! Gracias a la gravedad terrestre puedes usar las lecturas del acelerómetro para saber cuál es el ángulo de inclinación respecto al eje X o eje Y.
Supongamos que la IMU esté perfectamente alineada con el suelo. Entonces, como puedes ver en la imagen, el eje Z marcará 9.8, y los otros dos ejes marcarán 0. Ahora supongamos que giramos la IMU 90 grados. Ahora es el eje X el que está perpendicular al suelo, por lo tanto marcará la aceleración de la gravedad.
Si sabemos que la gravedad es 9.8 m/s², y sabemos que mesura dan los tres ejes del acelerometro, por trigonometría es posible calcular el ángulo de inclinación de la IMU. Una buena fórmula para calcular el ángulo es:
Hay otras fórmulas equivalentes, pero yo prefiero la tangente.
Dado que el ángulo se calcula a partir de la gravedad, no es posible calcular el ángulo Z con esta fórmula ni con ninguna otra. Para hacerlo se necesita otro componente: el magnetómetro, que es un tipo de brújula digital. El MPU-6050 no lleva, y por tanto nunca podrá calcular con precisión el ángulo Z. Sin embargo, para la gran mayoría de aplicaciones sólo se necesitan los ejes X e Y.
El Giroscopio
En un principio, los giroscopios eléctricos eran unos voluminosos artefactos que valían la mayor parte del presupuesto militar de un estado. Más tarde, durante la segunda guerra mundial se emplearon para dirigir cohetes y torpedos. Por suerte, gracias la revolución digital y la miniaturización de circuitos, hoy en día cualquier aficionado a la electrónica puede permitirse uno. Aunque no para construir misiles.
El giroscopio mide la velocidad angular. Si no tienes muy frescas tus lecciones de física del instituto voy a recordarte que la velocidad angular es el número de grados que se gira en un segundo.
Si sabemos el ángulo inicial de la IMU, podemos sumarle el valor que marca el giroscopio para saber el nuevo ángulo a cada momento. Supongamos que iniciamos la IMU a 0º. Si el giroscopio realiza una medida cada cierto intervalo de tiempo, y marca un cierto valor en el eje Y, tendremos el ángulo con esta sencilla fórmula:
Dónde Δt es el tiempo que transcurre cada vez que se calcula esta fórmula, AnguloYAnterior es el ángulo calculado la última vez que se llamó esta fórmula y GiroscopioY es la lectura actual del ángulo Y del giroscopio.
(Por ejemplo: si en el instante t=0 se inicia la IMU a 0º, y al cabo de 0’5 segundos el giroscopio marca 12º, el nuevo ángulo sería 6º)
Y lo mismo pasa con los ejes X, Z. Sólo que se suele ignorar el eje Z, puesto que al no poder calcular un ángulo Z con el Acelerómetro, no se puede aplicar un Filtro Complementario para el eje Z (en seguida verás qué es un Filtro Complementario).
Ya tenemos las lecturas. ¿Simple, verdad? Pues en realidad no tanto.
Error en las medidas
En un mundo ideal donde hadas y elfos cantan alegres y dulces canciones alrededor de hogueras, donde los dragones surcan los cielos, los árboles hablan con las setas y C++ no provoca errores en tiempo de ejecución, las IMUs son unos artefactos mágicos que con un poco de trigonometría puden dar un ángulo con total exactitud.
Pero estás en el mundo real, hijo. Y hay dos problemas muy importantes: el ruido y los errores.
El ruido son todas aquellas interferencias que afectan a los dispositivos electrónicos. El acelerómetro es capaz de medir cualquier ángulo, sin embargo sus lecturas son ruidosas y tienen un cierto margen de error.
Si alguna vez quieres dibujar un gráfico de las medidas de un acelerómetro en función del tiempo, verás algo de este estilo:
El ángulo real (ideal) está marcado en azul, y las lecturas reales del sensor están en rojo. Puedo afirmar que no cumple a rajatabla la definición de “preciso”.
Por si esto fuera poco, el acelerómetro también detecta cualquier aceleración que no sea la de la gravedad. Por tanto, si mueves la IMU sin girarla, al aplicar una aceleración en otro eje, la IMU lo detectará como un cambio de rotación.
Por otra parte tenemos el giroscopio. A diferencia del acelerómetro, da las medidas con mucha precisión. Pero al realizar los cálculos del ángulo es inevitable que se produzca un pequeño error, que con el tiempo va acumulándose hasta que cualquier similitud con la realidad es pura coincidencia. Esto en inglés se llama drift.
¿Significa esto que debes darte por vencido? Para nada. Hay una (varias) forma(s) de combinar los datos del acelerómetro y el giroscopio para así obtener medidas acuradas. Y aquí es dónde entra en juego:
Tu amigo el filtro
La idea es muy simple: hay que conseguir eliminar el ruido, el drift y conseguir que el acelerómetro no cambie de ángulo al detectar otra fuerza que no sea la gravedad.
Hay distintos algoritmos, llamados filtros, que hacen esta tarea. Uno de los mejores es el famoso Filtro de Kálman, del que puede que hayas oído a hablar. Se utiliza en los aviones, cohetes y satélites geoestacionarios.
El filtro de Kálman es sorprendente. Es considerado uno de los mayores hallazgos del siglo pasado, y con razón. Capaz de calcular el error de cada medida a partir de las medidas anteriores, eliminarlo y dar el valor real del ángulo. En cierto modo es un algoritmo que aprende en cada iteración. No suena nada mal, ¿verdad?
Sin embargo tiene dos problemas:
- Tiene un coste de procesamiento algo elevado
- Es muy complicado de entender. Y pongo énfasis en el “muy”. Échale un vistazo.
Así pues, tenemos otros filtros a nuestra disposición. El que vamos a utilizar es conocido como Filtro Complementario o Complementary Filter en inglés. Es ideal para implementar con Arduino: fácil de utilizar, bajo coste de procesamiento y con una precisión muy buena.
¿En qué consiste exactamente? El Filtro Complementario es en realidad una unión de dos filtros diferentes: un High-pass Filter para el giroscopio y un Low-pass Filter para el Acelerómetro. El primero deja pasar únicamente los valores por encima de un cierto límite, al contrario que el Low-pass filter, que sólo permite a los que están por debajo.
La fórmula resultante de combinar (complementar, de aquí el nombre) los dos filtros es:
Dónde AnguloGyro es el ángulo del Giroscopio que hemos calculado previamente, y AnguloAccel con el ángulo del Acelerómetro calculado con la fórmula de la tangente. Δt es el tiempo que ha pasado (en segundos) desde la última vez que se ha calculado el filtro. Esta fórmula es la misma para el eje X, Y.
NOTA: Si lo deseas, puedes probar de cambiar el valor de 0.98 y 0.02 por un valor personalizado. Eso sí, ambos tienen que sumar 1.
Y así se termina Da Theory. Ahora hay que utilizar las fórmulas en un código para Arduino.
In Praxis
Las fórmulas y los números viven tranquilas en el abstracto mundo de las matemáticas. A pesar de que este lugar está custodiado por unos seres divinos llamados matemáticos, cuya función es asegurarse de que sólo los licenciados puedan utilizar las fórmulas en el mundo real, vamos a implementar estos algoritmos en una placa Arduino.
Las conexiones son muy simples. Con los 5V del USB tendrás energía de sobra.
- MPU Vcc -> Arduino 3.3v (o 3v3 en algunos modelos)
- MPU Gnd -> Arduino Gnd
- MPU SCL -> Arduino A5
- MPU SDA -> Arduino A4
IMPORTANTE! Estas conexiones están probadas en una Arduino UNO y Arduino Nano, cuyos pines SDA y SCL son A4 y A5 respectivamente. Si utilizas otra placa puede que los pines sean otros. En este enlace aparece una lista con los pines SDA y SCL de otras versiones de Arduino (Due, Leonardo…)
Así pues, tienes las fórmulas. Tienes la IMU. Tienes una placa Arduino. Tienes el circuito. ¿Qué falta? Saber cómo interaccionar con la IMU para obtener lecturas. El MPU-6050 dará unos raw values (“valores en bruto”) que después habrá que refinar (dividir por una constante) a fin de conseguir valores utilizables.
La web oficial de Arduino dispone de un ejemplo para leer datos de la MPU-6050. Partiré de ella, aunque habrá que modificarla considerablemente ya que sólo da los valores sin refinar del Giroscopio y el Acelerómetro.
Empezamos por las declaraciones.
#include <Wire.h> //Direccion I2C de la IMU #define MPU 0x68 //Ratios de conversion #define A_R 16384.0 #define G_R 131.0 //Conversion de radianes a grados 180/PI #define RAD_A_DEG = 57.295779 //MPU-6050 da los valores en enteros de 16 bits //Valores sin refinar int16_t AcX, AcY, AcZ, GyX, GyY, GyZ; //Angulos float Acc[2]; float Gy[2]; float Angle[2];
Voy a comentarlo. La primera línea incluye la librería Wire.h, necesaria para la interacción vía protocolo I2C.
#define MPU 0x68 es la dirección I2C de la IMU que se especifica en la documentación oficial.
Los ratios de conversión son los especificados en la documentación. Deberemos dividir los valores que nos dé el Giroscopio y el Acelerómetro entre estas constantes para obtener un valor coherente. RAD_A_DEG es la conversión de radianes a grados.
La IMU da los valores en enteros de 16 bits. Como Arduino los guarda en menos bits, hay que declarar las variables que almacenarán los enteros provinientes de la IMU como un tipo de enteros especiales. int16_t AcX, AcY, AcZ, GyX, GyY son, pues, los raw_values de la IMU.
Finalmente tenemos tres arrays (Acc[], Gy[], Angle[]) que guardan el ángulo X, Y del Acelerómetro, el Giroscopio y el resultado del Filtro respectivamente. [0] se corresponde a X. [1] a Y.
La función setup es la siguiente:
void setup() { Wire.begin(); Wire.beginTransmission(MPU); Wire.write(0x6B); Wire.write(0); Wire.endTransmission(true); Serial.begin(9600); }
Se inicia la comunicación por I2C con el dispositivo MPU, y se “activa” enviando el comando 0. También se inicia el puerto de série para ver los resultados.
El void loop es un poco más complejo. Se leen y guardan los datos de la IMU, se calcula el ángulo y se aplica el filtro complementario. Para simplificar el código, he supuesto que Δt es 0.01. Pero si quieres ser riguroso, humano, deberías calcular el tiempo con la función millis() de Arduino.
void loop() { //Leer los valores del Acelerometro de la IMU Wire.beginTransmission(MPU); Wire.write(0x3B); //Pedir 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(); //A partir de los valores del acelerometro, se calculan los angulos Y, X //respectivamente, con la formula de la tangente. 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; //Leer 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(); //Calculo del angulo del Giroscopio Gy[0] = GyX/G_R; Gy[1] = GyY/G_R; //Aplicar el 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]; //Mostrar los valores por consola Serial.print("Angle X: "); Serial.print(Angle[0]); Serial.print("\n"); Serial.print("Angle Y: "); Serial.print(Angle[1]); Serial.print("\n------------\n"); delay(10); //Nuestra dt sera, pues, 0.010, que es el intervalo de tiempo en cada medida }
Escribe estas tres funciones en un sólo código, compila, carga. Si ahora abres el Monitor de Série, deberías ver como van oscilando los números muy rápidamente. Puedes probar a girar la IMU y detener el Desplazamiento Automático para ver como cambian los ángulos.
El filtro tarda un tiempo a adaptarse a los cambios, lo cuál es normal al filtrar las frecuencias.
Y esto es todo. Espero que esta guía te sirva de referencia para futuros proyectos. Los filtros de este tipo suelen utilizarse conjuntamente con un Controlador PID (PID controller) para controlar y corregir el movimiento de motores en función de las lecturas de la IMU. Si estás interesado en realizar un proyecto como un drone o un robot balanceador, puede ser de utilidad comprender cómo funciona.
Finalmente debo decir que existen librerías para Arduino que incluyen Filtros de Kálman y Filtros Complementarios. ¿Por qué no las he mencionado? Mi consejo cuándo construyas tu proyecto es que, si puedes, evites las librerías de terceros. Aprender a implementar este tipo de algoritmos por tu cuenta mejorará tus conocimientos y posibilidades mucho más que si te limitas a las funciones prefabricadas.
Y al fin y al cabo, ¿qué es la robótica sin pelearse con las fórmulas, problemas y código?
Final de línea.
Hola buenas! Alguien sabria por que en el loop solo usa el registro 0x3B?
Es decir, seria el de Xout, o sea solo esta requiriendo los datos del acelerometro en el eje x, por que en los demás no? Lo mismo hace con el
0x43 con el giroscopio.
Saludos, Fernando. Fíjate que partimos del 0x3B, pero después leemos 6 registros (0x3B -> 0x41). Con el giroscopio es lo mismo pero con 4 registros.
como eliminar al conteo de 180 graos
Una pregunta, como puedo mandar una señal dependiendo de como esten los ejes, a través de un modulo bluetooth, con la funcion if de condicion ?
Hola de nuevo
Tengo un problema mayor ahora.
sus cálculos funcionan bien en el banco de pruebas, pero si surgen aceleraciones no lineales (fuerza centrífuga …) los valores ya no son confiables.
Encontré esta función Roll = (((acos ((sin (beta) * Ay + cos (beta) * Ax) / Az)) * RAD_A_DEG) -90) / 2; También reemplaza Ax y Ay con su AngleX y AngleY. bueno en el banco de pruebas, un poco mejor en movimiento, pero todavía valores poco confiables.
¿podría resolver con los cuaterniones de Mahony / Magdwick?
Todavía no he logrado que funcionen
Muchas gracias
Sí, podrías utilizar esta IMU con un filtro de Mahony o de Magdwick. Pero ten en cuenta que son más complicados de implementar que el filtro complementario.
Me di cuenta
Intenté usar madgwick.h y mahony.h que tienen la función getROll, pero los resultados no son confiables: los valores devueltos no corresponden al movimiento de la unidad. También traje uno sketch encontrado en la red, pero con un gran drift.
Traté de aplicar los diversos consejos que se encuentran alrededor, pero no obtuve nada. Las bibliotecas adafruitAHRS, adafruit_LSM9DS1 no pueden usarlas con el nano33.
Para madgwickAHRS.h y mahonyAHRS.h no entendí cómo obtener Roll: no hay getRoll y quizás los cuaterniones deben calcularlo
Hola,
Estoy tratando de presentar los resultados del skecht en una pantalla LCD con numeros grandes. De hecho, en el serial monitor los resultados me parecen muy coherentes pero necesito que sean exportables a la LCD. Ante mi incpacidad como programador, lo he intentado con algun code de internet, pero los errores de compilacion me confunden. Podrias echarme una mamo… gracias!
Hola
Estoy intentando su trabajo con Arduino nano 33 ble y funciona bien.
Estoy tratando de hacer un interruptor giroscópico, pero no soy un programador.
Probé varios filtros para la IMU pero ninguno me dio un resultado estable como este.
Pero si inserto las tres funciones en mi scketch, la lectura del ángulo ya no es correcta: varía de +/- 6 ° en lugar de +/- 90 °
El tiempo de lectura es de alrededor de 25millis y agregué el cálculo del tiempo en lugar de 0.010,como se sugiere.
¿alguna sugerencia?
Muchas gracias
lo siento por mi (google) español
Saludos omomoto.
No sé decirte qué es lo que puede estar fallando. Básicamente, este es el código que utilizo para mis proyectos.
Deberías comprobar que el código esté bien copiado. Asegúrate también de haber definido correctamente los ratios de conversión de radianes a grados. Por último asegúrate de no haberte equivocado al multiplicar la lectura del giroscopio por la constante de tiempo (como haber escrito 0.25 en vez de 0.025).
fue un problema de inicialización de IMU
Introduje if (IMU.gyroscopeAvailable()) prima di leggere il giroscopio y funciona bien ahora
Muchas gracias
lo queria usar para un drone pero tarda demasiaso den obtener los angulos hay alguna manera de que sea mas rapido?
Puedes variar los parámetros 0.98 y 0.02 del filtro complementario (por ejemplo probar algo como 0.9 y 0.1), y también reducir el delay del final del bucle principal.
Gracias por compartir tus conocimientos.
Gracias a ti por leerme, humano.
Final de línea.
Genio, gracias
Eres un Crack!
Hola, muchas gracias por el tutorial, al iniciarme con este tipo de sensores me fue mucho de ayuda, sin embargo, he tenido problemas con éstos… He utilizado código sin ocupar librerías, más que la de Wire, como se muestra en este tutorial, y también he utilizado código usando la librería de Jeff Rowberg pero con ambos códigos he presentado el mismo problema, el cual es el siguiente: Algunas veces, el programa puede correr mucho tiempo sin problema, pero otras el monitor serial muestra solo algunos datos y el programa se para y una vez que pasa esto, batallo mucho para… Leer más »
¡Hola, Mons! Pueden estar fallando muchas cosas y es difícil de decir, pero lo más probable es que sea problema con el puerto USB. Es posible que, si envías muchas lecturas seguidas a tu ordenador, este se sature y no dé abasto a leerlas todas. Si puedes, haz la prueba con otro ordenador o un puerto USB 3.0.
Y he encontrado este hilo del foro de arduino que quizás te ayude: https://forum.arduino.cc/index.php?topic=77828.0
¡Un saludo!
Muchas gracias por su respuesta, intentaré probando lo que me comentó. Solo que como comentario adicional me gustaría mencionar que había agregado una línea de Serial.print, como guía, antes de las líneas en las que se leen los valores del acelerómetro y del giroscopio, con esto pude notar que al comentar las líneas que leen dichos valores el programa corre de manera normal, y solo cuando agrego aquello relacionado a dichas líneas empiezo a tener ese problema, incluso el programa se para aunque no haya mandado tantas lecturas, por ello pensé que era algún detalle con algún proceso de la… Leer más »
I have a problem with MPU6050 gyro sensors, I am making school project with Vehicle Accident GPS tracking. When the normal condition, eventhing is ok. Gyro is working his axis,but when over limit gyro’s x,y,z values, LCD and Serial monitor is stop their process. how can i do that?
Saludos. Sinceramente, no entiendo tu pregunta. ¿Quieres que el monitor serial deje de enviar mensajes cuándo la IMU sobrepase unos ciertos valores límite? En ese caso es tan fácil como añadir un condicional que lo compruebe.
I am trying to interface the mpu 650 module to node mcu to calibrating the values for robot i am
trying to useed the display the calibrating values (X-Y axis) please provide the code for node mcu.
thankyou.
Saludos, satya. El NodeMCU puede programarse con el IDE de Arduino, por tanto te sirve el mismo código que hay en el tutorial.
Final de línea.
I am trying to interface the mpu 650 module to node mcu to calibrating the values for robot i am
trying to useed the display the calibrating values (X-Y axis) please provide the code for node mcu.
thankyou.
excelente explicacion me ayudo mucho con el MPU6050, sera posible usar estas mismas formulas con el MPU9250? como conseguiria el angulo en z?
Saludos José. He probado este código tanto con MPU6050 como el MPU9250 y me ha funcionado bien. Básicamente, si corres este código con un MPU9250 lo estarás utilizando como si fuera una IMU de 6-DOF sin magnetómetro. Lo que no he conseguido con el MPU9250 es acceder correctamente a las lecturas del magnetómetro y obtener una lectura fiable del ángulo Z (incluso con librerías), así que con esto lo siento mucho pero no puedo ayudarte… Si quieres una IMU de 9-DOF que sí me ha dado buenos resultados te recomiendo la BNO055, que además tiene muy buena documentación. Final de… Leer más »
Hola muy buen post pero tengo una pregunta, cuando uno varia el tiempo, la medida varia mucho para un valor pequeño de tiempo, miro que tiene una medida correcta dandole un peso como tienes de 0.98 al primer termino angulo+angulogyro*t, pero cuando el valor de tiempo es grande, el resultado es muy grande ya que sube muy rapido porque el delta t vale mucho, y para este caso cuando el tiempo es grande, obtengo mejores resultados dandole mayor valor al segundo termino, deberia de hacer un promedio de todas las variables de tiempo o que? gracias por tu atención.
Saludos, Sebastian. El segundo valor se corresponde al peso que le das al acelerómetro. Como no depende del tiempo, es normal que cuándo la delta es grande, su valor sea más preciso que el del giroscopio.
En cuánto a tu pregunta, no sabría qué responderte. Quizás podrías mejorar la precisión si ajustaras los pesos en función de la delta, pero no estoy seguro.
Final de línea.
Excelente aporte, muchas gracias por compartir esta valiosa información. Tengo un problema y te agradecería mucho si puedes ayudarme. Deseo detener el movimiento de un carro impulsado por un motor dc cuando este alcance una aceleración determinada (Por ejemplo; que cuando el vehículo partiendo del reposo y mediante el programa y controlador L298N vaya incrementando su potencia, obtenga como registro en el acelerómetro un valor de 1.6g en X, se detenga o ejecute otra acción).
Intente con los bucles while, Do-While, if, etc… pero no logro hacer que funcione.
Gracias y Saludos!!!.
Saludos, Marco. La variable AcX te da el valor en bruto del eje X del acelerómetro. Sólo tienes que escribir un condicional que te mire si el valor de AcX es superior al límite que quieras, y poner la instrucción de parada dentro de éste: if(AcX > limite) motores(0,0); //condicion de parada También podrías hacerlo mediante un bucle while: mientras el valor de AcX sea superior al límite, los motores se quedan quietos. Sólo tienes que asegurarte de ir leyendo el acelerómetro y actualizando AcX cuándo estés dentro del bucle, de lo contrario entrarás en un bucle infinito. Final de… Leer más »
Excelente explicacion sencilla y clara. Que precision logras con este sensor en los grados de inclinacion?, quiero usarlo en un sensor inclinometro single axis. Saludos
Hola. He leido todo tu blog y me pregunto si al necesitar solo los valores de velocidad angular en cada instante de tiempo es necesario realizar 1) la calibracion del sensor y 2) implementar el uso del filtro complementario? Gracias
Saludos, Andres.
Si sólo quieres la velocidad angular, no necesitas ni leer el acelerómetro ni implementar el filtro complementario. Te basta con leer los valores del giroscopio y mostrarlos por pantalla.
En cuanto a lo de calibrar el sensor, no creo que sea necesario en este caso.
Final de línea.
Hola, muchas gracias por el super tutorial, muy muy completo. Quería hacerte una pregunta, porque quiero montar un objeto con arduino, y saber si voy por buen camino. Quiero montar un arduino con un gps con el que obtengo mi posición, y marcarle otra posición a una distancia de unos 500 metros y mediante una brújula digital (leyendo esto creo que el mpu se ajusta mas) saber si estoy apuntando hacia esa posición o no. He probado con una brújula HMC5883 y calculando la posición respecto al norte magnético, pero la precisión es bastante mala, y no se si con… Leer más »
Saludos, Antonio.
Lo que tu estás intentando es conocer la rotación en el eje Z. El MPU-6050 es una IMU de 6DOF que sólo puede conocer la rotación en los ejes X e Y, pues no tiene magnetómetro.
Para lo que estás intentando hacer necesitarás otra IMU, como el MPU-9250 o el BNO-055. Después tendrás que buscar otro filtro (o una librería adecuada) pues el filtro complementario tal y cómo lo explico aquí sólo sirve para IMUs de 6-DOF. Puedes probarlo con un Filtro de Madgwick.
Espero que esto responda tus dudas.
Final de línea.
GENIAL!!!! Después de una semana sin resultados al fin conseguí sacarle los datos a mi 9250 con esta fórmula, eso si, el problema es que el dato principal que necesito es el eje z y la deriva es imposible…. y no entiendo como solucionarlo con el magnetómetro, nisiquiera con librerías específicas del 9250 que no se como implementar los 9 valores para solucionar la deriva, tenés algo sobre eso? Infinitas gracias!!!
Saludos, Emiliano. Me temo que todo lo que tengo sobre IMUs es acerca del MPU6050 + Filtro Complementario.
Estimado, no veo que Angle[0] y Angle[1] esten inicializados? o por defecto Arduino les asigna simepre el valor 0 a cualquier variable que este declarada aunque no inicializada?. Muchas gracias.
Saludos, Gustavo.
Angle[] es una matriz de dos espacios que se inicializa al principio del programa (en la última línea del primer fragmento de código).
No necesitamos asignarles un valor inicial puesto que los llenamos con las lecturas de la IMU antes de leerlos.
Final de línea.
Hola, muchas gracias! Queria preguntarte porque envias la direccion 0x6B en el setup y luego envias un 0?
buenas amigo tengo un problema salen dos valores y van en asenso pero al llegar a -35.27 en x
35.26 y y de ai no se mueven los valores
Esto es porque has conectado mal los pines SDA y SCL. Deberías revisar las conexiones.
Final de línea.
Hola….me pareció interesante q usaras solo la libreria wire.h , asi podemos ven con claridad todoel funcionamiento.
Una duda q tengo es porque dices que no se puede calcular el angulo del eje z , con respecto al plano horizontal , como lo hacias con x e y. Supongo q al inclinar la board que posee el 6050 , la componente de la gravedad se descompone en los 3 ejes, y cada eje tiene un angulo con respecto al plano horizontal…..o me equivoco?
hola amigo, soy nuevo en el tema, tu post es muy completo, quisiera saber solo para el eje X, voy a realizar un trabajo de balancin de 2 helices, tengo tos , pero me va mal en la programacion.
Saludos, jose.
El valor Angle[0] te da el valor de la inclinación para el eje X.
Si sólo necesitas este eje y quieres ahorrarte cálculos puedes borrar las líneas dónde se calcula Acc[1], Gy[1] y Angle[1], puesto que no vas a necesitarlas.
Final de línea.
Después probablemente necesites implementar un controlador PID para controlar las hélices en función del ángulo de la IMU.
https://es.wikipedia.org/wiki/Controlador_PID
hola, Tr4nsduc7or
asi es estoy usando control PID en este sistema, intentare borrar esas lineas, muchas gracias.
Muchas gracias por el tutorial, Estoy desarrollando un sensor, para colocar en un automovil, en el que pueda medir la aceleracion/desaceleracion resultante en el sentido de circulacion, y las aceleraciones a 90 grados del sentido de circulacion (para detectar cuando se dobla con el vehiculo en situacion riesgosa). El problema es que no se de antemano como van a colocar ese sensor en cada vehiculo, lo mas probable es no quede ni paralelo totalmente al suelo, ni el sentido de circulacion coincida con los ejes del IMU. Pensaba hacer una calibracion en cada vehiculo, primero en forma estatica con la… Leer más »
Amigo ¿de que mundo mágico bienes ?, fue fascinante y lo mejor es que el escrito no esta “pesado ” . Me a gustado la redacción del texto. Felicidades.
Hola, quiero posicionar un giroscopio, el adxl 345, en 90 grados utilizando servos, podrian ayudarme con el codigo? saludos.
¡Hola Joaquín! Léete la documentación de la librería servo de Arduino:
https://www.arduino.cc/en/Tutorial/Knob
https://www.arduino.cc/en/Tutorial/Sweep
Muy buen tutorial! Estoy intentando conectar el sensor MPU-6050 con el Adafruit HUZZAH32 pero no consigo que cambien los valores por el monitor de Arduino IDE.
SDA es el pin 22
SCL es el pin 23
He cambiado los pines del código Wire.begin(4,5) por Wire.begin(22,23) y no me muestra nada.
¿A que podría deberse este problema?
Muchas gracias.
Saludos, Adrian.
Lo siento, no tengo tu modelo de placa y no puedo decirte exactamente dónde puede estar el problema. Asegúrate de que los pines que has establecido para el I2C sean correctos (por las imágenes que he encontrado en Google, creo que tu placa no tiene ningún pin 22 ni 23) y revisa las conexiones (que SDA y SCL no estén girados). También comprueba que la IMU tenga suficiente energía y no esté dañada.
Final de línea.
Muy buen tutorial, gracias por la explicación detallada.
tenes un calambre en el mate pero bue…buen tuto
Hola. Estoy por hacer un trabajo final que consiste en estabilizar una torreta de tiro. Obviamente a escala. La idea a futuro es llevarlo a una escala real. El tema es la precisión del filtro complementario. Necesito 2 minutos o menos de precisión en la medición del ángulo. Es posible obtenerla con el filtro complementario?
[…] positioning angles (roll and pitch) from accelerometer and gyroscope’s readings [1,2, and 3]. The simplest way to obtain trustful readings of the sway angles is to combine the readings from […]
Muy buen tutorial, me gustaría saber ¿cómo puedo imprimir los valores del acelerómetro en sistema internacional?, teniendo en cuenta que mi IMU tiene el plano XY paralelo al del suelo. Supongo que la lectura que debería tener en “Acz” tendría que corresponder a “-1G = -9.81 [m/s^2]” ¿Cuál sería la manera adecuada de encontrar la relación de la lectura con el valor de aceleración de la gravedad?
Saludos, Iván.
Simplemente deja la IMU quieta sobre la mesa y anota el valor que te marque el eje Z. Si no recuerdo mal, aplicándole el ratio de conversión debería darte -9.8m/s² aproximadamente, pero si no lo hace tendrás que multiplicarlo por una constante.
Final de línea.
Como puedo citar tu articulo? 🙂
Saludos, Jonathan.
Si quieres citarme de forma informal (para un artículo de un blog, por ejemplo) bastará con añadir un link a este tutorial.
Si necesitas citar mi artículo para algo más formal (un trabajo académico, una tesis, una carta…) la forma correcta es esta: http://normasapa.com/como-citar-referenciar-paginas-web-con-normas-apa/
Espero que esto resuelva tu duda, humano.
Final de línea.
Buena explicación, ¿como puedo hacer que me mande los valores a ciertos intervalos? por ejemplo que me mida inicialmente de 0 grados a 90 grados sin que me muestre los valores intermedios como 20 grados, 30 grados, 70 grados, etc.
me corrigo, digo que inicialmente el MPU mida 0 grados y que despues de un movimiento mande 90 grados.
simplemente has una función así if(grado>=0){ grado=90; }
¿No sería escribir un condicional que compruebe el ángulo de la IMU, y sólo lo muestre si es igual a 0 o a 90? Es una idea.
Final de línea.
Replanteo la pregunta, quiero decir que no guarde los valores, osea que por cada “x” vaya realizando las mediciones y que nomas muestre esos valores sin registrar los valores entre el intervalo.
Saludos, Sergio.
Lo siento pero, sinceramente, no entiendo tu pregunta. ¿De qué valores entre el intervalo me estás hablando? El programa sólo guarda un único valor en su memoria, que es el valor actual del ángulo, y se actualiza cada vez que se recorre el bucle (perdiendo así los valores anteriores).
Por favor, intenta ser más claro.
Final de línea.
Muchas gracias por tu información, tengo una duda podrías ayudarme con la fórmula para obtener la velocidad mediante la integración de los valores obtenidos de un acelerómetro. Muchas gracias
Saludos, Cristian. Integrando la fórmula de la aceleración en función del tiempo se obtiene la velocidad: v = a*t + c, dónde c es la constante de integración. Como quieres que para t = 0, v = vi (dónde vi es la velocidad inicial al comenzar el programa), tendrás que establecer c = vi. Por tanto, la fórmula de la velocidad será v = a*t + vi. La constante vi tendrás que introducirla a mano en el programa, pero normalmente será cero si tu sistema parte del reposo. Sin embargo, esta fórmula no te dará un resultado preciso. Con el… Leer más »
¿Y las siguientes velocidades? v(0)=a*t+vi, v(1)=a*t+v(0) … v(n)=a*t+v(n-1) Sería algo así?
Saludos, Fusibletérmico.
Pues sí, tienes toda la razón. Se me olvidó totalmente ponerlo, y sólo expliqué el cálculo para el primer instante. En los instantes posteriores la velocidad debe calcularse de la manera que has dicho. Muchas gracias por tu aportación.
Final de línea.
Agradecerte el tutorial, sin gente como vosotros, a electrónica no seria lo mismo.
Un apunte, aun que supongo que la mayoría ya lo sabréis, poniendo un delay de 1 segundo o menos en el set up, se soluciona el tema de tener que pulsar el botón de reset si tienes la imu conectada a la salida de 3,3 del arduino al encenderla.
Buenas, me encanto tu aporte la verdad me encanta ver el codigo de los demas y darme cuenta de las diferentes formas de pensar de cada quien, te queria sugerir una mejora en la hora de marcar el tiempo transcurrido como sabes no es una constante y tiene pequeñas variaciones por lo cual me tome la libertad de añadir estas lineas de codigo que te comparto, b = a; a = millis(); son dos variables de tipo long sin signo y se ocupan en la parte de delta t Angle[0] = 0.98 *(Angle[0]+Gy[0]*((a-b)/1000.0)) + 0.02*Acc[0]; Angle[1] = 0.98 *(Angle[1]+Gy[1]*((a-b)/1000.0)) +… Leer más »
Buenas noches, Ricardo.
Sí, la forma que planteas sería la forma más correcta de aplicar el filtro complementario. Es importante tener en cuenta las variaciones de tiempo. La razón por la que no añadí ningún cálculo del delta time fue porque creí que era mejor no complicar más el código.
No obstante, gracias por tu comentario y por leerme.
Final de línea.
Hola excelente el tutorial. Te hago una consulta
El eje Z es el unico que no se puede calcular siempre?? Si yo uso el sensor en posición vertical como pones vos en la imagen, se puede seguir calculando el eje x e y?
saludos
Saludos, Cristian.
El eje Z (paralelo al suelo) no se puede calcular nunca con una IMU de 6-DOF (al menos de forma precisa). Los ejes X e Y siempre vas a poder calcularlos pongas como pongas la IMU.
Si deseas calcular el eje Z, necesitarás otra IMU que lleve magnetómetro además de giroscopio y acelerómetro.
Final de línea.
Hola, estoy tratando de controlar un servo con el giro en una posición específica, pero cuando intento mantenerlo en 90 grados una plataforma (pegada al servo) esta solo se balancea de un lado para otro y no llega a ser estable, solo oscila como respuesta de “control” … cómo puedo hacer? Alguna sugerencia o código? :’v
Hola! ¿Estás manteniendo la IMU quieta?
amigo Cristopher, tengo exactamente el mismo problema, por favor escribeme, buscame en facebook como joaquin abed-nego, o mandame un whatsapp al +5218711322750, me gustaria compartir mi codigo contigo y ver si juntos podemos encontrar una solucion, o si tu ya encontraste que me ilustres. Saludos.
Existe alguna librería para poder integrar la aceleración? Necesito obtener distancia
Saludos, Manuel.
Supongo que podrías utilizar la librería oficial del MPU-6050 para Arduino (https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050) Pero, ¿no es más fácil integrarlo a mano, sabiendo la velocidad y posición inicial?
Final de línea.
En cada muestra sumas el valor de la aceleración, cada muestra debe ser multiplicada por el tiempo de muestreo. Saludos
Buen aporte, me ha servido de mucho para hacer mi proyecto!
Buen dia, la presente es para solicitar informacion de como interpretar los datos que observo de mi giroscopio, he configurado el registro del giroscopio y me arroja unos valores los cuales no se que son, me gustaria saber como pasarlos a grados, gracias por su ayuda.
Saludos, Juan.
¿Has refinado los valores del giroscopio o estás mostrando directamente los raw values?
Por otra parte, el giroscopio muestra la velocidad angular, no la rotación en grados. Si quieres pasarlos a grados tendrás que multiplicar las lecturas por el diferencial de tiempo entre cada lectura del giroscopio, y sumarlo a la lectura anterior:
angulo = angulo + giroscopio*dt;
Final de línea.
Exelente tutorial, una consulta, hay alguna manera de mostrar como dato la pendiente?
O sea, necesito medir el porcentaje de una pendiente, es posible? Como?
Gracias de antemano.
Saludos, Gaston.
Puedes hacer una regla de tres, teniendo en cuenta que 45 grados equivaldría a una pendiente del 50%.
Final de línea.
Excelente tutorial, mil gracias por la explicacion. Tengo un MPU6050 y estoy probando el codigo, sin embargo, me gustaria ir mas alla; me interesa el robot balanceador y el dron, podria indicarme algunos libros buenos para aprender robotica? Desde ya muchas gracias por la ayuda
Saludos, Daniel.
Libros de robótica sobre estos dos temas no puedo indicarte ninguno. Todo lo que he aprendido ha sido por internet o en libros técnicos sobre matemáticas avanzadas, que no están directamente relacionados con la robótica.
Final de línea.
Este código funciona con un maple mini rev arm cortex m3
Hola Tr4nsduc7or, primero felicitarte por tu explicación precisa y cargada de ironía (lo que facilita mucho leerla y entenderla). Yo tengo justamente problemas con todo el resto del IMU… me refiero al eje Z y la brújula. Quiero programar una brújula usando el MPU-9250, que tiene acelerómetro, giroscopio y magnetómetro, 9 ejes en total. Mientra el IMU se mantenga horizontal al suelo, con los ejes X e Y puedo encontrar el norte magnético, pero si el sensor se inclina, el sensor comienza a marcar cualquier cosa, como que el norte queda al sur y el oeste apuntando a la luna.… Leer más »
Saludos, Rodrigo. Gracias por leer mi tutorial, y me alegra saber que te ha gustado. Sí, de hecho tengo planteado desde hace tiempo hacer este mismo tutorial pero con el MPU-9250. Sin embargo, me he encontrado con dificultades a la hora de acceder a los registros de memoria de mi IMU, y empiezo a pensar que no esté averiada. Por esta razón no sé cuándo voy a poder publicarlo. Te sugiero que pruebes con el código de esta página: https://github.com/kriswiner/MPU-9250 Por otra parte, la lectura del magnetómetro está sujeta a muchísimas interferencias del entorno. Para filtrarla, te sugiero que busques… Leer más »
Tr4nsduc70r, tu podrian informarme cúal és tu nombre completo? Yo estou haciendo una pesquisa y precisio informar el nombro copleto del autor.
Saludos, Lucas. Lo siento, pero los autores de Robologs preferimos conservar el anonimato.
Final de línea.
Buen día, soy nueva en esto y cuando trato de grabar la secuencia en el sensor me aparece el siguiente mensaje: avrdude: stk500_getsync(): not in sync: resp=0x00, a qué se debe?
Estoy utilizando un sensor GY-521 y el arduino DUE
Saludos, Dayan.
Este error se produce porque la IDE de Arduino no puede conectarse con la placa para cargar el programa. Asegúrate de que el modelo de Arduino que le has especificado a la IDE sea un Arduino DUE (ve a Tools->Board y selecciona el modelo de Arduino correspondiente). Si el problema persiste podría ser que el cable USB o la placa Arduino estuviesen dañados.
Final de línea.
estoy trabajando desde matlab
estoy trabajando MPU6050 desde matlab tengo los 6 valores pero no se como calcular los angulos roll y pitch, me gustaria saber si solucionaste el problema.
Saludos, Miguel Angel. Seguramente este otro tutorial te sirva. Es lo mismo que hacemos en el tutorial de esta página, pero con Matlab rotando un cubo: http://robologs.net/2014/11/04/arduino-y-matlab-v-leer-una-imu-por-serial/
No contesté a Ariel Acurana porque a parte de este comentario, me escribió otro en la página del tutorial de Matlab que acabo de pasarte, y preferí responder todas sus dudas ahí. Puede que la respuesta que di a su comentario también te sirva de ayuda (https://robologs.net/2014/11/04/arduino-y-matlab-v-leer-una-imu-por-serial/#comment-2519).
Esto es todo. Espero que te ayude.
Final de línea.