Overview

The NXP Precision 9DoF breakout combines two of the best motion sensors we've tested here at Adafruit: The FXOS8700 3-Axis accelerometer and magnetometer, and the FXAS21002 3-axis gyroscope.

These two sensors combine to make a nice 9-DoF kit, that can be used for motion and orientation sensing. In particular, we think this sensor set is ideal for AHRS-based orientation calculations: the gyro stability performance is superior to the LSM9DS0, LSM9DS1L3GD20H + LSM303, MPU-9250, and even the BNO-055 (see our Gyro comparison tutorial for more details)

Compared to the BNO055, this sensor will get you similar orientation performance but at a lower price because the calculations are done on your microcontroller, not in the sensor itself. The trade off is you will sacrifice about 15KB of Flash space, and computing cycles, to do the math 'in house'

To make it fast and easy for you to get started, we have a version of AHRS that we've adapted to work over USB or Bluetooth LE. Load the code onto your Arduino-compatible board and you will get orientation data in the form of Euler angles or quaternions! It will work on a ATmega328 but faster/larger chips such as M0 or ESP8266 will give you more breathing room.

Each board comes with the two chips soldered onto a breakout with 4 mounting holes. While the chips support SPI, they don't tri-state the MISO pin, so we decided to go with plain I2C which works well and is supported by every modern microcontroller and computer chip set.  There's a 3.3V regulator and level shifting on the I2C and Reset lines, so you can use the breakout safely with 3.3V or 5V power/logic. Each order comes with a fully assembled and tested breakout and a small strip of header. Some light soldering is required to attach the header if you want to use in a breadboard.

So what makes this so 'Precision'-y, eh?

Glad you asked! This particular sensor combination jumped out at us writing the Comparing Gyroscopes learning guide since the FXAS21002 exhibited the lowest zero-rate level off any of the gyroscopes we've tested, with the the following documented levels (converted to degrees per second for convenience sake):

  • At +/- 2000 dps 3.125 dps
  • At +/- 250 dps 0.3906 dps

The zero-rate level is important in orientation since it represents the amount of angular velocity a gyroscope will report when the device is immobile. High zero-rate levels can cause all kinds of problems in orientation systems if the data isn't properly compensated out, and distinguishing zero-rate errors from actual angular velocity can be non-trivial. This is particularly important in sensor fusion algorithms where the gyroscope plays an important part in predicting orientation adjustments over time. A high zero-rate level will cause constant rotation even when the device is immobile!

By comparison, most other sensors tested have 10-20 times these zero-rate levels, which is why we consider this particular part very precise. There is little work to do out of the box to get useful, actionable data out of it. See the table of similar parts below to compare for yourself:

Technical Details

The NXP Precision 9DoF board consists of two separate ICs, described in detail below:

FXOS8700 3-Axis Accelerometer/Magnetometer

  • 2-3.6V Supply
  • ±2 g/±4 g/±8 g adjustable acceleration range
  • ±1200 µT magnetic sensor range
  • Output data rates (ODR) from 1.563 Hz to 800 Hz
  • 14-bit ADC resolution for acceleration measurements
  • 16-bit ADC resolution for magnetic measurements

FXAS21002 3-Axis Gyroscope

  • 2-3.6V Supply
  • ±250/500/1000/2000°/s configurable range
  • Output Data Rates (ODR) from 12.5 to 800 Hz
  • 16-bit digital output resolution
  • 192 bytes FIFO buffer (32 X/Y/Z samples)

Assembly

Prepare the header strip:

Cut the strip to length if necessary. It will be easier to solder if you insert it into a breadboard - long pins down

Add the breakout board:

Place the breakout board over the pins so that the short pins poke through the breakout pads

And Solder!

Be sure to solder all pins for reliable electrical contact.

Solder one side first

(For tips on soldering, be sure to check out our Guide to Excellent Soldering).

Twist the board around and solder the other row!

You're done! Check your solder joints visually and continue onto the next steps

The NXP Precision 9DoF breakout has the following pinout:

