Skip to content

9-Axis LSM9DS1 Sensor Wireling Tutorial

TinyCircuits 9-Axis Sensor Wireling product photo

If you are looking to do a project with an inertial motion sensor, look no further than this 9-Axis sensor! The LSM9DS1 features 3 acceleration channels, 3 angular rate channels, and 3 magnetic field channels. This array of channels allows users to create very sophisticated motion applications. 9-Axis sensors are popular in virtual reality experiences for their excellent tracking of motion. This tutorial will teach you the basics on how to read values from this sensor.

The LSM9DS1 has a linear acceleration full scale of ±2g/±4g/±8/±16 g, a magnetic field full scale of ±4/±8/±12/±16 gauss and an angular rate of ±245/±500/±2000 dps.

Technical Details ST LSM9DS1 9-Axis DOF Specs
  • 3 acceleration channels, 3 angular rate channels, 3 magnetic field channels
  • ±2/±4/±8/±16 g linear acceleration full scale
  • ±4/±8/±12/±16 gauss magnetic full scale
  • ±245/±500/±2000 dps angular rate full scale
  • 16-bit data output
  • “Always-on” eco power mode down to 1.9 mA
  • Embedded temperature sensor
  • Embedded FIFO
  • Position and motion detection functions
  • Click/double-click recognition
TinyDuino Power Requirements
  • Voltage: 3.0V - 5.5V 
  • Current: 4.6mA (Normal Mode).  Due to the low current, this board can be run using the TinyDuino coin cell option
Pins Used
  • A5/SCL - I²C Serial Clock line
  • A4/SDA - I²C Serial Data line
  • 10mm x 10mm (.394 inches x .394 inches)
  • Max Height (from lower bottom of Wireling to upper top Wireling Connector): 3.70mm (0.15 inches)
  • Weight: 1 gram (.04 ounces)


To interface with any TinyCircuits Arduino board, you will need the Arduino IDE and a Micro USB Cable

There are multiple processor/adapter combinations that can be used with Wirelings. Use the following table to find the combination that works for you.

Processor Adapter
*TinyDuino and USB TinyShield Wireling Adapter TinyShield
*TinyZero Wireling Adapter TinyShield
*TinyScreen+ Wireling Adapter TinyShield
WirelingZero N/A
*RobotZero N/A
Arduino Wireling Arduino Shield
Raspberry Pi Wireling Pi Hat

* These processors have a 32-pin connector and can have multiple Wireling Adapter TinyShields stacked to increase the number of Wireling ports up to a maximum of 32 total Wireling ports.

In order to interface with Wirelings, you'll need the appropriate number of Wireling Cables and the Wireling.h Library (You can download this from GitHub as linked, or from the Library Manager in the Arduino IDE).

You will also need the 9-Axis Wireling and the included example Arduino sketch.

Wireling Code
Port 0

Hardware Assembly

Depending on the development system you choose, you will need to put together a TinyDuino stack using the 32-pin tan connectors, or you will just need to plug in your Wireling to Port 0 using a Wireling Cable. (You can change this port in the included Arduino Sketch using the Wireling.selectPort() function)

NOTE: Be mindful when inserting Wireling Cables - the connector pins inside the 5-pin connectors on Wirelings can be bent when cables are inserted at an angle.

TinyCircuits 9-Axis Sensor Wireling assembly photo

Software Setup

If you have not already done so, download the 9-Axis Wireling Example Sketch and open it in the Arduino IDE. All the necessary files for the program are included in the zipped folder.

Make the correct Tools selections for your development board. If unsure, you can double check the Help page that mentions the Tools selections needed for any TinyCircuits processor.

Upload Program

Once you have the correct Tools selections, upload the program to your processor!

 * LSM9SD1 9-Axis Wireling Example:
 * This code has the ability to print out all available values from the 
 * 9-Axis sensor, but some are commented out in this Sketch so as not to 
 * over-crowd the Serial Monitor. This program shows the basic methods 
 * on interfacing with this sensor to retrieve value readings. 
 * Hardware by: TinyCircuits
 * Written by: Ben Rose, Lavérena Wienclaw, & Brandon Farmer for TinyCircuits
 * Initiated: 11/20/2017 
 * Updated: 12/06/2019

#include <Wire.h>            // For I2C connection
#include <Wireling.h>        // For Wireling Interfacing

// For the communication with the LSM9DS1
#include "RTIMUSettings.h"    
#include "RTIMU.h"
#include "RTFusionRTQF.h"

#include <EEPROM.h>

RTIMU *imu;                         // the IMU object
RTFusionRTQF fusion;                // the fusion object
RTIMUSettings settings;             // the settings object
int DISPLAY_INTERVAL = 300;         // interval between pose displays

// Global variables to retrieve, store, and schedule readings from the sensor
unsigned long lastDisplay;
unsigned long lastRate;
int sampleCount;
RTVector3 accelData;
RTVector3 gyroData;
RTVector3 compassData;
RTVector3 fusionData; 

