Description
In this tutorial, I will show you how to configure and extract data from the magnetometer (HMC5883L) sensor on the GY-80 10DOF module from ICStation. While there are some very good libraries on the internet which will give you full access to this sensor, I will show you what you need to know without using a library. This means that it may get a bit technical at times, but I will hold your hand along the way and provide explanations as required. I would also recommend that you watch the complete video from start to finish - as the video provides really useful information.
HMC5883L Magnetometer Datasheet:
You can find the datasheet for the HMC5883L pretty easily by searching on the internet. Here are a couple of sources:
Arduino Libraries
This tutorial does not use any external libraries.
It does use the Wire library for I2C communication.
However, there is no extra download required to access the Wire library.
If you are looking for a library specific for the HMC5883L sensor, then I would recommend one of these:
Like I said - you do not need an HMC5883L library for this tutorial. The libraries above are listed for those who wish to learn more about this particular sensor.
Arduino IDE
The Arduino IDE can be downloaded from the Arduino website. Visit the Arduino IDE download page.
I generally use the ZIP file for Windows and never seem to have any issues.
There are downloads available for all the major operating systems.
ARDUINO CODE:
I have created a Gist for the Arduino code to configure and extract data from the HMC5883L sensor. However, I also have a GitHub repository which aims to capture the code for all of the sensors on the GY-80 module. Code for the other sensors will become available in due time. Meanwhile, have a look at the code below for the HMC5883L sensor:
//================================================================================================ | |
// Title: GY-80 3-axis Magnetometer (HMC5883L) | |
// Author: ScottC, http://arduinobasics.blogspot.com | |
// Version: 1.0 | |
// Date: 24th Oct 2016 | |
// Arduino IDE: 1.6.9 | |
// Attribution: Inspired by Sparkfun Quickstart guide : https://www.sparkfun.com/tutorials/301 | |
// Datasheet: https://cdn.sparkfun.com/datasheets/Sensors/Magneto/HMC5883L-FDS.pdf | |
// or | |
// https://cdn-shop.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf | |
// | |
// Description: This is a simple sketch which aims to quickly get you up and running with the GY-80 Magnetometer sensor. | |
// It does not go into too much detail, however, this sketch can be modified easily to | |
// accomodate changes in | |
// a) Output Rate (Hz) | |
// b) Number of samples per measurement output | |
// c) Amount of Gain | |
// This sketch uses Single measurement mode rather than continuous measurement mode. | |
// Single measurement mode data output can be quicker than continuous measurement mode. | |
// See datasheet for continuous measurement mode. | |
//================================================================================================ | |
#include <Wire.h> //I2C Arduino Library - inbuilt into Arduino IDE (no library download required) | |
#define address 0x1E //I2C address of the Magnetometer | |
//Global variables | |
int x,y,z; //Variables used to hold the triple axis data | |
int xCal=0, yCal=0, zCal=0; //Variables used to calibrate the triple axis data. | |
int calValue = 1000; //On startup, all axis variables will equal this number. | |
//===================================================================================================== | |
// setup(): | |
// This runs once only. | |
// Setup Serial and I2C communication. | |
// Configure the Magnetometer to use 8 samples (averaged) per measurement output. (Register A) | |
// Change the output rate of Magnetometer to 3Hz : This is only useful in continuous-measurement mode. (Register A) | |
// Set the gain to +/- 2.5 Ga, which changes the digital resolution to 1.52 (Register B) | |
// Calibrate all axis values to 1000. Which means that all axis variables will equal 1000 on startup, no matter what position the sensor is in. | |
//----------------------------------------------------------------------------------------------------- | |
void setup(){ | |
//Initialize Serial and I2C communications | |
Serial.begin(9600); | |
Wire.begin(); | |
//Setup the magnetometer | |
magSetting(0x00, B01101000); // Magnetometer settings associated with Register A. See datasheet for acceptable values. | |
magSetting(0x01, B01100000); // Magnetometer settings associated with Register B. See datasheet for acceptable values. | |
calibrateMag(); // Set or calibrate all axis variables to the calValue. | |
} | |
//===================================================================================================== | |
// loop(): | |
// This code runs in an endless loop | |
// getReadings(): is used to read the data for each axis and assign these values to variables x,y and z. | |
// printReadings(): is used to display these values in the Serial Monitor window. | |
//----------------------------------------------------------------------------------------------------- | |
void loop(){ | |
getReadings(); | |
printReadings(); | |
} | |
//===================================================================================================== | |
// magSetting(regLoc, setting): | |
// regLoc: is the register address location that we want to interact with (RegA = 0x00, RegB = 0x01, Mode = 0x02) | |
// setting: is the 8bit code used to configure the magnetometer (see datasheet) | |
// | |
// This function allows you to configure the magnetometer to suit your specific application | |
// A delay of 10 is used, but anything above 7 is recommended. | |
//----------------------------------------------------------------------------------------------------- | |
void magSetting(byte regLoc, byte setting){ | |
Wire.beginTransmission(address); | |
Wire.write(regLoc); | |
Wire.write(setting); | |
Wire.endTransmission(); | |
delay(10); | |
} | |
//===================================================================================================== | |
// getReadings(): | |
// It is necessary to send the bytes (0x02 and 0x01) to instruct the magnetometer to prepare for single measurement mode | |
// Request 6 bytes from the magnetometer and then read 2 bytes per axis (assigned to variables x, y and z). | |
// The xCal, yCal, and zCal variables adjust the magnetometer's readings relative to it's initial state. | |
// Set the global "calValue" variable to 0 if you don't want to "calibrate" the magnetometer on startup. | |
// The magnetometer should send back 6 bytes of positional data, if not, an Error message will be printed to the serial monitor | |
//----------------------------------------------------------------------------------------------------- | |
void getReadings(){ | |
magSetting(0x02, 0x01); //prepare to take reading (Single measurement mode) - this populates the registers with data | |
Wire.requestFrom(address, 6); //Request 6 bytes. Each axis uses 2 bytes. | |
if (Wire.available()>5){ | |
x = readValue()- xCal; | |
z = readValue()- zCal; | |
y = readValue()- yCal; | |
} else { | |
Serial.println("****Error: Less than 6 bytes available for reading*****"); | |
} | |
} | |
//===================================================================================================== | |
// readValue(): | |
// This reads the magnetometer's data registers - 2 bytes at a time. | |
// All 6 data registers must be read properly before new data can be placed into any of these data registers | |
// This function reads two bytes (8bit + 8bit) and joins them together to make a 16bit integer value. | |
// This value is returned and assigned to one of the axis variables x, y and/or z. | |
// With every read() called, the data register pointer is incremented. | |
// When magSetting(0x02, 0x01) is called in the getReadings() function, the pointer is reset to the first data register (03). | |
//----------------------------------------------------------------------------------------------------- | |
int readValue(){ | |
int val = Wire.read()<<8; | |
val |= Wire.read(); | |
return val; | |
} | |
//===================================================================================================== | |
// printReadings(): | |
// This funtion is used to print the 3 axis values (x, y and z) to the Serial monitor window. | |
//----------------------------------------------------------------------------------------------------- | |
void printReadings(){ | |
Serial.print("x: "); | |
Serial.print(x); | |
Serial.print(" y: "); | |
Serial.print(y); | |
Serial.print(" z: "); | |
Serial.println(z); | |
} | |
//===================================================================================================== | |
// calibrateMag(): | |
// This function is used to calibrate or set each axis value to calValue. | |
// calValue is defined in the global variables section (=1000) | |
// After calibration, each axis variable (x, y and z) will equal the calValue, no matter what position the magnetometer is in. | |
//----------------------------------------------------------------------------------------------------- | |
void calibrateMag(){ | |
getReadings(); | |
xCal = x-calValue; | |
yCal = y-calValue; | |
zCal = z-calValue; | |
} |
This code will set all axis values to 1000 upon startup. Moving the GY-80 module around will result in a value greater or less than 1000, however, returning the sensor back to it's original position, should result in values very close to 1000 on each axis. I chose to introduce this calibration in order to avoid negative values, and I liked the fact that I could set a heading with values that were easy to remember.
The magSetting function was created to easily configure the magnetometer.
Make sure to look at the video and also the datasheet for further information about calibrating the magnetometer.
The getReadings function was created to easily retrieve the magnetometer axis data. I chose to use Single measurement mode in this tutorial.
Hooking it up:
You can communicate with any of the sensors on the GY-80 module using I2C. The HMC5883L magnetometer sensor is no different. You will need four connections between the Arduino UNO and the GY-80 module. Have a look at the diagram below for the connection diagram and table.
Fritzing diagram
Project pictures
Concluding comments
The HMC5883L sensor on the GY-80 module is quite interesting and works relatively well. There are a number of other sensors on the GY-80 module which can provide complementary positional data. At some point, I plan to come back and explain some of the other sensors on this module, but first I would like to create a real-life project using the magnetometer. So stay tuned. You may want to subscribe to my social networks or to this blog to be notified of that project when I complete it.
I would like to thank ICStation for their collaborative efforts. Their contribution was invaluable to this tutorial's existence.
Visit my ArduinoBasics Google + page.
Follow me on Twitter by looking for ScottC @ArduinoBasics.
I can also be found on Pinterest and Instagram.
Have a look at my videos on my YouTube channel.
Description: HMC5883L on the GY-80 module Rating: 3.5 Reviewer: Unknown ItemReviewed: HMC5883L on the GY-80 module
0 comments:
Post a Comment