Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Módulos Arduino CIES

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 21

NOTAS

Módulos_Arduino_CIES

Ing. Mauricio Hernández


Contenido

Ir al índice

Índice general

Índice de figuras ii
Índice de tablas ii
1. Introducción 1
2. Módulos disponibles 1
3. Uso del sensor MPU6050 1
3.1. Calibración ········································································································ 4
3.2. Valores de inclinación del sensor ·········································································· 10
3.3. Valores de rotación con el giroscopio ···································································· 11
3.3.1. Código en Arduino ······················································································ 11

4. Otros módulos 15
4.1. Módulos de relés ······························································································· 15

i
Contenido

Índice de figuras
Fig 1: Conexión del sensor MPU a la placa controladora ··································································· 3
Figura 2: Vector de aceleración de gravedad y cálculo de la inclinación del sensor, los ejes x, y y z son fijos
respecto al propio sensor. ········································································································· 10
Figura 3: Un mismo modo de rotación de un objeto entorno a su eje z, con dos inclinaciones diferentes del
mismo respecto a tierra. ··········································································································· 11
Figura 4: Salida del monitor al rotar el sensor MPU6050 en su eje X unos 90 grados ···························· 14
Figura 5: Salida del monitor al rotar el sensor MPU6050 en su eje Y unos 90 grados ···························· 15
Figura 6: Módulo de 8 relés electromecánicos del Instituto FIIIDT ······················································ 16
Figura 7: Modulo de 4 relés de estado sólido, se disparan con nivel bajo en la entrada ·························· 16

Índice de tablas
Tabla 2.1: Módulos sensores disponibles para Arduino o similares – Octubre 2024 ································· 1
Tabla 3.1: Rangos por defecto del MPU6050 ·················································································· 2

ii
3. Uso del sensor MPU6050

1. Introducción
En el presente documento se pretende exponer información referente a módulos compatibles
con Arduino disponibles en CIES – FIIIDT para investigación y desarrollo de proyectos, tanto
internos como externos. Esto puede funcionar como un método de recopilación de datos sobre los
dispositivos disponibles en el instituto.

2. Módulos disponibles
En el laboratorio 235 se tiene un set de componentes y módulos para Arduino de uso general,
los cuales se listan en la tabla siguiente:

Tabla 2.1: Módulos sensores disponibles para Arduino o similares – Octubre 2024

Concepto Código/ID Cantidad Notas

Brújula digital o magnetómetro


1 soldado en placa HMC5883L 2 Interfaz I2C

Sensor de humedad y
temperatura RH/T soldado en
2 placa HTU21/SHT21 Interfaz I2C

Unidad de medición inercial,


3 acelerómetro-giroscopio ITG/MPU (MPU6050) Interfaz I2C

Para el sensor MPU6050, se empezará probando la librería MPU6050 v1.4.1 (de Electronic
Cats), descargable desde el Arduino IDE. Esta librería está basada en la librería jrowberg/i2cdevlib
(i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub ).

Continúa...

3. Uso del sensor MPU6050


Los rangos por defecto del sensor se muestran en la tabla siguiente:

Ir al índice 1
Tema 3: Uso del sensor MPU6050

Tabla 3.1: Rangos por defecto del MPU6050

Variable Valor mínimo Valor central Valor máximo

Lectura del MPU -32768 0 +32767

Aceleración lineal -2g m/s2 0 m/s2 2g m/s2

Velocidad angular -250° /s 0° /s 250° /s

El rango de aceleración por defecto está comprendido entre -2g y 2g, siendo g la gravedad de
la tierra cerca del nivel del mar. El MPU permite trabajar hasta con 16g m/s2 para el acelerómetro y
2000 grados /s para el giroscopio por cada eje.

A continuación se muestra un ejemplo de código en el cual se usa la librería mencionada para


manejar el sensor MPU1:

// 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 pin AD0. Si no se especifica, 0x68 estará implícito (voltaje bajo por
pull down interno)
MPU6050 sensor; //objeto de clase

// MPU6050 sensor(0x69); // el constructor puede recibir la direccción I2C 0x69 o 0x68


