Construye una Brújula Digital en Tiempo Real con Arduino y Processing
En este proyecto de Arduino veremos cómo podemos hacer esta brújula de aspecto genial usando un Arduino, un magnetómetro MEMS y el IDE de Processing. Aquí tienes un vídeo de demostración de la brújula: Todo lo que necesitamos para este proyecto es un magnetómetro MEMS, para medir el campo magnético terrestre, una placa Arduino y algunos cables jumper. Como ejemplo usaré el HMC5883L, un magnetómetro de 3 ejes integrado en la placa breakout GY-80. Primero necesitamos obtener los datos del sensor usando la placa Arduino a través del protocolo I2C. Luego, usando los valores del eje X y eje Y del sensor, calcularemos el rumbo y enviaremos su valor al IDE de Processing a través del puerto serie. El siguiente código hará ese trabajo: Si necesitas más detalles sobre cómo funciona el magnetómetro MEMS y cómo obtener datos de él, puedes consultar mi tutorial de sensores MEMS. Aquí primero necesitamos recibir los valores de rumbo que vienen del puerto serie. Para más detalles sobre cómo se hace esto, puedes consultar mi tutorial de Arduino y Processing. La brújula es en realidad una imagen, o más precisamente, está compuesta por múltiples imágenes transparentes cargadas en el IDE de Processing. Las imágenes deben estar ubicadas en el directorio de trabajo del sketch. Después de definir los objetos de imagen en la sección draw() usando la función image() cargamos la imagen de fondo (que es opcional, puedes usar solo un color simple para el fondo). Luego se carga la imagen de la Brújula, que usando la función rotateZ() se rota con los valores del rumbo. Encima de ellas se carga la imagen de la Flecha de la Brújula. Aquí está el código del IDE de Processing: Aquí puedes descargar los archivos del proyecto, las imágenes y los códigos fuente:Visión General
Cómo Funciona la Brújula
Parte Arduino
/* Brújula Arduino
*
* por Dejan Nedelkovski,
* www.HowToMechatronics.com
* */
#include <Wire.h> //Librería I2C Arduino
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float heading, headingDegrees, headingFiltered, declination;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //Dirección I2C 7bit de HMC5883
void setup(){
// Inicializar comunicaciones Serial e I2C
Serial.begin(115200);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Seleccionar registro de modo
Wire.write(0x00); // Modo de medición continua
Wire.endTransmission();
}
void loop(){
//---- Eje X
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mX1 = Wire.read();
}
//---- Eje Y
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mY1 = Wire.read();
}
//---- Eje Z
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1) {
mZ1 = Wire.read();
}
//---- Eje X
mX1=mX1<<8;
mX_out =mX0+mX1; // Datos en bruto
// De la hoja de datos: 0.92 mG/dígito
Xm = mX_out*0.00092; // Unidad Gauss
//* El campo magnético terrestre varía de 0.25 a 0.65 Gauss, así que estos son los valores que necesitamos obtener aproximadamente.
//---- Eje Y
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;
//---- Eje Z
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;
// ==============================
//Calculando Rumbo
heading = atan2(Ym, Xm);
// Corrigiendo el rumbo con el ángulo de declinación según tu ubicación
// Puedes encontrar tu ángulo de declinación en: https://www.ngdc.noaa.gov/geomag-web/
// En mi ubicación son 4.2 grados => 0.073 rad
declination = 0.073;
heading += declination;
// Corrigiendo cuando los signos están invertidos
if(heading <0) heading += 2*PI;
// Corrigiendo debido a la adición del ángulo de declinación
if(heading > 2*PI)heading -= 2*PI;
headingDegrees = heading * 180/PI; // El rumbo en unidades Grados
// Suavizando el ángulo de salida / Filtro pasa bajos
headingFiltered = headingFiltered*0.85 + headingDegrees*0.15;
// Enviando el valor del rumbo a través del Puerto Serie al IDE Processing
Serial.println(headingFiltered);
delay(50);
}Lenguaje: Arduino (arduino)Parte IDE Processing
/* Brújula Arduino
*
* por Dejan Nedelkovski,
* www.HowToMechatronics.com
* */
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
PImage imgCompass;
PImage imgCompassArrow;
PImage background;
String data="";
float heading;
void setup() {
size (1920, 1080, P3D);
smooth();
imgCompass = loadImage("Compass.png");
imgCompassArrow = loadImage("CompassArrow.png");
background = loadImage("Background.png");
myPort = new Serial(this, "COM4", 115200); // inicia la comunicación serial
myPort.bufferUntil('\n');
}
void draw() {
image(background,0, 0); // Carga la imagen de fondo
pushMatrix();
translate(width/2, height/2, 0); // Traslada el sistema de coordenadas al centro de la pantalla, para que la rotación ocurra justo en el centro
rotateZ(radians(-heading)); // Rota la Brújula alrededor del eje Z
image(imgCompass, -960, -540); // Carga la imagen de la Brújula y como el sistema de coordenadas se ha reubicado necesitamos establecer la imagen en -960x, -540y (mitad del tamaño de la pantalla)
popMatrix(); // Trae el sistema de coordenadas de vuelta a la posición original 0,0,0
image(imgCompassArrow,0, 0); // Carga la imagen de la Flecha de la Brújula que no se ve afectada por la función rotateZ() debido a la función popMatrix()
textSize(30);
text("Heading: " + heading,40,40); // Imprime el valor del rumbo en la pantalla
delay(40);
}
// comienza a leer datos del Puerto Serie
void serialEvent (Serial myPort) {
data = myPort.readStringUntil('\n');// lee los datos del Puerto Serie y los pone en la variable String "data"
heading = float(data); // Convierte el valor String en valor Float
} Lenguaje: Arduino (arduino)
Proceso de manufactura
- Crea un Impresionante Sistema Ambilight para Monitor con Arduino
- Construye un Dispositivo de Levitación Ultrasónica con Arduino – Guía Paso a Paso
- Mando universal Android con Arduino, 1Sheeld y control IR
- Construye un Voltímetro Inteligente con Arduino y Smartphone – Proyecto DIY Fácil
- Medición precisa de frecuencia y ciclo de trabajo con Arduino UNO
- Crea un Botón de Teclado Personalizado y "Apuñalable" con Arduino: Guía Paso a Paso
- Medición de Distancia en Tiempo Real con Sonar Arduino y Visualización en Processing
- Contador Inteligente de Plazas de Aparcamiento: Seguimiento en Tiempo Real con Arduino, Processing y PHP
- Control de brillo LED sin interrupciones con Bolt IoT y Arduino UNO
- Brazo Robótico Inteligente Controlado por Arduino: Tutorial DIY Fácil
- Crea una Interfaz Web en PHP para Controlar tu Arduino Uno