Working Principle
The Honeywell HMC5883L (and pin-compatible QMC5883L) is a 3-axis anisotropic magnetoresistive (AMR) sensor. Thin permalloy (NiFe) strips on the die change electrical resistance when exposed to an external magnetic field. By measuring resistance changes across three orthogonal axes, the sensor resolves the Earth's magnetic field vector into X, Y, Z components.
Analogy: Imagine three tiny compass needles mounted at right angles. Each needle's deflection tells you how much of the Earth's field pulls along that axis. Together they give you a full 3D magnetic vector.
Electrical Characteristics
| Parameter | Value |
|---|---|
| Supply Voltage | 2.16 V – 3.6 V |
| Measurement Range | ±1.3 to ±8.1 Gauss (configurable) |
| Resolution | 5 milliGauss (at ±1.3 Ga gain) |
| Output Data Rate | 0.75 – 75 Hz |
| Interface | I2C (address 0x1E / 0x0D for QMC5883L) |
| Current | 100 µA typical |
| Heading Accuracy | 1–2° (after calibration) |
Interfacing with an MCU
The HMC5883L uses I2C only at address 0x1E. The popular GY-271 breakout includes a voltage regulator and pull-ups. Note: many GY-271 modules now ship with the QMC5883L (address 0x0D) — check the chip marking and use the appropriate library.
Calibration
Magnetometers require hard-iron and soft-iron calibration to correct for nearby magnetic distortions:
- Hard-iron: Slowly rotate the sensor in all orientations, record min/max per axis, then compute offsets:
offset_x = (x_max + x_min) / 2. - Soft-iron: Scale axes so the calibration sphere becomes a true sphere:
scale_x = (y_range + z_range) / (2 * x_range). - Heading:
heading = atan2(y_cal, x_cal) * 180 / PI— apply magnetic declination for true north.
Code Example
/*
* HMC5883L Compass — Arduino I2C
* Uses Wire library directly (works with both HMC5883L and QMC5883L)
* Wiring: SCL→A5, SDA→A4, VCC→3.3V
*/
#include <Wire.h>
#define HMC5883L_ADDR 0x1E
void setup() {
Serial.begin(9600);
Wire.begin();
/* Configure: 8 samples averaged, 15 Hz, normal measurement */
Wire.beginTransmission(HMC5883L_ADDR);
Wire.write(0x00); Wire.write(0x70); /* Config Register A */
Wire.endTransmission();
/* Set gain to ±1.3 Ga (1090 LSB/Gauss) */
Wire.beginTransmission(HMC5883L_ADDR);
Wire.write(0x01); Wire.write(0x20); /* Config Register B */
Wire.endTransmission();
/* Continuous measurement mode */
Wire.beginTransmission(HMC5883L_ADDR);
Wire.write(0x02); Wire.write(0x00); /* Mode Register */
Wire.endTransmission();
Serial.println("HMC5883L Compass Ready");
}
void loop() {
Wire.beginTransmission(HMC5883L_ADDR);
Wire.write(0x03); /* Start at data register */
Wire.endTransmission();
Wire.requestFrom(HMC5883L_ADDR, 6);
int16_t x = (Wire.read() << 8) | Wire.read();
int16_t z = (Wire.read() << 8) | Wire.read();
int16_t y = (Wire.read() << 8) | Wire.read();
float heading = atan2((float)y, (float)x) * 180.0 / PI;
if (heading < 0) heading += 360.0;
Serial.print("X: "); Serial.print(x);
Serial.print(" Y: "); Serial.print(y);
Serial.print(" Z: "); Serial.print(z);
Serial.print(" Heading: "); Serial.print(heading, 1);
Serial.println("°");
delay(250);
}
Real-World Applications
Autonomous Robot Navigation
Mobile robots fuse magnetometer heading with wheel encoders and IMU data for dead-reckoning navigation in GPS-denied environments (warehouses, underground). The compass provides an absolute heading reference that corrects gyroscope drift over time.
Limitations
- Magnetic interference: Motors, speakers, and steel structures corrupt readings — mount far from ferrous components.
- Tilt error: Earth's field has a vertical component; without tilt compensation (accelerometer), heading errors grow with tilt angle.
- QMC5883L confusion: Many GY-271 modules ship with QMC5883L (different register map, address 0x0D) — verify the chip before coding.
- Indoor inaccuracy: Building rebar and wiring distort the local magnetic field, reducing accuracy to 5–10°.