The compass can be purchased at sparkfun
Image above shows the tiny compass sensor and on the right you can see the visualiser created in processing. The red dot describes the orientation of the compass, it is very accurate and sensitive to rotational movement and the sensors tiny size makes it very usable in wearable projects. The code below is for the compass (found on the arduino forum). I have adjusted only slightly so that it gives a figure over serial that is usable with processing which is right at the bottom of this page.
/**
compassHMC6352v02 10:06 14/01/2009
code grabbed from the arduino forum, some changes have been made but not to the nitty gritty
link: http://forum.sparkfun.com/viewtopic.php?t=6236
**/
#include -Wire.h-
int HMC6352Address = 0x42;
int slaveAddress; // This is calculated in the setup() function
byte headingData[2];
int i, headingValue;
void setup()
{
slaveAddress = HMC6352Address >> 1; // This results in 0x21 as the address to pass to TWI
Serial.begin(9600);
Wire.begin();
}
void loop()
{
// Send a "A" command to the HMC6352
// This requests the current heading data
Wire.beginTransmission(slaveAddress);
Wire.send("A"); // The "Get Data" command
Wire.endTransmission();
delay(10); // The HMC6352 needs at least a 70us (microsecond) delay
// after this command. Using 10ms just makes it safe
// Read the 2 heading bytes, MSB first
// The resulting 16bit word is the compass heading in 10th's of a degree
// For example: a heading of 1345 would be 134.5 degrees
Wire.requestFrom(slaveAddress, 2); // Request the 2 byte heading (MSB comes first)
i = 0;
while(Wire.available() && i < 2)
{
headingData[i] = Wire.receive();
i++;
}
headingValue = headingData[0]*256 + headingData[1]; // Put the MSB and LSB together
Serial.println(int (headingValue)); // The whole number part of the heading
delay(100);
}
/**
Code for reading in data from HMC6352 compass (or other)
and visualizing results.
Pete Rogers 19/12/2008 12.15
**/
import processing.serial.*;
int lf = 10; // Linefeed in ASCII
int myWidth = 600; // stage width
int myHeight = 600; //stage height
String sensorString = null; //string holding raw data from arduino
int sensorInt = 0; //number from sensor
Serial myPort; // The serial port
void setup() {
size(myWidth, myHeight); //set up the stage window
smooth(); //make the visual quality high
//lines below open and configure the serial port
println(Serial.list());
myPort = new Serial(this, Serial.list()[1], 9600);
myPort.clear();
sensorString = myPort.readStringUntil(lf);
sensorString = null;
}
void draw() {
background(255); //repaints background
drawCompassGraphics();
drawCompassDot((sensorInt / 10));
}
void drawCompassDot(float rot){
float r = radians(rot);
translate(myWidth/2,myHeight/2);
rotate(r);
fill(255,0,80);
ellipse(200,0,25,25);
fill(255,70,180);
noStroke();
ellipse(200,0,14,14);
}
/**
draws static graphics
**/
void drawCompassGraphics(){
for (int i = 0; i < 36; i = i + 3){
stroke(0);
strokeWeight(4);
pushMatrix();
translate(myWidth/2,myHeight/2);
rotate(radians(i * 10));
line(230,0,220,0);
popMatrix();
}
fill(255);
stroke(0);
strokeWeight(4);
ellipse(myWidth/2,myHeight/2,400,400);
}
//serialEvent function is triggered whenever there is data from the arduino
void serialEvent(Serial myPort){
sensorString = myPort.readStringUntil(lf);
if ( sensorString != null) {
sensorString = trim( sensorString);
sensorInt = int( sensorString);
}
}