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
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
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); } ; }