// Make Serial Monitor compatible for all TinyCircuits processors
#if defined(ARDUINO_ARCH_AVR)
  #define SerialMonitorInterface Serial
#elif defined(ARDUINO_ARCH_SAMD)
  #define SerialMonitorInterface SerialUSB

void setup() {
  int errcode;
  while (!SerialMonitorInterface);
  Wire.begin(); // Begin I2C communication

  // Initialize Wireling
  Wireling.selectPort(0); //9-Axis Sensor Port, may differ for you

  imu = RTIMU::createIMU(&settings);        // create the imu object

  SerialMonitorInterface.print("ArduinoIMU begin using device "); SerialMonitorInterface.println(imu->IMUName());
  if ((errcode = imu->IMUInit()) < 0) {
    SerialMonitorInterface.print("Failed to init IMU: "); SerialMonitorInterface.println(errcode);

  // See line 69 of RTIMU.h for more info on compass calibaration 
  if (imu->getCalibrationValid())
    SerialMonitorInterface.println("Using compass calibration");
    SerialMonitorInterface.println("No valid compass calibration data");

  lastDisplay = lastRate = millis();
  sampleCount = 0;

  // Slerp power controls the fusion and can be between 0 and 1
  // 0 means that only gyros are used, 1 means that only accels/compass are used
  // In-between gives the fusion mix.

  // use of sensors in the fusion algorithm can be controlled here
  // change any of these to false to disable that sensor

void loop() {
  unsigned long now = millis();
  unsigned long delta;

  if (imu->IMURead()) {     // get the latest data if ready 
    fusion.newIMUData(imu->getGyro(), imu->getAccel(), imu->getCompass(), imu->getTimestamp());
    if ((delta = now - lastRate) >= 1000) {
      SerialMonitorInterface.print("Sample rate: "); SerialMonitorInterface.print(sampleCount);
      if (imu->IMUGyroBiasValid()) {
        SerialMonitorInterface.println(", gyro bias valid");
      else {
        SerialMonitorInterface.println(", calculating gyro bias - don't move IMU!!");

      sampleCount = 0;
      lastRate = now;
    if ((now - lastDisplay) >= DISPLAY_INTERVAL) {
      lastDisplay = now;

      // Get updated readings from sensor and update those values in the 
      // respective RTVector3 object
      accelData = imu->getAccel();
      gyroData = imu->getGyro();
      compassData = imu->getCompass();
      fusionData = fusion.getFusionPose();

      displayAxis("Accel:", accelData.x(), accelData.y(), accelData.z());         

// The following data is commented out for easy reading and you can uncomment it all by 
// highlighting it and using "'Ctrl' + '/'" for windows or "'COMMAND' + '/'" for Mac
//      // Gyro data
//      displayAxis("Gyro:", gyroData.x(), gyroData.y(), gyroData.z());       
//      // Compass data  
//      displayAxis("Mag:", compassData.x(), compassData.y(), compassData.z());    
//      // Fused output
//      displayDegrees("Pose:", fusionData.x(), fusionData.y(), fusionData.z());      

// Prints out pieces of different radian axis data to Serial Monitor
void displayAxis(const char *label, float x, float y, float z) {
  SerialMonitorInterface.print(" x:"); SerialMonitorInterface.print(x);
  SerialMonitorInterface.print(" y:"); SerialMonitorInterface.print(y);
  SerialMonitorInterface.print(" z:"); SerialMonitorInterface.print(z);

// Converts axis data from radians to degrees and prints values to Serial Monitor
void displayDegrees(const char *label, float x, float y, float z) {
  SerialMonitorInterface.print(" x:"); SerialMonitorInterface.print(x * RTMATH_RAD_TO_DEGREE);
  SerialMonitorInterface.print(" y:"); SerialMonitorInterface.print(y * RTMATH_RAD_TO_DEGREE);
  SerialMonitorInterface.print(" z:"); SerialMonitorInterface.print(z * RTMATH_RAD_TO_DEGREE);

There are several different metrics that can be read from the 9-Axis sensor, so for clarity the majority of the data is commented out in the loop(). When you run the program as is, you should see the Accelerometer values from all three axes. This is what the output should look like from the Serial Monitor if you wave the 9-Axis around a few times.

TinyCircuits 9-Axis Sensor Serial Monitor output
Program Executing

You can decide what values are important or unimportant to you, and uncomment other outputs around line 118 in the program.

NOTE: The sensor will need a few seconds after the upload of the program to calibrate a still position in order to print out better readings. The Serial Monitor will print when the gyro bias is valid, so it is best to calibrate the sensor with the help of the Serial Monitor before moving it around.

Beyond the program

The library used for the 9-Axis example are from an RTIMU library made by mrbichel and RPi-Distro, you can find the GitHub library page here if you would like to learn more or contribute.

Now you'll just have to figure out what values you want to read from the 9-Axis and how to make a fun, moving project out of it!


Contact Us

If you have any questions or feedback, feel free to email us or make a post on our forum. Show us what you make by tagging @TinyCircuits on Instagram, Twitter, or Facebook so we can feature it.

Thanks for making with us!