Maker.io main logo

How to interface an IMU with an ESP8266

2021-03-31 | By Maker.io Staff

An IMU, or inertial measurement unit, can be a useful addition to all sorts of projects. IMUs typically combine accelerometers, gyroscopes, and sometimes magnetometers to measure the angular speed of a physical body. However, translating the readings from such an IMU sensor can be a challenging task. Because of that, this article employs a BNO085 based IMU breakout board. This board converts the values from different sensors and combines them to an easy-to-understand and beginner-friendly value, such as a rotation vector, that describes the orientation of the sensor board in three-dimensional space. This technique is useful for various applications such as flight-controllers, for example, in model aircraft.

Bill of Materials

Product/Where to buy

Connecting the IMU Breakout Board to the ESP8266

This step depends on the IMU board you choose and the requirements of your project. Many IMU breakout modules allow the users to select one of several communication options to interface the sensors with a microcontroller. You can get a heads up on different ways of interfacing sensors with an ESP8266 development board here. In this article, however, I decided to use the I2C bus for communications. This particular module, however, supports other communication options such as SPI and UART.

The following diagram shows how to connect the components for communicating over I2C:

How to interface an IMU with an ESP8266

Note that this device already includes appropriate pull-up resistors on the I2C lines (SDA, SCL), so it isn't necessary to add external ones. Different modules, however, might require external resistors to function as intended. Consult the datasheet of your module if you want to employ a different one in your project.

Furthermore, users can employ the P0 and P1 pins to select the communication mode of the IMU breakout board. If P0 and P1 are pulled low (or left floating), then the board defaults to I2C, which is what I wanted in this case.

It's possible to change the I2C address of the device by pulling the DI pin high in the I2C mode. If the pin is low (or floating), the device listens to address 0x4A. If the DI pin is high, the device will respond to 0x4B.

Testing the IMU

Getting the IMU to work with any ESP8266 based development board can be somewhat troublesome, especially over I2C. That is the reason I chose this setup. I wanted to document a few of my findings while working with the IMU and the ESP8266. For one, the official Adafruit library isn’t quite ideal for this task, as it needs too much memory, which renders it useless on many low-resource development boards. If you don’t want to manually implement the communications protocol of the sensor itself (the BNO085 in this case), we recommend you employ the Sparkfun BNO080 library instead. The BNO085 is backward compatible with the BNO080, and the library works perfectly fine. Here’s a short test script to get you up and running:

Copy Code
// Include the necessary libraries
// Wire handles the I2C communication
// The BNO080 library implements the communication protocol

#include <Wire.h>
#include "SparkFun_BNO080_Arduino_Library.h"

#define WARM_UP_TIME 150
#define IMU_ADDRESS 0x4A

// Create a new IMU object
BNO080 imu;

void setup()
{
  Serial.begin(9600);

  // Make sure to supply the correct pin numbers to the SDA and SCL pins!
  Wire.begin(4, 5);
  Wire.setClockStretchLimit(4000);

  // The ESP8266 seems to be unable to read data from the sensor without the
  // added clock stretch limit and if the sensor didn't have a short
  // 'warm-up' time to initialize itself.
  // Therefore, wait for a few milliseconds
 
  long start_millis = millis();

  Serial.println("Initializing sensor...");

  while(millis() - start_millis < WARM_UP_TIME)
  { }

  Serial.println("Ready!");
 
  Wire.flush();

  // Check if the IMU is available
  if (imu.begin(IMU_ADDRESS, Wire) == false)
  {
	Serial.print("Couldn't find the IMU at address ");
	Serial.println(IMU_ADDRESS);
    
	while(true)
	{ }
  }

  // Increase the I2C data rate to 400kHz
  Wire.setClock(400000);

  // Send requests to the IMU every 50ms
  imu.enableRotationVector(50);
}

void loop()
{
  // Check whether the sensor is ready to transmit data
  // This should happen roughly every 50ms (as defined above)
  if (imu.dataAvailable())
  {
	float i = imu.getQuatI();
	float j = imu.getQuatJ();
	float k = imu.getQuatK();
	float real = imu.getQuatReal();
	float acc = imu.getQuatRadianAccuracy();

	Serial.print(i, 2);
	Serial.print(",");
	Serial.print(j, 2);
	Serial.print(",");
	Serial.print(k, 2);
	Serial.print(",");
	Serial.print(real, 2);
	Serial.print(",");
	Serial.print(acc, 2);
	Serial.print(",");

	Serial.println();
  }
}

You can see the aforementioned warm-up time of the sensor in the setup method of the script. For that, the sketch acquires the time since it started in milliseconds, and then it waits in a while loop until the current time surpasses the warm-up time defined at the beginning of the script. Make sure to supply the correct SDA and SCL pins to the Wire library in the setup method. Then, the setup method sets custom values to the clock and clock stretch limit in the Wire library to enable communication between the ESP8266 and the IMU. Last but not least the start method enables the rotation vector readout on the IMU, and it requests data every 50 milliseconds. The loop method itself does nothing particularly interesting. It just checks whether the sensor is ready to deliver a result, and the loop method then receives the values from the sensor. In this example, the ESP8266 reads the rotation vector. You can visualize the results with the serial plotter of the Arduino IDE:

How to interface an IMU with an ESP8266

Summary

An IMU can be a useful addition in a wide variety of projects ranging from flight controllers for RC planes to security devices, for example, tilt-detectors. Typically, IMU breakout boards offer a good range of different communication methods they support. This makes it easy to choose the right one for the microcontroller in your project or according to your project requirements. This particular IMU board was a little more difficult to use with the ESP8266, as initially expected. The official Adafruit library didn’t seem to work very well for me. Instead, I employed the compatible Sparkfun BNO080 library for Arduino. This library, in conjunction with a short warm-up time for the sensor, made the IMU a useful addition to my portfolio of sensors.

制造商零件编号 2821
ESP8266 FEATHER HUZZAH LOOSE HDR
Adafruit Industries LLC
¥121.69
Details
制造商零件编号 4754
ADAFRUIT 9-DOF ORIENTATION IMU F
Adafruit Industries LLC
¥210.22
Details
制造商零件编号 64
BREADBOARD TERM STRIP 3.40X2.20"
Adafruit Industries LLC
¥41.71
Details
制造商零件编号 759
JUMPER WIRE M/M 2.950" 1PC
Adafruit Industries LLC
¥32.15
Details
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum