Digitaler Kompass in Echtzeit mit Arduino & Processing bauen
In diesem Arduino-Projekt zeigen wir, wie man einen coolen Kompass mit Arduino, einem MEMS-Magnetometer und der Processing IDE baut. Hier ist ein Demonstrationsvideo:
Überblick
Benötigt werden: Ein MEMS-Magnetometer zur Messung des Erdmagnetfelds, ein Arduino-Board und Jumper-Kabel. Als Beispiel nutze ich den HMC5883L, ein 3-Achsen-Magnetometer auf dem GY-80 Breakout-Board.
Funktionsweise des Kompasses
Arduino-Teil
Zuerst lesen wir die Sensordaten per I2C-Protokoll über den Arduino ein. Aus den X- und Y-Achsen-Werten berechnen wir den Kurs (Heading) und senden ihn über den seriellen Port an die Processing IDE. Der folgende Code erledigt das:
/* Arduino Kompass
* von Dejan Nedelkovski,
* www.HowToMechatronics.com
*/
#include <Wire.h> // I2C Arduino Bibliothek
#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 // I2C 7-Bit Adresse HMC5883
void setup() {
Serial.begin(115200);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Modus-Register wählen
Wire.write(0x00); // Kontinuierlicher Messmodus
Wire.endTransmission();
}
void loop() {
//---- X-Achse
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mX0 = Wire.read(); }
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mX1 = Wire.read(); }
//---- Y-Achse
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mY0 = Wire.read(); }
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mY1 = Wire.read(); }
//---- Z-Achse
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mZ0 = Wire.read(); }
Wire.beginTransmission(Magnetometer);
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer, 1);
if(Wire.available() <= 1) { mZ1 = Wire.read(); }
//---- Rohdaten zusammenfügen
mX1 = mX1 << 8; mX_out = mX0 + mX1;
Xm = mX_out * 0.00092; // Gauss (laut Datenblatt: 0,92 mG/digit)
mY1 = mY1 << 8; mY_out = mY0 + mY1;
Ym = mY_out * 0.00092;
mZ1 = mZ1 << 8; mZ_out = mZ0 + mZ1;
Zm = mZ_out * 0.00092;
// ==============================
// Kurs berechnen
heading = atan2(Ym, Xm);
// Deklination korrigieren (standortabhängig)
// Finden Sie Ihren Deklinationswinkel: https://www.ngdc.noaa.gov/geomag-web/
// An meinem Standort: 4,2 Grad => 0,073 rad
declination = 0.073;
heading += declination;
// Vorzeichen korrigieren
if(heading < 0) heading += 2*PI;
if(heading > 2*PI) heading -= 2*PI;
headingDegrees = heading * 180/PI; // Grad
// Glättung / Tiefpassfilter
headingFiltered = headingFiltered * 0.85 + headingDegrees * 0.15;
// Kurswert über Serial an Processing senden
Serial.println(headingFiltered);
delay(50);
}
Für Details zur Funktionsweise von MEMS-Magnetometern und Datenerfassung siehe mein MEMS-Sensoren-Tutorial.
Processing IDE Teil
Hier empfangen wir die Kurswerte vom seriellen Port. Details zur Arduino-Processing-Kommunikation finden Sie in meinem Arduino-Processing-Tutorial.
Der Kompass besteht aus mehreren transparenten Bildern, die in Processing geladen werden. Die Bilder müssen im Arbeitsverzeichnis des Sketches liegen. Im draw()-Bereich laden wir per image() zuerst das Hintergrundbild (optional, kann auch einfarbig sein). Dann laden wir das Kompassbild, das mit rotateZ() entsprechend dem Kurswert gedreht wird. Darüber liegt das Kompass-Pfeil-Bild.
Hier ist der Processing-Code:
/* Arduino Kompass
* von 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);
myPort.bufferUntil('\n');
}
void draw() {
image(background, 0, 0);
pushMatrix();
translate(width/2, height/2, 0); // Koordinatensystem in Bildschirmmitte verschieben
rotateZ(radians(-heading)); // Kompass um Z-Achse drehen
image(imgCompass, -960, -540); // Bild bei halber Bildschirmgröße negativ positionieren
popMatrix(); // Koordinatensystem zurücksetzen
image(imgCompassArrow, 0, 0); // Pfeil nicht von Rotation betroffen
textSize(30);
text("Heading: " + heading, 40, 40);
delay(40);
}
void serialEvent(Serial myPort) {
data = myPort.readStringUntil('\n'); // Daten bis Zeilenende lesen
heading = float(data); // String in Float umwandeln
}
Projektdateien (Bilder & Quellcodes) zum Download:
Herstellungsprozess
- Monitor-Ambilight selbst bauen mit Arduino Nano & WS2812B LEDs
- Ultraschall-Schwebegerät mit Arduino bauen – Akustische Levitation Schritt für Schritt
- Universelle Android-Fernbedienung mit Arduino, 1Sheeld & IR-Steuerung
- Intelligentes Voltmeter mit Arduino & Smartphone bauen – Einfaches DIY-Projekt
- Frequenz & Tastverhältnis präzise messen mit Arduino UNO
- Selbstbau: Schlagbare, anpassbare Tasten mit Arduino und Piezo-Element
- Echtzeit-Entfernungsmessung mit Arduino Sonar & Processing-Visualisierung
- Intelligenter Parkplatzzähler: Echtzeit-Fahrzeugverfolgung mit Arduino, Processing & PHP
- Stufenlose LED-Helligkeitssteuerung mit Bolt IoT und Arduino UNO
- Intelligenter Arduino-Roboterarm bauen: Einfaches DIY-Tutorial