Simple Electronic Compass

> 2 min read

This is a simple electronic compass display project, which uses the HM55B compass module to determine the North direction. The LEDs will be used to indicate where North is. When the module is facing north, the specific LED that is facing north will light up. The code used was adapted from here.

How it works

ard_cmp1

The HM55B compass module is a dual axis magnetic field sensor, which means that it measures the strength of magnetic field of both the x-axis & y-axis. In this project, we will measure the surrounding magnetic field & indicate the direction of North using 4 LEDs located, which would be allocated as North, South, East & West direction respectively.

 

Demo

 

When the Compass Module is facing North, the LED facing North will light up.

 

Schematics

compass_light

 

Code

/*
/////////////////////////////////
Htachi HM55B Compass
parallax (#)

AUTHOR:   kiilo kiilo@kiilo.org
License:  http://creativecommons.org/licenses/by-nc-sa/2.5/ch/

http://parallax.com/Store/Microcontrollers/BASICStampModules/tabid/134/txtSearch/hm55b/List/1/ProductID/98/Default.aspx?SortField=ProductName%2cProductName
http://sage.medienkunst.ch/tiki-index.php?page=HowTo_Arduino_Parallax_HM55B_Kompass
http://playground.arduino.cc/HM55B

/////////////////////////////////
*/
#include <math.h> // (no semicolon)
//// VARS
byte CLK_pin = 8;
byte EN_pin = 9;
byte DIO_pin = 10;

int X_Data = 0;
int Y_Data = 0;
int angle;

int ledN = 2;
int ledE = 3;
int ledW = 4;
int ledS = 5;

//// FUNCTIONS

void ShiftOut(int Value, int BitsCount) {
  for(int i = BitsCount; i >= 0; i--) {
    digitalWrite(CLK_pin, LOW);
    if ((Value & 1 << i) == ( 1 << i)) {
      digitalWrite(DIO_pin, HIGH);
      //Serial.print("1");
    }
    else {
      digitalWrite(DIO_pin, LOW);
      //Serial.print("0");
    }
    digitalWrite(CLK_pin, HIGH);
    delayMicroseconds(1);
  }
//Serial.print(" ");
}

int ShiftIn(int BitsCount) {
  int ShiftIn_result;
    ShiftIn_result = 0;
    pinMode(DIO_pin, INPUT);
    for(int i = BitsCount; i >= 0; i--) {
      digitalWrite(CLK_pin, HIGH);
      delayMicroseconds(1);
      if (digitalRead(DIO_pin) == HIGH) {
        ShiftIn_result = (ShiftIn_result << 1) + 1; 
        //Serial.print("x");
      }
      else {
        ShiftIn_result = (ShiftIn_result << 1) + 0;
        //Serial.print("_");
      }
      digitalWrite(CLK_pin, LOW);
      delayMicroseconds(1);
    }
  //Serial.print(":");

// below is difficult to understand:
// if bit 11 is Set the value is negative
// the representation of negative values you
// have to add B11111000 in the upper Byte of
// the integer.
// see: http://en.wikipedia.org/wiki/Two%27s_complement
  if ((ShiftIn_result & 1 << 11) == 1 << 11) {
    ShiftIn_result = (B11111000 << 8) | ShiftIn_result; 
  }


  return ShiftIn_result;
}

void HM55B_Reset() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B0000, 3);
  digitalWrite(EN_pin, HIGH);
}

void HM55B_StartMeasurementCommand() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}

int HM55B_ReadCommand() {
  int result = 0;
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1100, 3);
  result = ShiftIn(3);
  return result;
}


void setup() {
  Serial.begin(115200);
  pinMode(EN_pin, OUTPUT);
  pinMode(CLK_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);
pinMode(ledN, OUTPUT);  
pinMode(ledE, OUTPUT);  
pinMode(ledW, OUTPUT);  
pinMode(ledS, OUTPUT);  


  HM55B_Reset();
}

void loop() {
  HM55B_StartMeasurementCommand(); // necessary!!
  delay(40); // the data is 40ms later ready
  Serial.print(HM55B_ReadCommand()); // read data and print Status
  Serial.print(" ");  
  X_Data = ShiftIn(11); // Field strength in X
  Y_Data = ShiftIn(11); // and Y direction
  Serial.print(X_Data); // print X strength
  Serial.print(" ");
  Serial.print(Y_Data); // print Y strength
  Serial.print(" ");
  digitalWrite(EN_pin, HIGH); // ok deselect chip
  angle = 180 * (atan2(-1 * Y_Data , X_Data) / M_PI); // angle is atan( -y/x) !!!
  Serial.print(angle); // print angle
  Serial.println("");
  if(angle==0){
    digitalWrite(ledN, HIGH); 
       digitalWrite(ledE, LOW);  
    digitalWrite(ledW, LOW);  
    digitalWrite(ledS, LOW);  
 
}else  if(angle==90){ 
    digitalWrite(ledN, LOW); 
       digitalWrite(ledE, HIGH);  
    digitalWrite(ledW, LOW);  
    digitalWrite(ledS, LOW);  
 
}else  if(angle==180){
    digitalWrite(ledN, LOW); 
       digitalWrite(ledE, LOW);  
    digitalWrite(ledW, LOW);  
    digitalWrite(ledS, HIGH);  
 
}else  if(angle==-90){
    digitalWrite(ledN, LOW); 
       digitalWrite(ledE, LOW);  
    digitalWrite(ledW, HIGH);  
    digitalWrite(ledS, LOW);  
 
}else{
   digitalWrite(ledN, LOW); 
       digitalWrite(ledE, LOW);  
    digitalWrite(ledW, LOW);  
    digitalWrite(ledS, LOW);  
}
  ;
}

You may also like...