Hi. I have the Honeywell HMC5883L magnetometer sensor which I am using for a project involving a robotic minesweeper for a uni project.
About the project: We basically have this small vehicle which runs off an Arduino connected to motors. Sensors are used to control navigation and detection of mines, which are simulated by magnet disks buried under sand.
I just have some questions on it for now:
-
Would this library that I found suit my purposes (below)? I could just extract the relevant parts of code below to use in my main program?
-
What exactly do I do with the output data this provides?
With a distance sensor, I can compare the distance read and do something. Here, however, I get 7+(?) values? X/Y/Z raw, X/Y/Z scaled and an angle? What do I do with this in terms of my project? I have a basic general idea that x/y/z values will change according to the strength of a magnet near it, but in what way?
- I have the magnet disk I linked above with me and tested it with the code below and I seem to get a reaction so that values changed. However, I'm not sure how I deal with values. From observation, the following occurs:
- -4096 occurs when I place the magnet close to the sensor. This doesn't seem to be affected by whether I put it infront or behind
- Really low values (~-2 to 3) occur when I place it in contact or extremely close (maybe with a gap of around 2 millimeters)
Here is a screenshot of serial readings:
Are these occurrences normal?
-
Linked to 3, how would I approach trying to convert some reading into a distance measurement so I know if I've reached, say, 5cm, away from the mine?
-
The test stage for my minesweeper is circular in nature, and I wish to have the vehicle turn 180 essentially upon running into the wall. Could I use this sensor to somehow detect how much angle I've turned? I was thinking of assigning the current angle reading on start of turn, and then processing until the angle reading is off by 180? I'd do this in two 90 degree turns. Is this approach valid?
/*
HMC5883L_Example.pde - Example sketch for integration with an HMC5883L triple axis magnetomerwe.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Reference the I2C Library
#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5883L.h>
// Store our compass as a variable.
HMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;
// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
// Initialize the serial port.
Serial.begin(9600);
Serial.println("Starting the I2C interface.");
Wire.begin(); // Start the I2C interface.
Serial.println("Constructing new HMC5883L");
compass = HMC5883L(); // Construct a new HMC5883 compass.
Serial.println("Setting scale to +/- 1.3 Ga");
error = compass.SetScale(1.3); // Set the scale of the compass.
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));
Serial.println("Setting measurement mode to continous.");
error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));
}
// Our main program loop.
void loop()
{
// Retrive the raw values from the compass (not scaled).
MagnetometerRaw raw = compass.ReadRawAxis();
// Retrived the scaled values from the compass (scaled to the configured scale).
MagnetometerScaled scaled = compass.ReadScaledAxis();
// Values are accessed like so:
int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)
// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(scaled.YAxis, scaled.XAxis);
// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Mine is: 2? 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
float declinationAngle = 10.95 * DEG_TO_RAD;
heading += declinationAngle;
// Correct for when signs are reversed.
if(heading < 0)
heading += 2*PI;
// Check for wrap due to addition of declination.
if(heading > 2*PI)
heading -= 2*PI;
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;
// Output the data via the serial port.
Output(raw, scaled, heading, headingDegrees);
// Normally we would delay the application by 66ms to allow the loop
// to run at 15Hz (default bandwidth for the HMC5883L).
// However since we have a long serial out (104ms at 9600) we will let
// it run at its natural speed.
// delay(66);
}
// Output the data down the serial port.
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
Serial.print("Raw:\t");
Serial.print(raw.XAxis);
Serial.print(" ");
Serial.print(raw.YAxis);
Serial.print(" ");
Serial.print(raw.ZAxis);
Serial.print(" \tScaled:\t");
Serial.print(scaled.XAxis);
Serial.print(" ");
Serial.print(scaled.YAxis);
Serial.print(" ");
Serial.print(scaled.ZAxis);
Serial.print(" \tHeading:\t");
Serial.print(heading);
Serial.print(" Radians \t");
Serial.print(headingDegrees);
Serial.println(" Degrees \t");
}
Thanks.