Power Pins

  • VIN - 3.3-5V input, which feeds the on board 3.3V voltage regulator and optionally sets the signal levels for the I2C pins (SCL and SDA) if you are using a 5V system. On a 3.3V system (any Adafruit Feather, for example), connect 3.3V to VIN for 3.3V logic throughout the system. On a 5.0V system, connect VIN to 5V, and the signals will be shifted downward to 3.3V before reaching the NXP sensors (which are limited to 3.6V or less for the pins).
  • 3Vo - This is the output of the 3.3V linear regulator on the NXP Precision 9DoF Breakout. On a 5V system, you can use this as an additional 3.3V supply if you need some extra 3.3V power.
  • GND - This should be connected to GND on your development board.

Digital Pins

  • SCL - I2C, Connect this to SCL on your development board. This pin is level-shifted and 3-5V logic safe.
  • SDA - I2C, Connect this to SDA on your development board. This pin is level-shifted and 3-5V logic safe.
  • RST - Optionally connect this to RST on your development board (depending on the logic level used), or to a GPIO pin if you wish to manually reset the sensors on the breakout. This pin isn't required in most circumstances, but can be useful to recover from error conditions on long running systems where the sensors might have entered an unknown config state. This pin is level-shifted and 3-5V logic safe.
  • AI1, AI2 - This two pins allow interrupts from the Accelerometer/Magnetometer (see the datasheet for details). These are not level shifted but since they are outputs only, you can use with 3 or 5V logic systems.
  • GI1, G12 - These two pins allow interrupts from the Gyroscope (see the datasheet for details). These are not level shifted but since they are outputs only, you can use with 3 or 5V logic systems.

Breadboard Connection

Since 9DoF sensors are usually used for orientation and detecting movement, you'll normally want to securely connect the breakout to something before using it.

The pinout below shows how you can connect the NXP Precision 9DoF Breakout to any Adafruit Feather development board. The image below uses the Bluefruit nRF52 Feather, which is a great MCU to combine with the NXP Precision 9DoF since the ARM Cortex M4F has a lot of processing power, and Bluetooth Low Energy makes it easy to get the orientation data onto your phone or computer without any cables getting in the way!

Arduino Code

Breadboard Connection

Since 9DoF sensors are usually used for orientation and detecting movement, you'll normally want to securely connect the breakout to something before using it.

The pinout below shows how you can connect the NXP Precision 9DoF Breakout to any Adafruit Feather development board. The image below uses the Bluefruit nRF52 Feather, which is a great MCU to combine with the NXP Precision 9DoF since the ARM Cortex M4F has a lot of processing power, and Bluetooth Low Energy makes it easy to get the orientation data onto your phone or computer without any cables getting in the way!

But you can also use with an Arduino-compatible. Just make sure you connect Vin to 3-5V, GND to ground, and SCL + SDA to your microcontroller's I2C pin

Required Arduino Libraries

The following libraries can all be installed from the Arduino Library Manager:

Optionally, if you wish to generate orientation data from the raw sensor outputs (recommended!), you will also need the following library:

Installing the Libraries

The libraries mentioned above are already available in the Arduino Library Manager, and should be installed there to facilitate version tracking and easy software updates.

Open up the Library Manager... through the menu Sketch->Include Library->Library Manager... Then type in "Adafruit AHRS", "Adafruit Sensor", etc., to locate and install the libraries

Once you are done installing all 4 libraries, quit and re-start the Arduino IDE.

Testing the Sensors and Library Installation

The Adafruit_FXOS8700 and Adafruit_FXAS21002C repositories both contain a single example called sensorapi which demonstrates how to get raw sensor using the Unified Sensor Library (Adafruit_Sensor):

Both of these examples require Adafruit_Sensor to be installed on your system! If you're getting compilation errors, make sure you have it installed!

Load either of these examples, flash the sketch to your board, and then open the Serial Monitor and if everything is connected correctly you should see something resembling the following output (for the Gyroscope in this example):

Try moving around the board, spinning it or tilting it, to see the data change with motion!

