Hey all,
I'm working on my first project on arduino, which is to guide a robotic car to certain locations. So far I have completed the setups for most of the modules (ie. gps, bluetooth, motors), but I'm facing some difficulties with the compass calibration. I'm using the arduino-HMC5883L library (GitHub - jarzebski/Arduino-HMC5883L: HMC5883L Triple Axis Digital Compass Arduino Library) and running the calibrate code:
#include <Wire.h>
#include <HMC5883L.h>
HMC5883L compass;
int minX = 0;
int maxX = 0;
int minY = 0;
int maxY = 0;
int offX = 0;
int offY = 0;
void setup()
{
Serial.begin(9600);
// Initialize Initialize HMC5883L
while (!compass.begin())
{
delay(500);
}
// 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);
}
void loop()
{
Vector mag = compass.readRaw();
// Determine Min / Max values
if (mag.XAxis < minX) minX = mag.XAxis;
if (mag.XAxis > maxX) maxX = mag.XAxis;
if (mag.YAxis < minY) minY = mag.YAxis;
if (mag.YAxis > maxY) maxY = mag.YAxis;
// Calculate offsets
offX = (maxX + minX)/2;
offY = (maxY + minY)/2;
Serial.print(mag.XAxis);
Serial.print(":");
Serial.print(mag.YAxis);
Serial.print(":");
Serial.print(minX);
Serial.print(":");
Serial.print(maxX);
Serial.print(":");
Serial.print(minY);
Serial.print(":");
Serial.print(maxY);
Serial.print(":");
Serial.print(offX);
Serial.print(":");
Serial.print(offY);
Serial.print("\n");
}
After obtaining the X and Y values I substitute them into the following code (Compass):
#include <Wire.h>
#include <HMC5883L.h>
HMC5883L compass;
void setup()
{
Serial.begin(9600);
// Initialize Initialize HMC5883L
Serial.println("Initialize HMC5883L");
while (!compass.begin())
{
Serial.println("Could not find a valid HMC5883L sensor, check wiring!");
delay(500);
}
// 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(0, 0);
}
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 Bytom / Poland declination angle is 4'26E (positive)
// Formula: (deg + (min / 60.0)) / (180 / M_PI);
float declinationAngle = (4.0 + (26.0 / 60.0)) / (180 / M_PI);
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;
// Output
Serial.print(" Heading = ");
Serial.print(heading);
Serial.print(" Degress = ");
Serial.print(headingDegrees);
Serial.println();
delay(100);
}
The issue I'm having with the compass is that the accuracy is off by like 40 degrees. The average x and y value I got for 3 trials were x = 15.67 and y = 597. However, after playing with x and y values I get an accuracy of 3-4 degrees (in all 4 directions) when i changed the x and y to 32 and 910 manually. What I don't understand is that why am I not getting a high accuracy from the actual x and y value from the code?
I have the compass attached at a high elevation, away from any interference.