You will find below the Arduino and ProcessingCode. I used the arduino example code found into the library, and adaped it a bit.
The Processing code is from a code that I found on internet and adapted and changed some graphic details.
You will find also a link to download the library that I use.
Since the video, I have solved the angle issue, now performing 90 degrees angle with the compass will ouput correctly a +/- 90 degrees on the serial port.
HMC5883L Library:
http://dl.free.fr/q9O0J0cXe
Arduino code:
// Reference the I2C Library
#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5883L.h>
// Store our compass as a variable.
HMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;
//rounding angle
int RoundDegreeInt;
int PreviousDegree = 0;
// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
// Initialize the serial port.
Serial.begin(9600);
Wire.begin(); // Start the I2C interface.
compass = HMC5883L(); // Construct a new HMC5883 compass.
error = compass.SetScale(1.3); // Set the scale of the compass.
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));
error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));
}
// Our main program loop.
void loop()
{
// Retrive the raw values from the compass (not scaled).
MagnetometerRaw raw = compass.ReadRawAxis();
// Retrived the scaled values from the compass (scaled to the configured scale).
MagnetometerScaled scaled = compass.ReadScaledAxis();
// Values are accessed like so:
int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)
// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(scaled.YAxis, scaled.XAxis);
// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Mine is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
float declinationAngle = 0.009 ;
heading += declinationAngle;
// Correct for when signs are reversed.
if(heading < 0)
heading += 2*PI;
// Check for wrap due to addition of declination.
if(heading > 2*PI)
heading -= 2*PI;
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;
//correcting the angle issue
if (headingDegrees >= 1 && headingDegrees < 240)
{
headingDegrees = map(headingDegrees,0,239,0,179);
}
else if (headingDegrees >= 240)
{
headingDegrees = map(headingDegrees,240,360,180,360);
}
//rounding the angle
RoundDegreeInt =round(headingDegrees);
//smoothing value
if( RoundDegreeInt < (PreviousDegree + 3) && RoundDegreeInt > (PreviousDegree - 3) ) {
RoundDegreeInt = PreviousDegree;
}
Output(RoundDegreeInt);
PreviousDegree = RoundDegreeInt;
// Normally we would delay the application by 66ms to allow the loop
// to run at 15Hz (default bandwidth for the HMC5883L).
// However since we have a long serial out (104ms at 9600) we will let
// it run at its natural speed.
// delay(66);
}
// Output the data down the serial port.
void Output(int RoundDegreeInt)
{
//Serial.println();
Serial.println(RoundDegreeInt);
delay(150);
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Processing Code:
import processing.serial.*;
Serial myPort;
PFont b;
int lf = 10; // Linefeed in ASCII
String myString = null;
float angle;
void setup(){
size(600,400);
b = loadFont("Arial-BoldMT-48.vlw");
myPort = new Serial(this, "COM3", 9600);
}
void draw(){
background(255);
while (myPort.available() > 0) {
myString = myPort.readStringUntil(lf);
if (myString != null) {
//print(myString); // Prints String
angle=float(myString); // Converts and prints float
println(angle);
}
}
translate(160, 50);
// draw the compass background
ellipseMode(CENTER);
fill(50);
stroke(10);
strokeWeight(2);
ellipse(150,150,300,300);
// draw the lines and dots
translate(150,150); // translate the lines and dots to the middle of the compass
float CompassX = -angle;
rotate(radians(CompassX));
noStroke();
fill(51, 255, 51);
int radius = 120;
for( int degC = 5; degC < 360; degC += 10) //Compass dots
{
float angleC = radians(degC);
float xC = 0 + (cos(angleC)* radius);
float yC = 0 + (sin(angleC)* radius);
ellipse(xC,yC, 3, 3);
}
for( int degL = 10; degL < 370; degL += 10) //Compass lines
{
float angleL = radians(degL);
float x = 0 + (cos(angleL)* 145);
float y = 0 + (sin(angleL)* 145);
if( degL==90 || degL==180 || degL==270 || degL==360) {
stroke(51, 255, 51);
strokeWeight(4);
}
else {
stroke(234,144,7);
strokeWeight(2);
}
line(0,0, x,y);
}
fill(102, 102, 102);
noStroke();
ellipseMode(CENTER);
ellipse(0,0, 228,228); //draw a filled circle to hide the lines in the middle
b = loadFont("Arial-BoldMT-48.vlw");
textAlign(CENTER);
// Draw the letters
fill(250);
textFont(b, 32);
text("N", 1, -90);
rotate(radians(90));
text("E", 0, -90);
rotate(radians(90));
text("S", 0, -90);
rotate(radians(90));
text("W", 0, -90);
rotate(radians(90));
textFont(b,40);
textAlign(CENTER);
//text((angle), 20, 20);
println(angle);
//draw the needle
rotate(radians(-CompassX)); //make it stationary
stroke(234,144,7);
strokeWeight(3);
triangle(-10, 0, 10, 0, 0, -85);
fill(234,144,7);
triangle(-10, 0, 10, 0, 0, 60);
}