explicitamente

//las mediciones obtenidas del sensor directamente son: aceleración lineal (por eje) y
velocidad angular (por eje)

// 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(9600); //Iniciando puerto serial, altas velocidades pueden impedir una
transmisión correcta
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 cada 100 ms
sensor.getAcceleration(&ax, &ay, &az);
sensor.getRotation(&gx, &gy, &gz);

1 Referencias: Tutorial MPU6050, Acelerómetro y Giroscopio, Using multiple identical I2C devices – Xtronical,
https://howtomechatronics.com/tutorials/arduino/arduino-and-mpu6050-accelerometer-and-gyroscope-tutorial/, Calibrating & Optimising the MPU6050
– chillibasket

2 Ir al índice
3. Uso del sensor MPU6050
//Mostrar las lecturas separadas
Serial.print("\n a[x y z] \n");
Serial.print(ax); Serial.print(" ");
Serial.print(ay); Serial.print(" ");
Serial.print(az); Serial.print("\n \n ");

Serial.print("g[x y z] \n");
Serial.print(gx); Serial.print(" ");
Serial.print(gy); Serial.print(" ");
Serial.println(gz);

delay(100);
}

El código anterior fue grabado en la placa tipo Arduino con el sensor conectado y ha
funcionado sin errores, sin embargo los valores de medida mostrados hacen referencia a un offset
que no ha sido ajustado. Para resolver esto se requiere calibrar el sensor MPU.

Para obtener la lectura real de aceleración (o velocidad angular) se debe transformar el valor
devuelto por getAcceleration o getRotation (por defecto un entero entre -32768 y 32767), en base
al código previo:

accx=ax*(2*9.8) / (32767); // valor en m/s2, regla de 3

El valor 2*9.8 (2g) es la escala por defecto (tabla 3.1), este valor puede ser cambiado
sobreescribiendo uno de los registros de configuración del MPU vía I2C (pueden usarse las
funciones de la clase Wire, que son funciones de nivel bajo). Los valores posibles son 2g, 4g, 8g, y
16g. Ver hoja de datos para más detalles de este y otros registros de configuración.

Fig 1: Conexión del sensor MPU a la placa controladora

Ir al índice 3
Tema 3: Uso del sensor MPU6050

3.1. Calibración
Para realizar una calibración se usan algoritmos como se muestra en esta sección. La
calibración se realiza en parte debido a que cada módulo es único en lo que se refiere al error del
cero que viene de fábrica. El error de desplazamiento del cero (offset) se refiere a que el sensor
mide pequeñas magnitudes distintas de cero incluso si está completamente nivelado, cuando en
teoría debería medir valores cero (velocidad angular, ángulos y aceleración angular por ejes).

Existen funciones de la clase MPU6050 tanto para establecer como para obtener el offset de
aceleración por cada eje y velocidad angular del sensor. El código usa estas funciones para ajustar
el offset, como se verá a continuación. Las funciones de offset de aceleración son:

ax_o=sensor.getXAccelOffset(); // lee el offset actual para la aceleración en X


sensor.setXAccelOffset(ax_o); // establece ax_o como nuevo offset para aceleración en X

Sustituyendo X por Y o Z en las funciones previas se trabaja con los ejes restantes.

Para la velocidad angular se tiene:

gx_o=sensor.getXGyroOffset(); // retorna velocidad de rotación en el eje x del sensor


// el valor devuelto se debe escalar
sensor.setXGyroOffset(gx_o);

A continuación se muestra un código de calibración, la posición actual del sensor será la


nueva posición de referencia para mediciones futuras. La calibración se realiza antes de usar el
sensor.

// Codigo de calibracion del MPU6050


// I2Cdev and MPU6050 deben estar instaladas como librerías
// La libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

// MPU6050 sensor(0x69); // el constructor puede recibir la direccción I2C 0x69 o 0x68


explicitamente

//las mediciones obtenidas del sensor directamente son: aceleración lineal (por eje) y
velocidad angular (por eje)

