Estoy experimentando con varios sensores de acelerómetro / giroscopio para diferentes propósitos, desde robótica, equilibrio de drones, control de vibraciones, oscilaciones de edificios, hasta sismicidad.
En este caso estamos utilizando el MPU-6050 GY-521 acelerómetro y giroscopio de 6 ejes
Algunas de sus características son la salida digital I2C de datos MotionFusion de 6 ó 9 ejes en matriz de rotación, cuaternión, ángulo de Euler o formato de datos sin formato. Esto puede ser muy conveniente dependiendo del uso y del modelo algebraico de los datos que se están procesando. Por ejemplo, algún software de drones pueden preferir la representación de matriz o cuaternión para alimentar su motor de coordenadas interno. Voltaje de entrada: 5V. Sensor de velocidad angular triaxial (giroscopio) con una sensibilidad de hasta 131 LSBs / dps y un rango completo de ± 250, ± 500, ± 1000 y ± 2000dps. Acelerómetro triaxial con un rango programable de escala completa de ± 2g, ± 4g, ± 8g y ± 16g. El motor Digital Motion Processing ™ (DMP ™) procesa operaciones complejas de MotionFusion, temporización y sincronización de sensores y detección de gestos.
Hay varias implementaciones de módulos de sensores con diferentes características y advertencias. Mira aquí.
Conecte su tarjeta de sensores con Arduino UNO como se muestra.
Esto es realmente una conexión I2C. Esto supone que su placa tiene hardware I2C.
Para la conexión de software I2C vea otros ejemplos.
Cargue el siguiente código al su Arduino IDE:
// MPU-6050 Short Example Sketch // By Arduino User JohnChi // August 17, 2014 // Public Domain #include<Wire.h> const int MPU_addr=0x68; // I2C address of the MPU-6050 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; void setup(){ Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); Serial.begin(9600); Serial.println("Starting MPU6050 Enrique Latorres"); } void loop(){ Wire.beginTransmission(MPU_addr); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) Serial.print("AcX = "); Serial.print(AcX); Serial.print(" | AcY = "); Serial.print(AcY); Serial.print(" | AcZ = "); Serial.print(AcZ); Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //equation for temperature in degrees C from datasheet Serial.print(" | GyX = "); Serial.print(GyX); Serial.print(" | GyY = "); Serial.print(GyY); Serial.print(" | GyZ = "); Serial.println(GyZ); delay(333); }
Compile y cárguelo a la tarjeta Arduino. Abra el Serial Monitor para ver los resultados.
Starting MPU6050 Enrique Latorres AcX = 13344 | AcY = -1156 | AcZ = 9028 | Tmp = 20.06 | GyX = -64 | GyY = 20 | GyZ = -9 AcX = 13336 | AcY = -1116 | AcZ = 9284 | Tmp = 20.06 | GyX = -65 | GyY = 43 | GyZ = -44 AcX = 13476 | AcY = -1048 | AcZ = 9144 | Tmp = 19.97 | GyX = -93 | GyY = 43 | GyZ = -32 AcX = 13276 | AcY = -1164 | AcZ = 9160 | Tmp = 20.11 | GyX = -77 | GyY = 31 | GyZ = -36 AcX = 13268 | AcY = -1136 | AcZ = 9208 | Tmp = 20.06 | GyX = -76 | GyY = 51 | GyZ = -65 AcX = 13408 | AcY = -1016 | AcZ = 9212 | Tmp = 20.06 | GyX = -85 | GyY = 34 | GyZ = -51 AcX = 13484 | AcY = -1172 | AcZ = 9136 | Tmp = 20.11 | GyX = -18 | GyY = 30 | GyZ = -26 AcX = 13420 | AcY = -1144 | AcZ = 9124 | Tmp = 20.11 | GyX = -79 | GyY = 74 | GyZ = -37
Después de una simple sacudida vemos que está trabajando en el rango de 2g, y 32767 es el valor superior de la escala.
Para los seis ejes el rango de trabajo es -32768 a +32767. Entonces 16384 es 1g. Así que lo que AcX, AcY y AcZ están leyendo es la proyección ortogonal de la gravedad de la tierra a cada uno de los ejes medida en g. Si se coloca el sensor en un soporte horizontal, se obtendrá algo cerca de 16384 en el eje Z, más/menos algún ruido.
También se puede calcular algo así como √((13344 ÷ 16384) ² + (- 1156 ÷ 16384) ² + (9028 ÷ 16384) ² )= 0.9858707387 ~ = 1,0 g = 9.80665 m/s2 Nótese que la gravedad puede variar de acuerdo con diferentes factores y lugares en la Tierra. Además, este equipo lee datos crudos sin calibración.
Otro ejemplo usando la biblioteca de Rowberg.
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class // mofdified from example by Jeff Rowberg #include "I2Cdev.h" #include "MPU6050.h" #include "Wire.h" MPU6050 accelgyro(0X68); //default address I2C is 0x68 //declare variables int16_t ax, ay, az; int16_t gx, gy, gz; int16_t temp; float temp_MPU; #define LED_PIN 13 bool blinkState = false; void setup() { Wire.begin(); Serial.begin(38400); Serial.println("Initializing I2C devices..."); accelgyro.initialize(); Serial.println("Testing device connections..."); Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); // change accel/gyro offset values to zero accelgyro.setXGyroOffset(0); accelgyro.setYGyroOffset(0); accelgyro.setZGyroOffset(0); // configure Arduino LED for pinMode(LED_PIN, OUTPUT); Serial.println("MPU-6050 example - Enrique Latorres"); Serial.print("ax"); Serial.print("\t"); Serial.print("ay"); Serial.print("\t"); Serial.print("az"); Serial.print("\t"); Serial.print("temp"); Serial.print("\t"); Serial.print("gx"); Serial.print("\t"); Serial.print("gy"); Serial.print("\t"); Serial.println("gz"); } void loop() { // read raw accel/gyro measurements from device //accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); accelgyro.getAcceleration(&ax, &ay, &az); accelgyro.getRotation(&gx, &gy, &gz); temp=accelgyro.getTemperature(); // display tab-separated accel/gyro x/y/z values Serial.print(ax); Serial.print("\t"); Serial.print(ay); Serial.print("\t"); Serial.print(az); Serial.print("\t"); //convert integer to temperature in centigrades Celsius //https://www.i2cdevlib.com/forums/topic/53-mpu-6050-temperature-compensation/ temp_MPU=float(temp)/340+36.53; Serial.print(temp_MPU); Serial.print("\t"); Serial.print(gx); Serial.print("\t"); Serial.print(gy); Serial.print("\t"); Serial.println(gz); // blink LED to indicate activity blinkState = !blinkState; delay(300); //just slow down a little bit digitalWrite(LED_PIN, blinkState); }
Compilando y cargando el programa obtenemos el siguiente resultado en el Serial Monitor.
MPU-6050 example - Enrique Latorres ax ay az temp gx gy gz 12016 -2038 10648 20.95 61 -21 46 12030 -1838 10594 20.96 -102 -23 -115 12046 -1712 10550 20.95 -102 23 -97 11990 -1978 10640 20.93 32 62 85 12040 -1848 10616 20.97 -114 15 -105 11972 -1852 10642 20.94 -27 11 -5 11942 -1810 10688 20.94 -86 75 -13 11956 -5784 12308 20.96 -3029 822 -3583
Wow, gracias por toda la información que plasmaste en el blogJulio
Hola, tengo que realizar un proyecto en donde utilizo de 4 a 5 módulos GY-521. Tengo dudas de si puedo conectarlos en serie (agrupar los datos de salida) o cada módulo tiene que tener conexión independiente.
la alimentacion oprque va a 5v si el sensor dices que va a 3v? Gracias!
Está equivocado. Creo que copié las especificaciones del de 3v pero este es de 5V. Ya lo corrijo.
Los módulos se conectan por i2c. Se les tiene que programar diferentes direcciones. Entonces se ponen en paralelo.
Hola, dónde están declarados los pines de entrada? necesito cambiarlos porque estoy usando un sensor de presión SFE_BMP180 en conjunto y ambos usan los análogos 4 y 5 como entrada, no encuentro la parte del código donde los especifica. Gracias
Hola Mackarena. Supongo que haces referencia al uso de los pines de e/s 4 y 5 del esquema al final. Lo que sucede es que el ejemplo (con el programa) lo hice solamente con los pines dedicados para I²C. El que aparece arriba. Y para ver un ejemplo con los pines definidos por software dejo allí un link que lleva a un artículo de un tercero que hace ese ejemplo.