KalbeAbbasRachel Janse van Rensburg
Published © MIT

Build Your Own Digital Compass with XinaBox

Learn how to build a digital compass that displays the heading of your device with respect to magnetic north.

BeginnerFull instructions provided6 minutes1,587
Build Your Own Digital Compass with XinaBox

Things used in this project

Hardware components

CW01
XinaBox CW01
×1
IP02
XinaBox IP02
×1
OD01
XinaBox OD01
×1
SI01
XinaBox SI01
×1
XC10
XinaBox XC10
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

Digital Compass

C/C++
The compass displays heading of the sensor with respect to Magnetic North.
#include <xCore.h>
#include <xSI01.h>
#include <xOD01.h>

//Sensor Object
xSI01 SI01;
xOD01 OD01;

//Calibration and Sesnor variables
float mX, mY, mZ;
float mx_min, my_min, mz_min;
float mx_max, my_max, mz_max;
float mx_offset, my_offset, mz_offset;
float mx_calibrated, my_calibrated, mz_calibrated;
float mx_scale, my_scale, mz_scale;
static unsigned long startTime;
float avg_scale;

String dir; //Direction String

void setup() {

  mx_max = 0; my_max = 0; mz_max = 0;
  mx_min = 0; my_min = 0; mz_min = 0;

  startTime = millis();

  // Start the Serial Monitor at 115200 BAUD
  Serial.begin(115200);

  // Set the I2C Pins for CW01
#ifdef ESP8266
  Wire.pins(2, 14);
  Wire.setClockStretchLimit(15000);
#endif

  Wire.begin();

  if (!SI01.begin()) {
    Serial.println("Failed to communicate with SI01.");
    Serial.println("Check the Connector");
  } else {
    Serial.println("start successful");
  }

  // get min/max values by taking readings
  // from magnetometer of your choice

  OD01.begin();
  OD01.println("Move the device");
  OD01.println("in figure 8");
  OD01.println("pattern for 10s");
  delay(1000);
  
  //Calculating calibration parameters

  while (true)
  {

    SI01.poll();
    mX = SI01.getMX(); mY = SI01.getMY(); mZ = SI01.getMZ();

    if (mX > mx_max) mx_max = mX; if (mY > my_max) my_max = mY; if (mZ > mz_max) mz_max = mZ;
    if (mX < mx_min) mx_min = mX; if (mY < my_min) my_min = mY; if (mZ < mz_min) mz_min = mZ;

    mx_offset = (mx_min + mx_max) / 2;
    my_offset = (my_min + my_max) / 2;
    mz_offset = (mz_min + mz_max) / 2;

    mx_scale = (mx_max - mx_min) / 2;
    my_scale = (my_max - my_min) / 2;
    mz_scale = (mz_max - mz_min) / 2;

    avg_scale = (mx_scale + my_scale + mz_scale) / 3;

    delay(100);

    if (millis() - startTime > 10000) break;

  }
  OD01.println("Calibration done!");
  delay(2000);
  OD01.clear();

}

void loop() {

  SI01.poll();

  mX = SI01.getMX(); mY = SI01.getMY(); mZ = SI01.getMZ();
  
  //Calculates calibrated magnetic field
  mx_calibrated = avg_scale / (mX - mx_offset);
  my_calibrated = avg_scale / (mY - my_offset);
  mz_calibrated = avg_scale / (mZ - mz_offset);

  //Calculates heading
  float heading;
  if (-my_calibrated == 0)
    heading = (-mx_calibrated < 0) ? PI : 0;
  else
    heading = atan2(-mx_calibrated, -my_calibrated);
  heading += 1.15* PI / 180;

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

  else if (heading < -PI) heading += (2 * PI);

  Serial.println(heading);
  Serial.print("MX: ");
  Serial.println(mx_calibrated);
  Serial.print("MY: ");
  Serial.println(my_calibrated);

  heading *= 180.0 / PI;

  heading=(int)heading;
  
  //Adjusting heading value
  if ((heading >= -90) && (heading) <=0) heading += 180;
  if ((heading >= -180) && (heading <= -90)) heading += 360;
  if((heading>90)&&(heading<=182)&&(mx_calibrated<0)) heading+=180;
  if(heading>=360)heading=0;

  if(heading>315 || heading<=45)dir="North";
  if(heading>45 && heading<=135)dir="East";
  if(heading>135 && heading<=225)dir="South";
  if(heading>225 && heading<=315)dir="West";

  OD01.set2X();
  OD01.println(dir);
  OD01.print(heading);
  Serial.println(heading);

  delay(100);
  OD01.clear();

}

Credits

KalbeAbbas

KalbeAbbas

25 projects • 20 followers
An enthusiastic and dedicated Electronic engineer graduated from SSUET Karachi, Pakistan. Loves to discover Embedded electronics projects.
Rachel Janse van Rensburg

Rachel Janse van Rensburg

8 projects • 5 followers
Thanks to XinaBox.

Comments