If you see the sensor data shown above, everything is properly setup and connected, you can continue onto the next steps

Calibration (USB)

Calibration is an important part of any orientation system. Any magnetometer has two sources of error called Soft Iron Error and Hard Iron Error.

Soft Iron Error is generally caused by local magnetic interference from specific metals, causing a deviation in magnitude or direction. Soft iron errors will cause what should be 'spherical' data to be deformed into a pill shape. Correcting for soft-iron error is the process of transforming the pill shaped output back into a spherical form using matrix multiplication with the soft-iron coefficients against the raw x/y/z data.

Hard Iron Error is a caused by local magnetic fields, which 'add' to the existing magnetic field, causing a specific change in position relative to the ideal, centered spherical output you would see in a perfect environment with a perfect sensor. This is a static set of values for x/y/z that are applied to 'recenter' the magnetometer output.

Calibration should always be done in the final environment and project setup (enclosure, etc.) where the sensor will be used, since much of the calibration process involves compensating out local environmental variables!

Generating Calibration Data

To determine the soft iron and hard iron error coefficients for your specific sensors and environment using a USB cable, you can make use of the MotionCal app from PJRC.

Download and run the appropriate binary for your operating system, and place it somewhere convenient.

When you run the app, by default you will see something like this:

Next, with your development board and the NXP Precision 9DoF connected, load the ahrs_calibration_usb sketch from Adafruit_AHRS (source code on Github):

You should see something resembling the following code:

Make sure that you have the correct sensor target selected via the AHRS_VARIANT macro, which should be set as shown in the code below:

Download: file
// Define your target sensor(s) here based on the list above!
// #define AHRS_VARIANT    ST_LSM303DLHC_L3GD20
#define AHRS_VARIANT   NXP_FXOS8700_FXAS21002

Build and flash the sketch, and then without opening the Serial Monitor go back to the MotionCal app.

In MotionCal select the correct serial port from the drop-down list in the top-left-hand corner:

Once you are connected, start rotating the orientation sensors, and red dots will start to show up on the screen, and the soft iron error (Magnetic Mapping) and hard iron error (Magnetic Offset) will start to populate themselves:

Once you have a reasonably complete sphere (check the error percentages on the bottom of the screen!), make note of the Magnetic field values on the right-hand side:

Make Note of the Compensation Coefficients

The values generated above represent the coefficients that you will need to apply when running the ahrs_fusion_usb sketch (code on Github).

Note these values down (save a screenshot, for example!), and then plug them into ahrs_fusion_usb using the following setup (the values below are taken from the screenshot above):

Download: file
// Offsets applied to raw x/y/z mag values
float mag_offsets[3]            = { -2.20F, -5.53F, -26.34F };

// Soft iron error compensation matrix
float mag_softiron_matrix[3][3] = { {  0.934,  0.005,  0.013 },
                                    {  0.005,  0.948,  0.012 },
                                    {  0.013,  0.012,  1.129 } };

float mag_field_strength        = 48.41F;

// Offsets applied to compensate for gyro zero-drift error for x/y/z
float gyro_zero_offsets[3]      = { 0.0F, 0.0F, 0.0F };

Orientation Test (USB)

The Adafruit_AHRS repository contains everything you need to run a sensor fusion algorithm and get orientation data out of the NXP Precision 9DoF Breakout.

Generating Orientation Data

Before you can view or work with orientation, you first need to run the raw sensor output through something called a sensor fusion algorithm. As the name implies, this takes the output from a variety of sensors, and merges the results into orientation output, typically in Euler angles or Quaternions.

To generate orientation data, load the ahs_fusion_usb sketch (code on Github) in the Arduino IDE:

With this sketch loaded, make sure that you are targeting the right set of sensors, since this sketch can be used with a variety of different sensor models.

Make sure that you have selected NXP_FXOS8700_FXAS21002 as the AHRS_VARIANT macro:

Download: file
// Define your target sensor(s) here based on the list above!
// #define AHRS_VARIANT    ST_LSM303DLHC_L3GD20
#define AHRS_VARIANT   NXP_FXOS8700_FXAS21002

