Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Mirko Pavleski
Published © GPL3+

Arduino Analog + Digital Compass with HMC5883L sensor

Electronic version of the Compass, where the position of the needle is indicated by group of a three light-emitting diodes.

BeginnerFull instructions provided1 hour1,637
Arduino Analog + Digital Compass with HMC5883L sensor

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
HMC5883L Compass module
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1
NeoPixel Ring: WS2812 5050 RGB LED
Adafruit NeoPixel Ring: WS2812 5050 RGB LED
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Custom parts and enclosures

ring

Schematics

Schematic

circuit diagram,

Code

Code

Arduino
Arduino code,
/* Start of Code */
#include <SPI.h>
#include <Wire.h>
#include "FastLED.h"
#include <HMC5883L.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
#define OLED_RESET     4
#define SCREEN_ADDRESS 0x3C
Adafruit_SH1106 display(OLED_RESET);

#define NUM_LEDS 60 // Number of LEDs on Ring
#define DATA_PIN_RING 3 // Pin 3 connected to RGB Ring

CRGB leds_RING[NUM_LEDS];

HMC5883L compass;
int fixedHeadingDegrees; // Used to store Heading value

void setup()
{
Serial.begin(9600);
Wire.begin();
FastLED.addLeds<NEOPIXEL,DATA_PIN_RING>(leds_RING, NUM_LEDS);

    display.begin(SH1106_SWITCHCAPVCC, SCREEN_ADDRESS);
     display.clearDisplay();
       display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(22,10);
  display.println("mircemk");// Print text
  display.setCursor(22,40);
  display.println("COMPASS");
  display.display();
  delay(2000);

// Set measurement range
compass.setRange(HMC5883L_RANGE_1_3GA);

// Set measurement mode
compass.setMeasurementMode(HMC5883L_CONTINOUS);

// Set data rate
compass.setDataRate(HMC5883L_DATARATE_30HZ);

// Set number of samples averaged
compass.setSamples(HMC5883L_SAMPLES_8);

// Set calibration offset. See HMC5883L_calibration.ino
compass.setOffset(27, 200);
}

void loop()
{
Vector norm = compass.readNormalize();

// Calculate heading
float heading = atan2(norm.YAxis, norm.XAxis);

// Set declination angle on your location and fix heading
// You can find your declination on: http://magnetic-declination.com/
// (+) Positive or (-) for negative
// For Montreal,QC declination angle is -14'35W (negative)
// Formula: (deg + (min / 60.0)) / (180 / M_PI);
float declinationAngle = (5.0 + (3.0 / 60.0)) / (180 / M_PI);  //for Ohrid
heading -= declinationAngle;

// Correct for heading < 0deg and heading > 360deg
if (heading < 0)
{
heading += 2 * PI;
}

if (heading > 2 * PI)
{
heading -= 2 * PI;
}

// Convert to degrees
float headingDegrees = heading * 180/M_PI; 

// To Fix rotation speed of HMC5883L Compass module
if (headingDegrees >= 1 && headingDegrees < 240)
{
fixedHeadingDegrees = map (headingDegrees * 100, 0, 239 * 100, 0, 179 * 100) /100.00;
}
else {
if (headingDegrees >= 240)
{
fixedHeadingDegrees = map (headingDegrees * 100, 240 * 100, 360 * 100, 180 * 100, 360 * 100) /100.00;
}
}

int headvalue = fixedHeadingDegrees/4.88;
int ledtoheading = map(headvalue, 0, 59, 59, 0);

Serial.print("Angle:");
Serial.print(headingDegrees);
Serial.println();

    display.clearDisplay();   
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(20,10);
    display.println("Angle");

    display.setCursor(10,40);
    display.println(headingDegrees);
    display.display();

FastLED.clear();

if (ledtoheading == 0){
leds_RING[59] = CRGB::Red; 
leds_RING[0] = CRGB::Green; 
leds_RING[58] = CRGB::Green;
}
else {
if (ledtoheading == 59){
leds_RING[0] = CRGB::Red; 
leds_RING[59] = CRGB::Green; 
leds_RING[1] = CRGB::Green;
}
else {
leds_RING[ledtoheading] = CRGB::Red;
leds_RING[ledtoheading+1] = CRGB::Green;
leds_RING[ledtoheading-1] = CRGB::Green;
}
}

FastLED.setBrightness(50);
FastLED.show();
delay(100);
}

/* End of Code */

Credits

Mirko Pavleski

Mirko Pavleski

153 projects • 1301 followers

Comments