Feedback!

Color Compass

Views: 5820 Difficulty: 4 Status: Development
Screen_shot_2013-03-01_at_7.27.14_pm

Coupling the HMC5883L Compass with our color library turns the TFT LCD screen into wearable navigation.

Compasses help us orient ourselves in the world. The HMC 5883L is an affordable 3-axis compass. Bildr has a great tutorial and library to get you started. You can get the compass from sparkfun or digikey. We connect the compass to a SMD package arduino hooked up to a TFT LCD Screen. We use our arduino color library to color the compass hand rainbow colors depending on where it is facing.

Rainbow Compass

Compassy
Rainbows show you the cardinal directions.

Compass Video

Color compass accelerated. Strong magnets will confuse it.

Arduino Code

This code relies on several libraries: the very thorough HMC5883L library from bildr, adafruit's ST7735 TFT LCD Screen library, our color library, and the standard arduino SPI library. Okay now that we got the dependencies down, we got some functions to talk about:
int get_color_from_angle(int angle){
  Color cur_color=Color(0,0,0);
  cur_color.convert_hcl_to_rgb((float)angle/360,0.95,0.7);
  return cur_color.get_color_16bit(); 
}
This function translates from a degree ((0-360) that we got from the compass which represents our heading) and a color. Using the HSB color mode the above code maps each heading to a different hue. Then once we have read the heading from the compass (it is given in radians) we draw a ray and two orbiting circles rotated by the heading:
float headingDegrees = heading * 180/M_PI; 
  draw_ray(64,80, headingDegrees, 40);
  draw_orbiter(64,80, headingDegrees, 22,6);
  draw_orbiter(64,80, headingDegrees, 32,3);
/* LucidTronix color compass 
 * Rainbow colored wearable navigator 
 * For instructions, details and schematic, See:
 * http://www.lucidtronix.com/tutorials/30
 * Uses the HMC5883L.h library from bildr
 */
#include <color.h>
#include <ST7735.h>
#include <SPI.h>

#define cs 10   // for MEGAs you probably want this to be pin 53
#define dc 9
#define rst 8  // you can also connect this to the Arduino reset

ST7735 tft = ST7735(cs, dc, rst);

// 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;

int btnPin0 = 0;
int btnPin1 = 1;

int mode = 0;
int num_modes = 4;

unsigned int last_press = 0;

int background_color = 0xFF;
int color = 0xFF;

int backlight_pwm_pin = 3;
char* stringy = "nothinghere";
void setup(){
  pinMode(btnPin1,INPUT);
  pinMode(btnPin0,INPUT);
  tft.initR();               // initialize a ST7735R chip
  tft.writecommand(ST7735_DISPON); 
  delay(1000);
  tft.fillScreen(BLACK);
  tft.drawString(4, 4, "Starting up...", CYAN,1);
  Wire.begin(); // Start the I2C interface.
  compass = HMC5883L(); // Construct a new HMC5883 compass.
  float scalar = 4.0;
  //not checking errors you should if you have issues.
  error = compass.SetScale(scalar); // Set the scale of the compass.
  error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
  delay(500);
}
void loop(){
  if ( digitalRead(btnPin0) == HIGH)tft.fillScreen(WHITE);
  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;
  // 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/M_PI; 
  draw_ray(64,80, headingDegrees, 40);
  draw_orbiter(64,80, headingDegrees, 22,6);
  draw_orbiter(64,80, headingDegrees, 32,3);
}

void draw_ray(int ax, int ay, int angle, int radius ){
  float ray_x = cos(((float)angle*PI)/180.0f)*(float)radius;
  float ray_y = sin(((float)angle*PI)/180.0f)*(float)radius;
  int c = get_color_from_angle(angle);
  tft.drawLine(ax,ay,ax+ray_x, ay+ray_y, c);
}

void draw_orbiter(int ax, int ay, int angle, int radius, int a_size){
  float ray_x = cos(((float)angle*PI)/180.0f)*(float)radius;
  float ray_y = sin(((float)angle*PI)/180.0f)*(float)radius;
  int c = get_color_from_angle(angle);
  tft.fillCircle(ax+ray_x, ay+ray_y, a_size, c);
}

int get_color_from_angle(int angle){
  Color cur_color=Color(0,0,0);
  cur_color.convert_hcl_to_rgb((float)angle/360,0.95,0.7);
  return cur_color.get_color_16bit(); 
}

Parts

Title Description # Cost Link Picture
Wearable Wayfinder An Arduino on steroids! Full color LCD screen, accelerometer, compass, and real time clock loaded onto a wearable gadget! 1 $69.95 Link 3screens2
Permalink: http://lucidtronix.com/tutorials/30
The Wearable Wayfinder is a totally programmable, beautiful little computer for your wrist packed wit...
Wearable digital compass displays the direction in green LEDs....
Play pong on a little LCD screen with two big joysticks....
Control the hue, value and saturation on this pocket-sized joystick drawing machine....
Standalone programmable Heart-Shaped LED display....
Handheld gaming machine, based on the Arduino Leonardo, equipped with joystick, SD card and more....
Display bitmap images and text files and folders with this TFT LCD screen and SD Card navigator....
Mixing pixels from two face images together....