Categories
Electronics Rocketry

GY-87 HMC5883L Fix

Wow what a headache! I’m going to type this up here so that anyone with the same problem can hopefully find this post and fix it like I did. A quick recap first: I purchased a 9-axis breakout board for my rocket flight computer. The board comes with an MPU6050 IMU (accelerometer and gyroscope), a HMC5883L compass, and a BMP180 barometer. When it arrived, I noticed the compass was misbehaving. It was reachable on the I2C bus but was not outputting any heading data. I figured it’s internal MEMS device was busted and placed an order for a replacement.

GY-87 Breakout Board. Contains MPU6050 (top-right), HMC5883L (bottom-right), and BMP180 (bottom-left) as well as a 3.3v regulator. A nice all-in-one IMU board once you get past it’s one quirk!

The replacement GY-87 came and it too had a broken HMC5883L. This seemed sketchy to me and I did some digging. It turns out that the MPU6050 has a second I2C bus that is specifically for connecting to a compass, and in the case of the GY-87 breakout board, the HMC5883L is connected through the MPU6050 on it’s auxiliary I2C bus rather than simply being connected on the main I2C bus.

The MPU6050 has a secondary I2C bus on which it acts as master, and the HMC588L is the slave. This bus is internally connected to the main I2C bus ONLY if the pass-through mode is enabled for the MPU6050.

When the HMC5883L is connected on the AUX bus of the MPU6050, it will behave in one of two modes.

From the MPU6050 Datasheet

The confusing part of all of this is that even when in master mode, it seems to behave as a partial pass-through, allowing you to configure the HMC5883L but not read the magnetometer. This is also the default mode, so if you don’t realize this is the case you’ll get stuck believing that the magnetometer is busted, since it’ll be responsive to commands but have no useful heading data.

The magic fix for all this if you are using the standard MPU6050 Arduino library is to enable the pass-through mode using the following line of code during initialization:
accelgyro.setI2CBypassEnabled(true);

Note that you still need to initialize both the MPU6050 AND the HMC5883L as if they were both on the master I2C bus even though the HMC is on the auxiliary bus.

Once you do this, everything is sunshine and rainbows and behaves exactly as expected.

I’ve added my initialization code for this breakout board in case you want to use it too:

#include "I2Cdev.h"
#include "MPU6050.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
BMP180I2C bmp180(0x77);
MPU6050 accelgyro;

void setup() {
  Wire.begin();
  mag.begin();
  bmp180.begin();
  accelgyro.initialize();
  accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
  accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
  accelgyro.setI2CBypassEnabled(true);
}

Link to GY-87 on Amazon if you want to buy one: https://www.amazon.com/gp/product/B098JN14XV/ref=ox_sc_saved_title_2?smid=A39S0U3UP1U7UG&psc=1

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.