MPU6050 sensor; // crea el objeto sensor, si conecta 2 sensores MPU, estos deberán tener
direcciones I2C diferentes

// 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;

4 Ir al índice
3.1. Calibración

void setup() {
Serial.begin(9600); //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 calibracion");
// Espera un caracter para empezar a calibrar
while (true){if (Serial.available()) break;}
Serial.println("Calibrando, no mover IMU");

} // fin de funcion setup

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);

Ir al índice 5
Tema 3: Uso del sensor MPU6050

//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++;
}

Si se incluye el código de medición junto a la calibración se tiene el código siguiente:

// Aca se incluye calibración y lectura, la calibración termina bajo las condiciones


dadas, luego inicia el codigo principal

// Librerias I2C para controlar el mpu6050, se leen valores y se envian a la pc


// 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 pin AD0. Si no se especifica, 0x68 estará implicito (voltaje bajo por
pull down interno)
// MPU6050 sensor; //objeto de clase

MPU6050 sensor(0x68); // el constructor puede recibir la direccción I2C 0x69 o 0x68


explicitamente

// Las mediciones obtenidas del sensor directamente son: aceleración lineal (por eje) y
velocidad angular (por eje)
// Variables de mediciones, filtros y offset son globales
// 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;
int calibrado=0;

6 Ir al índice
3.1. Calibración
//Valor de los offsets
int ax_o,ay_o,az_o;
int gx_o,gy_o,gz_o;

int calibrar(void); //

void setup() {
Serial.begin(9600); // Iniciando puerto serial, con altas velocidades pueden fallar
la comunicacion
Wire.begin(); // Iniciando I2C
sensor.initialize(); // Iniciando el sensor MPU6050 via I2C

if (sensor.testConnection()) {
Serial.println("Sensor iniciado correctamente");
// Mostrar el offset inicial
}
else Serial.println("Error al iniciar el sensor");

// Leer, guardar e imprimir los offset:


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 iniciales:");
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");

calibrado=calibrar(); // solo debe ejecutarse una vez

} // fin de funcion setup

void loop() {

Serial.println("Fin de programa \n\n");

delay(1000); // provisional
}

int calibrar(void) {

Serial.println("Presione una tecla para iniciar calibracion del sensor MPU6050 \n \n");
while (true){if (Serial.available()) break;}
Serial.println("Calibrando, no mover sensor de su posición de referencia, presione una
tecla para terminar \n\n");

while(true){
// 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;

Ir al índice 7
Tema 3: Uso del sensor MPU6050
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; // reinicia para el siguiente conteo hasta 100


calibrado+=1;
} // fin de if
counter++;
if (Serial.available() && calibrado > 6) break; // termina calibracion, sale de while
} // fin de while true

Serial.println("Fin de calibracion \n\n"); //


return calibrado; // retorna una copia
} // fin de funcion calibrar

La función Serial.available() obtiene y retorna la cantidad de bytes disponibles para leer en el

8 Ir al índice
3.1. Calibración

puerto serial, pero no los lee en sí. Esto se refiere a los datos que ya han llegado al bufer
previamente. Si el valor devuelto es cero, no hay datos para leer en ese instante. Después de esta
función se suele ejecutar dato=Serial.read(), que retorna el primer byte disponible del bufer como
un entero, o un -1 si no hay datos para leer. A medida que se leen bytes, el bufer se va liberando,
por ende el valor devuelto por Serial.available() será cada vez menor hasta ser igual a cero.

Es posible cambiar el tamaño del buffer, es decir la cantidad de datos a leer por cada petición
del maestro I2C, pero si el tamaño se hace muy grande, el código tardará más en ejecutar cada
ciclo loop.

Las lecturas en el bucle principal son filtradas usando desplazamiento de bits para corregir las
mediciones. La expresión f_ax>>5 desplaza 5 bits de f_ax a la derecha rellenando con ceros a la
izquierda. Desplazar cinco posiciones a la derecha los bits de una cantidad equivale a dividirla
entre 32 (25) en decimal. Por tanto, f_ax-(f_ax>>5) equivale a 0,96f_ax. Similarmente, desplazar 3
bits equivale a dividir en 23 (8).

