Skip to Content

AK8975 Magnetometer with Arduino

AK8975 Magnetometer with Arduino

In this tutorial you will learn how to use the AK8975 3-Axis Magnetometer with an Arduino. The AK8975 is essentially an electronic compass that allows you to measure the strength of earth’s magnetic field (and other magnetic sources) along three axis.

The AK8975 uses highly sensitive Hall sensors and is designed for pedestrian city navigation in cell phone and other portable applications.

Required Parts

Obviously, you will need an AK8975 Sensor. Typically, you don’t buy the raw sensor but a breakout board that has a few extra components, which make it easier to connect the sensor.

Furthermore, you will need a microcontroller. I used an Arduino Uno for this project, but any other Arduino or any ESP32/ESP8266 will be fine.

AK8975 3-axis Magnetometer 

Arduino

Arduino Uno

USB Data Sync cable Arduino

USB Cable for Arduino UNO

Dupont wire set

Dupont Wire Set

Half_breadboard56a

Breadboard

Makerguides.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to products on Amazon.com. As an Amazon Associate we earn from qualifying purchases.

Features of the AK8975

The AK8975 is a 3-axis magnetometer suitable for compass application. It has a typical sensitivity of 0.3 µT / LSB with a resolution of 13 bit and has a built-in magnetic source for self-testing. The sensor offers I2C and 4-wire SPI as communication interfaces. It operates with 3-5V and has a typical current consumption of 350 µA. The following picture shows the internal block diagram of the AK8975:

Block Diagram of AK8975
Block Diagram of AK8975 (source)

You can easily identify the 3-axis Hall sensor to detect magnetic fields, the Multiplexer (MUX) to switch between the 3 axis, the built-in Magnetic Source for self-testing, the Analog-Digital-Converter (ADC) and the communication interface.

The pins of the AK8975 are as follows: VSS is Ground, VDD is the analog power supply and VID is the power supply for the digital interface.

CAD0 and CAD1 allow you to select the I2C address of the AK8975 (0x0C–0x0F). CSB enables the I2C or the SPI interface. To enable the I2C interface connect this pin to VID. SO is a serial output pin if the SPI interface is enabled.

SCL/SK and SDA/SI are the data communication pins for I2C or SPI, respectively. DRDY is the data-ready pin. High indictates that a data measurement is complete.

Finally, TST1, TST2 and TST6 are test points for manufacturing and RSF is a reserved pin. For more information see the datasheet of the AK8975 linked below:

Breakout board for AK8975

Typically you don’t buy the AK8975 chip itself but a breakout board that makes it much easier to connect the chip to an Arduino and also has the additional required electronic components. The picture below shows a typical breakout board for the AK8975:

Pinout of the AK8975
Pinout of the AK8975

The pinout essentially follows the pins described in the block diagram of the AK8975. VCC is the positive power supply and GND is ground. SCL and SDA are the data communication pins for I2C interface. SO is serial out – provided you use the SPI interface. CSB enables the I2C or the SPI interface. DRDY is the data-ready pin. And finally CAD0 and CAD1 are used to select the I2C address of the AK8975. The following table shows which CAD0 and CAD1 settings are linked to which I2C addresses:

I2C Address and CAD0/1 pin (source)

Note that there are several breakout boards for the AK8975, where the CDA1 pin is incorrectly labelled as CADY. See the example below:

AK8975 breakout board with CADY pin
AK8975 breakout board with CADY pin

But don’t worry, usually they are working fine and it just the wrong label on the silk screen.

Connecting AK8975 to Arduino

In this section, I show you how to connect the AK8975 to an Arduino. First, connect the SCL and SDA pins of the AK8975 breakout board to the corresponding pins on the Arduino board as shown below. Next, connect ground to GND and 3.3V (or 5V) to VCC of the AK8975.

To enable the I2C interface, we now need to connect CSB to 3.3V. And finally, we select the I2C address 0x0C by connecting CDA1 and CDA2 to ground.

Connecting AK8975 to Arduino
Connecting AK8975 to Arduino

If you have other devices connected to the I2C bus (e.g. a display) and they have conflicting I2C addresses, you can easily change the I2C address of the AK8975 by wiring CDA1 and CDA2 differently. For reference have a look at the table shown before.

To verify which I2C address is selected you can run the following I2C scanner code. It should print out the I2C address 0x0C. If not, something is wrong with your wiring.

#include "I2CScanner.h"

