Built-in project · Arduino Mega 2560 R3

Tilt compass on an Arduino Mega

An MPU-9250 on a Mega reads which way is down and which way is north: the accelerometer and the AK8963 compass through the bypass. The whole build, an Arduino Mega and 1 more part, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate Runs in your browser. Free, and no account needed.

Tilt compass · Arduino Mega 2560 R3live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Mega 2560 R3
// Tilt compass: an MPU-9250 reads which way is down and which way is north,
// with asukiaaa's MPU9250 library, on a Mega: the library's floating point
// and atan2() take more flash than an Uno example is allowed.
//
//   MPU-9250  SDA -> SDA, SCL -> SCL, VCC -> 5 V, GND -> GND
//
// Inside the chip are two devices. The accelerometer and gyroscope answer
// at 0x68, like an MPU6050. The AK8963 magnetometer sits behind them, and
// beginMag() sets the bypass bit so it answers at 0x0C on the same two
// wires. The accelerometer gives the tilt; the magnetometer gives the
// Earth's field, whose horizontal part points north.
//
// magHorizDirection() is atan2 of the magnetometer's X and Y: the angle of
// north from the chip's own axes, which only means a compass bearing while
// the board is held level.
//
// Things to try. Drag the heading slider and watch the direction follow.
// Then tip the board: the tilt changes and so does the direction, because
// the field also points down into the ground. A tilt-compensated compass
// uses the accelerometer to undo that.

#include <Wire.h>
#include <MPU9250_asukiaaa.h>

MPU9250_asukiaaa imu;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  imu.setWire(&Wire);
  uint8_t id = 0;
  imu.readId(&id);
  Serial.print("WHO_AM_I 0x");
  Serial.println(id, HEX);
  imu.beginAccel(ACC_FULL_SCALE_2_G);
  imu.beginMag();
}

void loop() {
  if (imu.accelUpdate() == 0) {
    float pitch = atan2(-imu.accelX(), imu.accelZ()) * 180.0 / PI;
    float roll = atan2(imu.accelY(), imu.accelZ()) * 180.0 / PI;
    Serial.print("pitch ");
    Serial.print((int)lround(pitch));
    Serial.print("  roll ");
    Serial.print((int)lround(roll));
  }
  if (imu.magUpdate() == 0) {
    Serial.print("  direction ");
    Serial.print((int)lround(imu.magHorizDirection()));
  }
  Serial.println();
  delay(500);
}

Parts list

3 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

4 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Arduino Mega 2560 R3 pin SCL; Nine-axis IMU, MPU-9250 pin SCL
  • Arduino Mega 2560 R3 pin SDA; Nine-axis IMU, MPU-9250 pin SDA
  • Ground: Arduino Mega 2560 R3 pin GND; Nine-axis IMU, MPU-9250 pin GND
  • 5 V: Nine-axis IMU, MPU-9250 pin VCC

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.