Si los valores medidos de ax no cambian de signo, el valor f_ax y p_ax se irán alejando del
cero, esto se aplica a todas las aceleraciones y velocidades angulares. Los valores de aceleración
y velocidad deben ser lo más cercanos posible a cero, dejando el sensor inmóvil y en posición
horizontal durante la calibración. Por cada 100 iteraciones, el offset de aceleración z se ajusta a
1g, y en el resto de ejes a 0g, en tanto que los offset de velocidad angular se ajustan a 0 grados /
seg.

El offset es ajustado cada 100 iteraciones, en función del valor o signo de p. Cuando se ajusta
el offset se obtiene un salto en las siguientes lecturas de aceleraciones ax, ay, ... (o velocidades
según sea el caso), haciendo que p tenga una nueva tasa de cambio para acercarse más
rápidamente al valor de referencia; cuando p logra alcanzar o cruzar el valor de referencia (en
if(p>referencia)...else...), se corrige nuevamente el offset correspondiente, y así sucesivamente por
cada 100 iteraciones. Cuando los valores de p convergen a los valores deseados de offset, se
procede a desconectar o reiniciar nuestro sistema.

Al usar el codigo anterior para calibrar se encontraron algunos inconvenientes, el tiempo para
la convergencia es considerable. Es necesario instalar el sensor en un soporte fijo para no tener
fluctuaciones en las medidas. Una vista parcial de la salida obtenida se muestra abajo. Los valores
de p iniciales están muy lejos del cero, y debido a ello su aproximación al valor deseado tarda un
tiempo considerable.

Promedio valores offset ( ax_o ay_o az_o gx_o gy_o gz_o ): -944 -1507 1954 12 32 120

Promedio valores p: 337 7592 15650 -6 -8 2

Promedio valores offset ( ax_o ay_o az_o gx_o gy_o gz_o ): -945 -1508 1955 13 33 119

Promedio valores p: 308 7603 15642 1 1 -2

Promedio valores offset ( ax_o ay_o az_o gx_o gy_o gz_o ): -946 -1509 1956 12 32 120

Promedio valores p: 296 7573 15661 -7 -4 5

Ir al índice 9
Tema 3: Uso del sensor MPU6050
Promedio valores offset ( ax_o ay_o az_o gx_o gy_o gz_o ): -947 -1510 1957 13 33 119

Promedio valores p: 284 7568 15673 5 -1 -4

Promedio valores offset ( ax_o ay_o az_o gx_o gy_o gz_o ): -948 -1511 1958 12 34 120

Otro código de calibración se puede encontrar en los códigos de ejemplo de Arduino IDE, que
se denomina IMU_ZERO.ino. Dicho ejemplo viene incluido con la librería descargada (MPU6050,
descrita en la sección 2).

3.2. Valores de inclinación del sensor


En esta sección se muestra un código para calcular los ángulos que forma el vector de
aceleración de gravedad (referencia) respecto a los planos de los ejes del sensor 2, esto permite
determinar la inclinación del mismo, obviamente se debe determinar la inclinación respecto a una
referencia conocida como lo es la aceleración de gravedad.

El ángulo x es el ángulo que forma el vector de gravedad g con el plano yz del sensor, el
ángulo Y es el ángulo que forma el vector g con el plano xz. Por triángulos rectángulos, se
expresan estos ángulos en función de arcotangentes. Los catetos respectivos son los que se
forman al rotar el sensor, como se ve en la figura 2.

ap2=Accx2 + Accz2
ap tan(y)=tan(roll)=|Accy| / |ap|
tan(y)=|Accy| / sqrt(Accx2 + Accz2)

Figura 2: Vector de aceleración de gravedad y cálculo de la inclinación del sensor, los ejes x, y y
z son fijos respecto al propio sensor.

El vector de gravedad g, que se muestra de color blanco en la figura 2, forma un ángulo y


