Feedback!

Compass Necklace HMC5883

Views: 2760 Difficulty: 3 Status: Development
Compass_main

Wearable digital compass displays the direction in green LEDs.

This wearable electronic jewel shows you where you are headed by lighting the way North. It uses the HMC5883 3-axis magnetometer chip. Sparkfun has a breakout board, and bildr has a nice tutorial too. This is the same chip we use in our full-spectrum color compass tutorial. The code is straightforward: it finds the heading from the HMC5883 magnetometer and then lights up the LED that is in the corresponding direction. It needs to be held flat to work correctly, though you can tilt compensate these magnetometers with an accelerometer if you want them to work in any orientation.

Comes in two colors!

Compass_buddies
Choose between red or green LEDs to help show you the way!

LED Compass Necklace Video

The compass necklace in action!

Arduino Code for an LED Compass

This code will light up LEDs on the compass to indicate the direction you are facing. The big idea is to read the current direction from the compass then light up the LED on the circuit board that is closest to pointing in the direction. Since there are only 12 LEDs on the PCB and an infinite number of directions one could face we have to accept some rounding error. The heart of the code is located in the compass_mode() function, and it goes like this:
  float headingDegrees = heading * 180/PI; 
  int cur_led = map((int)headingDegrees, 360,0,0,12);
  //north adjust
  cur_led = (cur_led+6) % lights;
  digitalWrite(leds[cur_led], HIGH);
First, we adjust from radians to degrees by multiplying by 180 / PI. Then we map from the 360 possible degrees to a number between 0 and 11 which will be the index of the LED we want to light up. Notice that the mapping also reverses the order of Heading Degrees so that 360 gets mapped to 0 and 0 gets mapped to 12. This is necessary because the compass module is on the opposite side of the PCB as the silkscreened directions so to make them match up we have to flip the order. Lastly, we adjust the LED index so that the North LED will correspond to facing north. Finally, we do a digitalWrite to the LED.
We communicate with the HMC 5885 module via the I2C protocol so we use the standard Arduino wire library. We also use the library from bildr for communicating with the HMC 5883 chip.
/* LucidTronix LED Compass
 * The HMC 5583 compass mapped to 12 LEDs
 * on a beautifully silkscreened PCB
 * For instructions, details and schematic, See:
 * http://www.lucidtronix.com/tutorials/42
 */
// Reference the I2C Library
#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5883L.h>
// Store our compass as a variable.
HMC5883L compass;

int lights = 12;

int leds[] = {0,1,2,3,4,5,6,7,8,9,10,17};
int pwm_leds[] = {3,5,6,9,10,11 };
int buttonPin = 16;
int mode = 0;
int modes = 6;
int wait = 400;
int cur_fade = 0;
int delta = 1;
int cur_led_chase =0;
unsigned int last_press = 0;
void setup() // run once, when the sketch starts
{
  for (int i = 0; i < lights; i++){
    pinMode(leds[i], OUTPUT);
  }
  pinMode(buttonPin, INPUT);
  Wire.begin(); // Start the I2C interface.
  compass = HMC5883L(); // Construct a new HMC5883 compass.
  float scalar = 1.3;
  //not checking errors you should if you have issues.
  compass.SetScale(scalar); // Set the scale of the compass.
  compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
  for (int i = 0; i < lights; i++){
    digitalWrite(leds[i], HIGH);
    delay(40);
  }
  delay(250);
  for (int i = 0; i < lights; i++){
    digitalWrite(leds[i], LOW);
    delay(30);
  }
  delay(100);
}
void loop()                     // run over and over again
{   
  compass_mode();
}

void compass_mode(){
  for (int i = 0; i < lights; i++) digitalWrite(leds[i], LOW);
  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);
  float declinationAngle = 0.0457;
  heading += declinationAngle;
 // heading += northAdjust;
  // 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;
  float headingDegrees = heading * 180/PI; 
  int cur_led = map((int)headingDegrees, 360,0,0,12);
  //north adjust
  cur_led = (cur_led+6) % lights;
  digitalWrite(leds[cur_led], HIGH);
  delay(50);  
}

Parts

Title Description # Cost Link Picture
HMC5883L-TR IC COMPASS 3 AXIS I2C 16LCC SMD Value: 2.16 V ~ 3.6 V ±8G Compass - Three Axis 1 $3.44 Link Screen_shot_2012-12-28_at_7.35.30_pm
ATMEGA168A-AU IC MCU AVR 16K FLASH 32TQFP Value: 1.8 V ~ 5.5 V 20MHz 1 $2.43 Link Screen_shot_2012-12-28_at_7.31.53_pm
Crystal CRYSTAL 16.00000 MHZ 20PF SMD Value: 16MHz 1 $0.53 Link Ecs-270-20-3x-en-tr
Switch SWITCH SLIDE DPDT 6VDC 0.3A SMT Value: DPDT 1 $0.44 Link Mfg_js202011scqn
Button Tactile switch SMD SPST 0.05A 12V Value: SPST 1 $0.2 Link Fsm4jsma
LED SMD LED 3X1.5MM 568NM Green Clear SMD Value: 2.2V Green 12 $0.18 Link Apl3015sgc-f01
Resistor Chip Resistor - Surface Mount RES 10K OHM 1/8W 5% 0805 SMD Value: 10k 3 $0.1 Link Screen_shot_2012-12-28_at_7.29.44_pm
Capacitor CAP CER 0.1UF 50V Y5V 0805 Value: 0.1µF 1 $0.1 Link 0805(6_0mm_thickness)
Resistor Array RES ARRAY 300 OHM 4 RES 1206 Value: 300 3 $0.02 Link Vishay_-_cra06s-8
Permalink: http://lucidtronix.com/tutorials/37
The Wearable Wayfinder is a totally programmable, beautiful little computer for your wrist packed wit...
Standalone programmable Heart-Shaped LED display....
Coupling the HMC5883L Compass with our color library turns the TFT LCD screen into wearable navigatio...
Rainbow flower necklace using the TLC5940....
Connecting the DS1307 real-time clock chip and our Heart Matrix you can show the time with love....
Two LED matrices give 70 LEDs to light up a necklace with messages....
Combine an electret microphone, Arduino and a heart matrix for a sound-sensitive wearable device....
The heartduino is a heart-shaped arduino clone complete with onboard sensors and a 70 pixel LED matri...