I2CScanner scanner;

void setup() {
  Serial.begin(9600);
  scanner.Init();
}

void loop() {
  scanner.Scan();
  delay(5000);
}

Code for measuring magnetic field with AK8975

In this section, I show you some example code to perform measurements with the AK8975. I am going to use the AK8975 Library by Jeff Rowberg. You could download the library as ZIP file from there and install it. But the library it is rather big and supports many more sensors, which you don’t need and which may conflict with other libraries.

I therefore extracted the necessary files and created a smaller library that contains only the code required for the AK8975 sensor. You can download the ZIP file of this library here. To install this ZIP library follow the usual steps. Click on Sketch -> Add .ZIP Library, and then select the file AK8975_lib.zip, you just downloaded.

Installing a .ZIP Arduino library
Installing a .ZIP Arduino library

With the library installed, let’s try the sensor out. The following code reads the strength of earth’s magnetic field along the three axis (X, Y, and Z) and prints them to the Serial monitor every half a second.

#include "Wire.h"
#include "AK8975.h"

AK8975 mag(0x0C);  

void setup() {
  Wire.begin();
  Serial.begin(9600);
  mag.initialize();
  if (!mag.testConnection()) {
    Serial.println("AK8975 connection failed!");
  }
}

void loop() {
  int16_t mx, my, mz;

  mag.getHeading(&mx, &my, &mz);

  Serial.print("X:");
  Serial.println(mx);
  Serial.print("Y:");
  Serial.println(my);
  Serial.print("Z:");
  Serial.println(mz);

  delay(500);
}

Let’s break down the code into its components for a clearer understanding.

Library Inclusion

First we include the Wire library and the necessary library for the AK8975 magnetometer. This library contains the functions and definitions needed to communicate with the sensor.

#include "Wire.h"
#include "AK8975.h"

Creating an Instance

Next, we create an instance of the AK8975 class named mag. This instance will allow us to access the functions defined in the library to interact with the magnetometer. Note that the I2C address of 0x0C is specified here.

AK8975 mag(0x0C);  

Setup Function

In the setup() function, we first initialize the Wire library. Serial.begin(9600) initializes the serial communication at a baud rate of 9600. This allows us to send data to the Serial Monitor for debugging and monitoring purposes.

Wire.begin();
Serial.begin(9600);

Next, we call the initialize() method on the mag instance to initialize the magnetometer. After that, we check the connection to the magnetometer using the testConnection() method. If we cannot connect, we print an error message to the Serial Monitor.

mag.initialize();
if (!mag.testConnection()) {
  Serial.println("AK8975 connection failed!");
}

Loop Function

In the loop() function, we start a measurement by calling the getHeading() method, which fills the magnetic field values mx, my, mz for the 3-axis.

int16_t mx, my, mz;
mag.getHeading(&mx, &my, &mz);

We then print the magnetic field values for the X, Y, and Z axes to the Serial Monitor.

Serial.print("X:");
Serial.println(mx);
Serial.print("Y:");
Serial.println(my);
Serial.print("Z:");
Serial.println(mz);

Finally, we introduce a delay of 500 milliseconds before the next measurement cycle begins, allowing for a readable output on the Serial Monitor.

delay(500);

Running the Code

If you upload and run the code, you should start to see magnetic field measurements, similar to the ones below, appearing on the Serial Monitor:

Output of AK8975 on Serial Monitor
Output of AK8975 on Serial Monitor

If you now tilt and rotate the sensor you can monitor the changing values of the magnetic field measurements for the three axis on the Serial Plotter:

Output of HSCDTD008A on Serial Plotter
Output of AK8975 on Serial Plotter

And that’s it! This tutorial should give you a good start with the AK8975.

Conclusions

In this tutorial you learned how to use the AK8975 3-Axis Magnetometer with an Arduino.

The AK8975 is very similar to the HSCDTD008A Magnetometer, though the HSCDTD008A has an resolution of 0.15μT/LSB while the AK8975’s resolution is only 0.3μT/LSB. On the other hand, the AK8975 has four different I2C addresses you can choose from, while the HSCDTD008A has a single, fixed I2C address.

The HSCDTD008A is the smaller chip, but on a breakout board that doesn’t really matter. However, due to its fixed I2C address the HSCDTD008A is also a bit easier to connect. Both magnetometer will be equally suitable for most application, though.

If you have an questions or comments, feel free to leave them in the comment section.

Happy Tinkering ; )