(roll) respecto al plano xz del sensor, la proyección del vector g en el plano xz es el vector a p, que
se muestra de color verde. Hay que recordar que los planos que forman los ejes rotan con el
sensor, mientras el vector de gravedad g queda fijo.

De forma similar al ángulo y, se determina x, que es el ángulo de proyección de g sobre el
plano yz del sensor como:

tan(x)=Accx / sqrt(Accy2 + Accz2)

2 Referencia: https://youtu.be/7VW_XVbtu9k?si=fuFyVvICLSS6YjMB

10 Ir al índice
3.3. Valores de rotación con el giroscopio

Siendo sqrt la función para sacar la raiz cuadrada. En nuestro código se usa directamente la
función arcotangente atan():

// ...
sensor.getAcceleration(&ax, &ay, &az); // valores sin procesar (escalar)
//Calcular los angulos de inclinacion:
float accel_ang_x=atan(ax/sqrt(pow(ay,2) + pow(az,2)))*(180.0/3.14); // radianes
float accel_ang_y=atan(ay/sqrt(pow(ax,2) + pow(az,2)))*(180.0/3.14);
// ...

Para calcular los ángulos de inclinación no hace falta escalar los valores leídos con
getAcceleration(…), ya que la tangente es adimensional.

3.3. Valores de rotación con el giroscopio


El giroscopio permite obtener el ángulo instantáneo de rotación de cada eje por separado.
Visto de otro modo, se trata del ángulo de giro de un plano imaginario cualquiera que contiene al
eje en cuestión (x, y o z) y a un punto del sensor.

No se debe confundir los ángulos de rotación de ejes, con los ángulos de inclinación del
sensor, aunque pueden coincidir en valor como casos particulares.

Hay que tener presente que un objeto puede rotar respecto a un eje del mismo, con
inclinaciones diferentes, esto se visualiza mejor en la figura 3. A esto se refiere la diferencia entre
inclinación del sensor y la rotación entorno a un eje.

Eje
perpendicular al
suelo z

Figura 3: Un mismo modo de rotación de un objeto entorno a su eje z, con dos inclinaciones
diferentes del mismo respecto a tierra.

3.3.1. Código en Arduino


Es posible medir el ángulo de rotación respecto a cada eje del sensor, usando la velocidad
angular calculada por el giroscopio y el tiempo aproximado transcurrido entre dos ejecuciones del
codigo principal. Luego se usa la siguiente fórmula:

Ir al índice 11
Tema 3: Uso del sensor MPU6050

actual = previo + t*w

Donde w es la velocidad medida por el giroscopio en rad/s. Se puede asumir un ángulo inicial
para  antes de entrar en el bucle. Esta fórmula se aplica por cada eje del sensor (x, y, z), por lo
tanto se obtienen 3 ángulos de rotación. Según el sentido de giro, w será positivo o negativo.

//
// 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 giroscopio


int gx, gy, gz; // valores en cero

long int tiempo_prev, dt;


float ang_x, ang_y;
float ang_x_prev, ang_y_prev; // valores previos

void setup() {
Serial.begin(9600); //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(); // primer instante en miliseg, angulos en cero
}

void loop() {
// Leer las velocidades
sensor.getRotation(&gx, &gy, &gz); // sin procesar

dt = millis()-tiempo_prev; // miliseg
tiempo_prev=millis(); // guardar el instante actual como previo

// Angulo actual por eje:


ang_x = (gx/131.0)*dt/1000.0 + ang_x_prev; //
ang_y = (gy/131.0)*dt/1000.0 + ang_y_prev; //
// g/131 es el escalado a grado/s según escala por defecto

ang_x_prev=ang_x; // guardar angulo actual como previo


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(50); // este delay influye en el dt


// usar el plotter de arduino IDE para graficar valores impresos
}

12 Ir al índice
3.3. Valores de rotación con el giroscopio

Con este código por lo general se produce un error acumulativo en la medición llamado drift,
el cual se debe eliminar o reducir agregando un filtro complementario en el código. Este error se
debe principalmente al ruido en la medición de la velocidad.

El ángulo de rotación se puede expresar en función del ángulo de proyección del vector g
sobre el plano xz, a su vez depende del ángulo que forma el vector g con el plano yz. El ángulo se
puede complementar como en el siguiente código.

// Obteniendo angulos de rotacion de ejes usando filtro complementario de ángulos, se usa


el ángulo del giroscopio y del acelerómetro:
// 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; // valores previos
float ang_x_prev, ang_y_prev;

void setup() {
Serial.begin(9600); //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 en segundos


tiempo_prev=millis(); // guardar el instante actual como previo

//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


ang_x = 0.90*(ang_x_prev+(gx/131.0)*dt) + 0.1*accel_ang_x; // Las constantes numericas
suman 1
ang_y = 0.90*(ang_y_prev+(gy/131.0)*dt) + 0.1*accel_ang_y;

// ( g/131 es el escalado a grado/s según escala por defecto )

ang_x_prev=ang_x; //angulo previo = angulo de rotacion actual


ang_y_prev=ang_y;

//Mostrar los angulos separadas por un [tab]

Ir al índice 13
Tema 3: Uso del sensor MPU6050

Serial.print(" Rotacion en X: ");


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

delay(50);
}

Las variaciones rápidas del ángulo medido del acelerómetro son filtradas por el ángulo del
giroscopio en el eje respectivo. En el código el ángulo del acelerometro contribuye solo con un
10% de su valor total. Estas constantes numéricas se pueden cambiar para fines de prueba.

Usando el código anterior, al rotar el sensor un ángulo aproximado de 90 grados positivos en


el eje x se muestran los valores parciales siguientes:

Figura 4: Salida del monitor al rotar el sensor MPU6050 en su eje X unos 90 grados

Hay que tomar en cuenta que el sensor fue colocado sobre una mesa para esta prueba, aún
así puede estar inclinado, ya que la mesa y el edificio donde se ubica pueden tener angulos de
inclinación pequeños que contribuyen con el desnivel del sensor.

Una rotación pura en el eje Y de unos 90 grados produjo la salida siguiente en la consola del
IDE Arduino:

14 Ir al índice
4.1. Módulos de relés

Figura 5: Salida del monitor al rotar el sensor MPU6050 en su eje Y unos 90 grados

Los resultados previos indican que el sensor puede funcionar para determinar su inclinación
aproximada respecto al suelo siempre que se haya calibrado y fijado adecuadamente en un
soporte.

Con estos resultados se puede decir que es posible usar el MPU6050 para realizar sistemas
de control en drones o plataformas que requieran nivelación o control de inclinación. Cabe
destacar que este sensor no es de los más precisos de su tipo, en caso de requerir mediciones de
mayor precisión y menos ruido se pueden implementar otros modelos de sensores disponibles
comercialmente,

4. Otros módulos

4.1. Módulos de relés


Se tiene disponible 2 módulos de 8 relés electromecánicos para control de cargas, estos son
adecuados para usar con microcontroladores como Arduino, internamente incluye desacople óptico
y protección. Este puede funcionar con 5V DC. Cada entrada se encuentra a un voltaje lógico alto
cuando no está conectada. Cuando se alimenta Vcc con 5 V el voltaje en cada entrada es de unos
3.3 V respecto a neutro. Al colocar una entrada a tierra se activa el relé correspondiente.

Estos relés manejan hasta 10 A, a voltajes de 30VDC, o de 120V/220 VAC.

Ir al índice 15
Tema 4: Otros módulos

Figura 6: Módulo de 8 relés electromecánicos del Instituto FIIIDT

Otros módulos disponibles son 2 módulos de 4 relés de estado sólido cada uno, el cual se
muestra en la figura 7. El modelo del relé es el G3MB-202P, este tipo de relé maneja corriente
alterna. La tensión de operación es de 5 V para el control. Cada relé tiene una capacidad de 2A,
hasta 240VAC. La corriente de trabajo es de unos 12mA por relé.

Figura 7: Modulo de 4 relés de estado sólido, se disparan con nivel bajo en la entrada

16 Ir al índice
4.1. Módulos de relés

Ir al índice 17

También podría gustarte