A compass is a device used for navigation and geographic orientation. It typically consists of a magnetized needle or another element, such as a compass card or compass rose, which can pivot to align itself with magnetic north.
In this project, we use Indus Board coin to make a compass. We program the board which uses accelerometer and magnetometer readings to calculate the heading of this compass.
Additionally, we use 4 LEDs which glows in the direction of compass, which are connected with four different pins of the Indus board.
Components required
S. No. | Name | Description | Number |
1. | Indus board coin | 3cm sized dev board | 1 |
2. | Device (laptop) | To program the Indus board. | 1 |
3. | USB cable | Required to connect Indus board to the device. | 1 |
4. | LEDs and resistors | To determine the direction of compass. | 4 |
5. | Jumper wires | To connect push buttons to the board. | 5 |
Schematic and Real Implementation
Arduino Code
#include <Wire.h>
#include <LSM303AGR_ACC_Sensor.h>
#include <LSM303AGR_MAG_Sensor.h>
#if defined(ARDUINO_SAM_DUE)
#define DEV_I2C Wire1 //Define which I2C bus is used. Wire1 for the Arduino Due
#define SerialPort Serial
#else
#define DEV_I2C Wire //Or Wire
#define SerialPort Serial
#endif
// Components
LSM303AGR_ACC_Sensor Acc(&DEV_I2C);
LSM303AGR_MAG_Sensor Mag(&DEV_I2C);
// Function prototypes
float calculateHeading(int32_t magData[3], int32_t accData[3]);
const int ledPin_n = 1;
const int ledPin_e = 2;
const int ledPin_s = 3;
const int ledPin_w = 4;
void setup() {
// Initialize the LEDs
pinMode(ledPin_n, OUTPUT);
pinMode(ledPin_e, OUTPUT);
pinMode(ledPin_s, OUTPUT);
pinMode(ledPin_w, OUTPUT);
// Initialize serial communication
SerialPort.begin(115200);
// Initialize I2C communication
DEV_I2C.begin();
// Initialize the accelerometer and magnetometer
if (Acc.begin() != 0) {
SerialPort.println("Failed to initialize LSM303AGR accelerometer!");
while (1);
}
if (Mag.begin() != 0) {
SerialPort.println("Failed to initialize LSM303AGR magnetometer!");
while (1);
}
// Enable the sensors
Acc.Enable();
Acc.EnableTemperatureSensor();
Mag.Enable();
}
void loop() {
// Read accelerometer data
int32_t accData[3];
Acc.GetAxes(accData);
// Read temperature
float temperature;
Acc.GetTemperature(&temperature);
// Read magnetometer data
int32_t magData[3];
Mag.GetAxes(magData);
// Calculate the heading
float heading = calculateHeading(magData, accData);
SerialPort.print("Heading: ");
SerialPort.print(heading, 3);
if((0<=heading and 20>=heading) or (340<=heading and 360>=heading)){
SerialPort.print(" NORTH");
digitalWrite(ledPin_n, HIGH); // pin 1
digitalWrite(ledPin_w, LOW); // pin 4
digitalWrite(ledPin_s, LOW); // pin 3
digitalWrite(ledPin_e, LOW); // pin 2
}
else if(70<=heading and 110>=heading){
SerialPort.print(" WEST");
digitalWrite(ledPin_w, HIGH); // pin 4
digitalWrite(ledPin_s, LOW); // pin 3
digitalWrite(ledPin_e, LOW); // pin 2
digitalWrite(ledPin_n, LOW); // pin 1
}
else if(160<=heading and 200>=heading){
SerialPort.print(" SOUTH");
digitalWrite(ledPin_s, HIGH); // pin 3
digitalWrite(ledPin_e, LOW); // pin 2
digitalWrite(ledPin_w, LOW); // pin 4
digitalWrite(ledPin_n, LOW); // pin 1
}
else if(250<=heading and 290>=heading){
SerialPort.print(" EAST");
digitalWrite(ledPin_e, HIGH); // pin 2
digitalWrite(ledPin_n, LOW); // pin 1
digitalWrite(ledPin_w, LOW); // pin 4
digitalWrite(ledPin_s, LOW); // pin 3
}
else if(20.01<=heading and 69.99>=heading){
SerialPort.print(" NORTH-WEST");
digitalWrite(ledPin_n, HIGH); // pin 1
digitalWrite(ledPin_w, HIGH); // pin 4
digitalWrite(ledPin_s, LOW); // pin 3
digitalWrite(ledPin_e, LOW); // pin 2
}
else if(110.01<=heading and 159.99>=heading){
SerialPort.print(" SOUTH-WEST");
digitalWrite(ledPin_n, LOW); // pin 1
digitalWrite(ledPin_w, HIGH); // pin 4
digitalWrite(ledPin_s, HIGH); // pin 3
digitalWrite(ledPin_e, LOW); // pin 2
}
else if(200.01<=heading and 249.99>=heading){
SerialPort.print(" SOUTH-EAST");
digitalWrite(ledPin_n, LOW); // pin 1
digitalWrite(ledPin_w, LOW); // pin 4
digitalWrite(ledPin_s, HIGH); // pin 3
digitalWrite(ledPin_e, HIGH); // pin 2
}
else if(290.01<=heading and 339.99>=heading){
SerialPort.print(" NORTH-EAST");
digitalWrite(ledPin_n, HIGH); // pin 1
digitalWrite(ledPin_w, LOW); // pin 4
digitalWrite(ledPin_s, LOW); // pin 3
digitalWrite(ledPin_e, HIGH); // pin 2
}
Serial.println();
// SerialPort.println(" degrees |");
delay(10); // Adjust delay as needed
}
float calculateHeading(int32_t magData[3], int32_t accData[3]) {
// Calculate tilt compensation
float pitch = atan2(accData[1], sqrt(sq(accData[0]) + sq(accData[2])));
float roll = atan2(-accData[0], accData[2]);
// Tilt compensation
float xh = magData[0] * cos(pitch) + magData[2] * sin(pitch);
float yh = magData[0] * sin(roll) * sin(pitch) + magData[1] * cos(roll) - magData[2] * sin(roll) * cos(pitch);
// Calculate heading in degrees
float heading = atan2(yh, xh) * 180 / PI;
// Normalize heading to 0-360 degrees
if (heading < 0) {
heading += 360;
}
return heading;
}
Author(s): Manjeet Vishwakarma, Â Abhay Verma and Satywanti Kundu are B.Tech ECE students at GJUS&T HISAR