Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino Nano and MPU-9250 Motion Sensor Interface

View and Edit Project In Cirkit DesignerImage of Arduino Nano and MPU-9250 Motion Sensor Interface

Circuit Documentation

Summary

This document provides a detailed overview of a circuit that interfaces an Arduino Nano with an MPU-9250/6500/9255 sensor. The Arduino Nano is used to read data from the MPU sensor and process it. The circuit includes the necessary wiring connections and embedded code to ensure proper communication and functionality.

Component List

Arduino Nano

MPU-9250/6500/9255

Wiring Details

Arduino Nano

MPU-9250/6500/9255

Code Documentation

/*
 * Arduino Sketch to interface with MPU-9250/6500/9255
 * This code reads the WHO_AM_I register of the MPU-9250/6500/9255 to confirm
 * hardware setup and basic functionality. The WHO_AM_I register should return
 * the correct device ID for the MPU-9250/6500/9255.
 * Additional functions include delay_ms, get_ms, and log for enhanced
 * functionality.
 * The code also integrates sensor data retrieval APIs for accelerometer,
 * gyroscope, compass, quaternion, euler angles, rotation matrix, heading,
 * and linear acceleration.
 * The code initializes orientation matrices for gyro and compass sensors.
 * The MPU device has one interrupt output pin. The interrupt can be programmed
 * to be generated either at FIFO output rate or DMP generated.
 * The MPU-9150, MPU-6050, MPU-9250, and MPU-6500 all feature an embedded
 * Digital Motion Processorâ„¢ (DMP) hardware accelerator engine. The DMP,
 * together with an embedded FIFO, offloads high-frequency motion algorithm
 * computation from the host application processor, reducing interrupts and
 * host MIPS to improve overall system performance.
 * This code also includes DMP initialization, loading the DMP firmware,
 * setting the FIFO rate, and enabling the DMP state.
 * DMP features can be dynamically enabled and disabled by setting the mask.
 * The code also reads DMP FIFO output when specific features are enabled.
 * This code includes a hardware self-test for the MPU-9250/6500/9255.
 * The self-test and factory calibration are bundled together to calculate
 * sensor offsets through the normal self-test routine.
 * The API returns the status of each axis of the sensor and the accel and
 * gyro bias for calibration.
 * This code also compensates for magnetometer distortions.
 */

#include <Wire.h>

#define MPU9250_ADDRESS 0x68
#define WHO_AM_I 0x75

void delay_ms(unsigned long ms) {
  delay(ms);
}

unsigned long get_ms() {
  return millis();
}

void log(const char* message) {
  Serial.println(message);
}

struct platform_data_s {
  signed char orientation[9];
};

static struct platform_data_s gyro_pdata = {
  .orientation = {0, -1, 0,
                  1, 0, 0,
                  0, 0, 1}
};

static struct platform_data_s compass_pdata = {
#ifdef MPU9150_IS_ACTUALLY_AN_MPU6050_WITH_AK8975_ON_SECONDARY
  .orientation = {1, 0, 0,
                  0, -1, 0,
                  0, 0, -1}
#else
  .orientation = {0, 1, 0,
                  1, 0, 0,
                  0, 0, -1}
#endif
};

void setup() {
  Serial.begin(9600);
  Wire.begin();
  pinMode(10, OUTPUT); // NCS pin
  pinMode(2, INPUT); // INT pin
  digitalWrite(10, HIGH); // Disable NCS
  delay(100);
  log("Starting MPU-9250/6500/9255 WHO_AM_I check...");
  Wire.beginTransmission(MPU9250_ADDRESS);
  Wire.write(WHO_AM_I);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU9250_ADDRESS, 1);
  if (Wire.available()) {
    uint8_t whoAmI = Wire.read();
    Serial.print("WHO_AM_I register: 0x");
    Serial.println(whoAmI, HEX);
    if (whoAmI == 0x71 || whoAmI == 0x73 || whoAmI == 0x68) {
      log("MPU-9250/6500/9255 detected.");
      if (dmp_load_motion_driver_firmware() == 0) {
        log("DMP firmware loaded.");
        if (dmp_set_fifo_rate(100) == 0) {
          log("FIFO rate set.");
          if (mpu_set_dmp_state(1) == 0) {
            log("DMP enabled.");
            short accel_bias[3], gyro_bias[3];
            int result = mpu_run_self_test(accel_bias, gyro_bias, 1);
            if (result == 0x07) {
              log("Self-test and factory calibration passed.");
            } else {
              log("Self-test and factory calibration failed.");
            }
          } else {
            log("Failed to enable DMP.");
          }
        } else {
          log("Failed to set FIFO rate.");
        }
      } else {
        log("Failed to load DMP firmware.");
      }
    } else {
      log("Unknown device detected.");
    }
  } else {
    log("Failed to read WHO_AM_I register.");
  }
}

void loop() {
  short gyro[3], accel[3];
  long quat[4];
  unsigned long timestamp;
  short sensors;
  unsigned char more;

  if (dmp_read_fifo(gyro, accel, quat, &timestamp, &sensors, &more) == 0) {
    if (sensors & INV_XYZ_GYRO) {
      Serial.print("Gyro: ");
      Serial.print(gyro[0]);
      Serial.print(", ");
      Serial.print(gyro[1]);
      Serial.print(", ");
      Serial.println(gyro[2]);
    }
    if (sensors & INV_XYZ_ACCEL) {
      Serial.print("Accel: ");
      Serial.print(accel[0]);
      Serial.print(", ");
      Serial.print(accel[1]);
      Serial.print(", ");
      Serial.println(accel[2]);
    }
    if (sensors & INV_WXYZ_QUAT) {
      Serial.print("Quat: ");
      Serial.print(quat[0]);
      Serial.print(", ");
      Serial.print(quat[1]);
      Serial.print(", ");
      Serial.print(quat[2]);
      Serial.print(", ");
      Serial.println(quat[3]);
    }
  }
  delay(1000); // Delay for readability
}

int dmp_enable_feature(unsigned short mask) {
  #include <SparkFunMPU9250-DMP.h>

#define SerialPort SerialUSB

MPU9250_DMP imu;

unsigned long stepCount = 0;
unsigned long stepTime = 0;
unsigned long lastStepCount = 0;

const signed char orientationMatrix[9] = {
  1, 0, 0,
  0, 1, 0,
  0, 0, 1
};
unsigned char lastOrient = 0;

void setup() 
{
  Serial