🔶 How to connect the digital compass HMC5883L to Arduino


Consider connecting the GY-273 module with the Honeywell HMC5883L three-axis digital compass. This microcircuit can be used for magnetometric measurements, in navigation, if greater accuracy of measurements is not required (with an accuracy of 1 … 2 ° and the possibility of calibration). The device is connected via the I2C interface.

We will need:

  • Arduino UNO or another compatible card;
  • GY-273 module with digital magnetic field sensor HMC5883L;
  • connecting wires (I recommend this set);
  • breadboard;

Description of the HMC5883L digital compass and GY-273 module

The HMC5883L digital compass is a miniature microchip made on a single chip, cheap and unpretentious, and it quickly gained recognition from radio amateurs. Often it is sold as part of a finished module with all the necessary strapping, for example, GY-273.

Here are the main technical characteristics of the magnetic sensor:

  • 3-axis magnetosensitive sensor;
  • 12-bit ADC with a resolution of 2 MGs (milligauss);
  • built-in self-test;
  • low operating voltage and low consumption;
  • I2C digital interface;
  • high scanning speed – up to 160 times per second (the time of one measurement is about 6 ms);
  • accuracy of determining the direction of 1 … 2 °;
  • can be used in strong magnetic fields (up to ± 8 Gauss).

Connecting the HMC5883L digital compass to the Arduino

The diagram of the connection of the magnetic sensor HMC5883L to the Arduino is shown in the figure. It is very compact and simple: the two-wire interface IIC is good, which requires a small number of connections.

You can use the breadboard. It should turn out about as in the photo. I also have a logic analyzer connected to the SCL and SDA buses in order to control the information exchange.

Sketch for Arduino that reads HMC5883L identification registers

How is the exchange with the magnetic sensor HMC5883L? Open the passport to the sensor HMC5883L and find out that the address of the device is 0x1E, and the following registers are available:

Let’s try to read the identification registers of 10 (0xA), 11 (0xB) and 12 (0xC) devices as the first acquaintance.

#define addr 0x1E 
void setup() {
Wire.begin(); } void loop() { Wire.beginTransmission(addr); Wire.write(0x0A); Wire.endTransmission(); Wire.requestFrom(addr, 3, true); while( Wire.available() ) { char a = Wire.read(); char b = Wire.read(); char c = Wire.read(); Serial.print("A = "); Serial.println(a, HEX); Serial.print("B = "); Serial.println(b, HEX); Serial.print("C = "); Serial.println(c, HEX); Serial.println(); } delay(100); }

Opening the serial monitor, we will see:

A = 48
B = 34
C = 33

The signal received by the logic analyzer will be as follows:

What does it mean? The first byte is the I2C address with which we (the master, Arduino) establish a connection (the upper 7 bits 0x1E), and the write mode (the low bit is 0x0); the number 0x3C is obtained. The second byte is the number 0xA, which we recorded at address 0x1E and the acknowledge bit from the HMC5883L sensor, which is a slave. This is the register number from which we will start reading data. This is where the first transaction ended. Begins next. The third byte is the read request from the slave (the upper 7 bits are the address 0x1E, the 8th bit is the read operation 0x1; the number 0x3D is obtained). The last 3 bytes with the values ​​0x48, 0x34 and 0x33 are the response of the HMC5883L slave device from the registers 0xA, 0xB, and 0xC, respectively.

Moving through the registers of the digital compass HMC5883L with continuous reading is carried out automatically. Those. each time it is not necessary to specify the register (but not prohibited). For example, if instead of 0xA we would write 0x3 and count 10 times, then we would get the values ​​in 10 registers, starting from the 3rd to the 12th.

And what are these three numbers – 0x48, 0x34, 0x33? Using the passport on the HMC5883L digital compass again, we will see that these are the default values ​​for the three identification registers:

Sketch for Arduino, reading digital compass HMC5883L

And now let’s consider a typical measuring task: let’s take readings of magnetic induction along three axes. This example is described in the passport to the device. We only translate it into a language understandable Arduino. So sketch.

#define addr 0x1E 

void setup() {

void loop() { 
  Wire.requestFrom(addr, 6); 
  while( Wire.available() )  
    int h = Wire.read(); 
    int l = Wire.read(); 
    int x = word(h, l);  

    int y = Wire.read(); 
    y = y << 8; 
    y = y | Wire.read(); 

    int z = Wire.read() << 8; 
    z |= Wire.read(); 
    Serial.print("X = ");  
    Serial.println(x, DEC); 
    Serial.print("Y = ");  
    Serial.println(y, DEC); 
    Serial.print("Z = ");  
    Serial.println(z, DEC); 

This shows the different options for obtaining a two-byte number from two separate bytes. Here’s how we did it: separately we counted the high byte and the low byte, and then we used the word operator, which combined two bytes into a two-byte number (the “word”). You can do this: read the high byte, move it 8 bits to the left, count the low byte, and then combine them by OR (OR). In the latter case, simply the shorter syntax of the previous version is given. Choose the one that is more convenient and understandable to you.

Consider the timing diagram of information exchange:

The first 5 bytes to a short pause are what we described in the void setup () section:

  • selection of slave address and recording mode;
  • selection of the first control register A (CRA) with the address 0x00 (according to the table above);
  • entry in the first CRA control register of the number 0x70 – averaging over 8 points, 15 Hz, normal measurements (see passport for details); HMC5883L translates the pointer to the next register – Control Register B (CRB);
  • write to the CRB register the number 0xA0, which corresponds to a sensitivity setting of 5; HMC5883L translates the pointer to the next register – Mode Register, mode selection register;
  • write to the mode register the number 0x00 – infinite measurement mode.

Then there is a small pause of about 20 µs, and two more bytes are transmitted – this is the choice of the slave address in the write mode and the write of the registered address – 0x03 – with which we will begin each data reading cycle defined by us in void loop (). This is the first data register, as shown in the table above.

The last 7 bytes mean the following:

  • the first byte of the 7th – the choice of the address of the slave and the read mode;
  • the next two are reading two bytes of readings from the X-axis channel;
  • the next two are the Y-axis;
  • the next two are the z-axis.

As a result, in the port monitor, we see the indications of the magnetic sensor in three axes:


 If you rotate the sensor in space, you can see how the readings change.

I think that the calibration and adjustment of the digital compass is a topic for a separate article.

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest