Getting compass direction with the BNO055

Hello, sorry I'm really new to this so if I'm asking something dumb of obvious I apologize. I am trying to get the compass direction on the BNO055. So for example I would like north to give me 0 degrees, south to be 180, east to be 90, and west to be 270. I am able to get kind of close to this by doing the following.

bno.getEvent(&magEvent, Adafruit_BNO055::VECTOR_MAGNETOMETER);

double magX = -1000000, magY = -1000000 , magZ = -1000000;
magX = magEvent.magnetic.x;
magY = magEvent.magnetic.y;
magZ = magEvent.magnetic.z;

double yaw = atan2(magY, magX) * 180/3.14159;

str = String(yaw, 3);


When the sensor is flat this pretty but works for getting the four directions although it gives be it is 0 to 180 to -180 back to 0. The real issue is that when I change the pitch of my sensor I get the compass angle changing and I have no idea why. Any links to examples for a basic compass like I am referring to would be great or ideas on who to fix my code.
Thank you.

The formula you quote works only when the magnetometer is properly calibrated, and level. Excellent tutorial on calibrating magnetometers.

For tilt compensation, you need to use the accelerometer as well. Use your favorite search engine and the phrase "tilt compensated compass" to find several documents describing how to do that. Or use Pololu's compass sensor and code.

Of course you can use the BNO055 in full 3D orientation mode and just print the yaw angle (after compensating for your magnetic declination), but it doesn't work very well, because the magnetometer calibration is so poorly done.

Note: use of Strings on standard Arduinos is not recommended, as they cause memory problems and program crashes.

Hi, don't be disheartened. I got decent results with this approach:

  • mount the compass as far away from electric current, servos or engines as you can
  • calibrate once and save the calibration to eeprom (adafruit sensor libaryr shows how to store offsets) - this is important to not have to do the accelerometer calibration again and again- - load calibration offsets from eeprom and use the COMPASS mode (eg. from the adafruit libraries - its number 9) in your sketch

In my experience the automatic magnetometer calibration is good enough to give you the yaw as an euler angle even with engines running and changing the magnetic field this way. Calibration for magnetometer and accelerometer and system overall might go down to 0 only if you tilt the device (pitch, roll) above 30 degrees aggressively or if you come into a strong magnetic field.

Worked nicely for my rc boat on water - might not be applicable to other use cases.


  • calibrate once and save the calibration to eeprom (adafruit sensor libaryr shows how to store offsets) - this is important to not have to do the accelerometer calibration again and again- [/quote]

How is saving the calibration possible? Because I found the following note on Adafruit's website:

Once the device is calibrated, the calibration data will be kept until the BNO is powered off.

The BNO doesn't contain any internal EEPROM, though, so you will need to perform a new calibration every time the device starts up, or manually restore previous calibration values yourself.

Device Calibration | Adafruit BNO055 Absolute Orientation Sensor | Adafruit Learning System

Use the Arduino eeprom to save the calibration results.

Calibration results are good for the position those results were take at. Say you calibrate the magnetometer whiles sitting in a car. After calibration, you walk away from the car, calibration no longer valid.

Get several bno’s in a solid fixed position, read the magnetometer readings for each sensor and record the readings. Use the 2 sensors that match the closest, no calibration.

Mount the sensors so that each magnetometer axis is 180 degree out of phase with the corresponding axis. You’ll end up mounting one on top and the other on the bottom of a PCB. Now you can sum the readings together for a self calibrated reading that is valid when the magnetometers are moved.