Compiling your sketch should produce output similar to this, though the final file size will vary depending on the platform you are compiled against:

You can test the output of this sketch by opening the Serial Monitor, where you should see some orientation output in Euler Angles by default:

Visualizing the Orientation Data

Next, you can visualize the orientation data if you want using an optional Processing sketch called bunnyrotate_ahrs_fusion_usb.pde (source on Github).

You can find the Processing sketch in ~/Documents/Arduino/libraries/Adafruit_AHRS/processing or you can click here to download the entire zip and extract the subdirectory

With the ahrs_fusion_usb sketch running in the background, as describe in the section above, open the bunnyrotate_ahrs_fusion_usb sketch in Processing, and run it.

Make sure that the Arduino Serial Monitor is closed before running the Processing app, or the serial port that provides the orientation data won't be available to Processing!

When you run the sketch, you will see a window pop up with a drop down box on the top section where you can select a serial port.

Select the serial port generated by your development board, and the Processing sketch should start capturing incoming aw orientation data. As the orientation data changes, the bunny on the screen will rotate along with the NXP Precision 9DoF Breakout:

As you rotate the board, the bunny should follow the movement similar to the .gif below:

Python & CircuitPython

It's easy to use the FXOS8700 + FXAS21002C 9DoF sensor with Python and CircuitPython, and the Adafruit CircuitPython FXOS8700 and Adafruit CircuitPython FXAS21002C modules.  These module allows you to easily write Python code that reads the accelerometer, magnetometer, and gyroscope values from the sensors.  Note the advanced sensor fusion algorithm to compute absolute orientation is not currently supported--you can only read the raw sensor accelerometer, magnetometer, and gyroscope values!

You can use this sensor with any CircuitPython microcontroller board or with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.

CircuitPython Microcontroller Wiring

First wire up a 9DoF to your board exactly as shown on the previous pages for Arduino.   Here's an example of wiring a Feather M0 to the sensor with an I2C connection:

  • Board 3V to sensor VIN
  • Board GND to sensor GND
  • Board SCL to sensor SCL
  • Board SDA to sensor SDA

Python Computer Wiring

Since there's dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported

Here's the Raspberry Pi wired with I2C:

  • Pi 3V3 to sensor VIN
  • Pi GND to sensor GND
  • Pi SCL to sensor SCL
  • Pi SDA to sensor SDA

CircuitPython Installation of FXOS8700 + FXAS21002C Library

Next you'll need to install both the Adafruit CircuitPython FXOS8700 and Adafruit CircuitPython FXAS21002C libraries on your CircuitPython board

First make sure you are running the latest version of Adafruit CircuitPython for your board.

Next you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  For example the Circuit Playground Express guide has a great page on how to install the library bundle for both express and non-express boards.

Remember for non-express boards like the Trinket M0, Gemma M0, and Feather/Metro M0 basic you'll need to manually install the necessary libraries from the bundle:

  • adafruit_fxos8700.mpy
  • adafruit_fxas21002c.mpy
  • adafruit_bus_device

Before continuing make sure your board's lib folder or root filesystem has the adafruit_fxos8700.mpy, adafruit_fxas21002c.mpy and adafruit_bus_device files and folders copied over.

Next connect to the board's serial REPL so you are at the CircuitPython >>> prompt.

Python Installation of FXOS8700 + FXAS21002C Library

You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling I2C on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!

Once that's done, from your command line run the following command:

  • sudo pip3 install adafruit-circuitpython-fxos8700
  • sudo pip3 install adafruit-circuitpython-fxas21002c

If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported!

CircuitPython & Python Usage

To demonstrate the usage of the sensor we'll initialize it and read the accelerometer, magnetometer, and gyroscope values from the board's Python REPL.

Run the following code to import the necessary modules and initialize the I2C connection with the sensor:

Download: file
import board
import busio
import adafruit_fxos8700
import adafruit_fxas21002c
i2c = busio.I2C(board.SCL, board.SDA)
fxos = adafruit_fxos8700.FXOS8700(i2c)
fxas = adafruit_fxas21002c.FXAS21002C(i2c)

Now you're ready to read values from the sensors using any of these properties.  For the FXOS8700:

  • accelerometer - A 3-tuple of X, Y, Z axis accelerometer values in meters per second squared.
  • magnetometer - A 3-tuple of X, Y, Z axis magnetometer values in gauss.

And for the FXAS21002C:

  • gyroscope - A 3-tuple of the X, Y, Z axis gyroscope values in radians per second.
Download: file
print('Acceleration (m/s^2): ({0:0.3f},{1:0.3f},{2:0.3f})'.format(*fxos.accelerometer))
print('Magnetometer (uTesla): ({0:0.3f},{1:0.3f},{2:0.3f})'.format(*fxos.magnetometer))
print('Gyroscope (radians/s): ({0:0.3f},{1:0.3f},{2:0.3f})'.format(*fxas.gyroscope))

See the FXOS8700 simpletest.py example for a complete demo of printing the accelerometer and magnetometer every second. Also see the FXAS21002C simpletest.py example for a complete demo of printing the accelerometer and magnetometer every second.  Save this as code.py on the board and examine the REPL output to see the range printed every second.

That's all there is to using the FXOS8700 and FXAS21002C sensors with CircuitPython!

Full Example Code

FXOS8700 test example:

# Simple demo of the FXOS8700 accelerometer and magnetometer.
# Will print the acceleration and magnetometer values every second.
import time

import board
import busio

import adafruit_fxos8700


# Initialize I2C bus and device.
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_fxos8700.FXOS8700(i2c)
# Optionally create the sensor with a different accelerometer range (the
# default is 2G, but you can use 4G or 8G values):
#sensor = adafruit_fxos8700.FXOS8700(i2c, accel_range=adafruit_fxos8700.ACCEL_RANGE_4G)
#sensor = adafruit_fxos8700.FXOS8700(i2c, accel_range=adafruit_fxos8700.ACCEL_RANGE_8G)

# Main loop will read the acceleration and magnetometer values every second
# and print them out.
while True:
    # Read acceleration & magnetometer.
    accel_x, accel_y, accel_z = sensor.accelerometer
    mag_x, mag_y, mag_z = sensor.magnetometer
    # Print values.
    print('Acceleration (m/s^2): ({0:0.3f}, {1:0.3f}, {2:0.3f})'.format(accel_x, accel_y, accel_z))
    print('Magnetometer (uTesla): ({0:0.3f}, {1:0.3f}, {2:0.3f})'.format(mag_x, mag_y, mag_z))
    # Delay for a second.
    time.sleep(1.0)

FXAS21002C test example:

# Simple demo of the FXAS21002C gyroscope.
# Will print the gyroscope values every second.
import time

import board
import busio

import adafruit_fxas21002c


# Initialize I2C bus and device.
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_fxas21002c.FXAS21002C(i2c)
# Optionally create the sensor with a different gyroscope range (the
# default is 250 DPS, but you can use 500, 1000, or 2000 DPS values):
#sensor = adafruit_fxas21002c.FXAS21002C(i2c, gyro_range=adafruit_fxas21002c.GYRO_RANGE_500DPS)
#sensor = adafruit_fxas21002c.FXAS21002C(i2c, gyro_range=adafruit_fxas21002c.GYRO_RANGE_1000DPS)
#sensor = adafruit_fxas21002c.FXAS21002C(i2c, gyro_range=adafruit_fxas21002c.GYRO_RANGE_2000DPS)

# Main loop will read the gyroscope values every second and print them out.
while True:
    # Read gyroscope.
    gyro_x, gyro_y, gyro_z = sensor.gyroscope
    # Print values.
    print('Gyroscope (radians/s): ({0:0.3f},  {1:0.3f},  {2:0.3f})'.format(gyro_x, gyro_y, gyro_z))
    # Delay for a second.
    time.sleep(1.0)

Downloads

This guide was first published on Apr 14, 2017. It was last updated on Apr 14, 2017.