Skip to the content.

MPU6050 Example with Arduino

TL;DR

This guide provides an example of how to use the MPU6050 accelerometer and gyroscope with Arduino, using PlatformIO for development. It includes instructions for connecting the MPU6050 to Arduino, setting up PlatformIO, handling common permission issues, and reading data from the sensor.

PIN Connections

Arduino            MPU6050
-------            -------
3.3V    ---------->   VCC
GND     ---------->   GND
SCL     ---------->   SCL
SDA     ---------->   SDA

Checking Arduino Connection Port

  1. Check USB devices using lsusb, where CH340 should appear, indicating the Arduino.
  2. Verify the port using ls /dev/tty*, which should show something like ttyUSB0 or ttyUSB1.
  3. If you receive a permission error for /dev/ttyUSB0, follow these steps:

    • Add user to dialout group:

      sudo usermod -aG dialout $USER
      
    • Check connected port:

      sudo dmesg | grep tty
      
    • Check and fix permissions (if necessary):

      ls -l /dev/ttyUSB0
      sudo chmod a+rw /dev/ttyUSB0
      

Setting Up PlatformIO for Arduino

  1. Install PlatformIO from the VSCode extensions tab.
  2. Create a new project:

    • Click New Project in PIO Home under Quick Access.
    • Name the project (e.g., mpu6050).
    • Select Arduino Uno as the board and Arduino as the framework.
    • Set a location for the project, e.g., /home/$USER/PlatformIO/mpu6050/.
  3. Code Setup:

    PlatformIO projects use .cpp files instead of Arduino’s .ino files.

    Example src/main.cpp file:

    #include <Arduino.h>
    
    int counter = 0;
    
    void setup() {
      Serial.begin(9600);
    }
    
    void loop() {
      counter++;
      Serial.println(counter);
      delay(1000);
    }
    
  4. Build and Upload:
    • Click Build ( icon).
    • Click Upload ( icon).

Resolving udev Permission Issues for PlatformIO

  1. Install PlatformIO’s udev rules:

    sudo curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/refs/heads/develop/platformio/assets/system/99-platformio-udev.rules -o /etc/udev/rules.d/99-platformio-udev.rules
    
  2. Restart udev:

    sudo service udev restart
    

MPU6050 Data Reading Example

  1. Install the Adafruit MPU6050 library from PlatformIO:

    • Go to Libraries in PIO Home and search for “MPU6050”.
  2. Project Configuration (platformio.ini):

    [env:uno]
    platform = atmelavr
    board = uno
    framework = arduino
    monitor_speed = 115200
    lib_deps = adafruit/Adafruit MPU6050@^2.2.6
    
  3. MPU6050 Code Example:

    // Arduino            MPU6050
    // -------            -------
    // 3.3V    ---------->   VCC
    // GND     ---------->   GND
    // SCL     ---------->   SCL
    // SDA     ---------->   SDA
    
    #include <Arduino.h>
    
    // Basic demo for accelerometer readings from Adafruit MPU6050
    
    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>
    #include <Wire.h>
    
    Adafruit_MPU6050 mpu;
    
    void setup(void)
    {
      Serial.begin(115200);
      while (!Serial)
        delay(10); // will pause Zero, Leonardo, etc until serial console opens
    
      Serial.println("Adafruit MPU6050 test!");
    
      // Try to initialize!
      if (!mpu.begin())
      {
        Serial.println("Failed to find MPU6050 chip");
        while (1)
        {
          delay(10);
        }
      }
      Serial.println("MPU6050 Found!");
    
      mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
      Serial.print("Accelerometer range set to: ");
      switch (mpu.getAccelerometerRange())
      {
      case MPU6050_RANGE_2_G:
        Serial.println("+-2G");
        break;
      case MPU6050_RANGE_4_G:
        Serial.println("+-4G");
        break;
      case MPU6050_RANGE_8_G:
        Serial.println("+-8G");
        break;
      case MPU6050_RANGE_16_G:
        Serial.println("+-16G");
        break;
      }
      mpu.setGyroRange(MPU6050_RANGE_500_DEG);
      Serial.print("Gyro range set to: ");
      switch (mpu.getGyroRange())
      {
      case MPU6050_RANGE_250_DEG:
        Serial.println("+- 250 deg/s");
        break;
      case MPU6050_RANGE_500_DEG:
        Serial.println("+- 500 deg/s");
        break;
      case MPU6050_RANGE_1000_DEG:
        Serial.println("+- 1000 deg/s");
        break;
      case MPU6050_RANGE_2000_DEG:
        Serial.println("+- 2000 deg/s");
        break;
      }
    
      mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
      Serial.print("Filter bandwidth set to: ");
      switch (mpu.getFilterBandwidth())
      {
      case MPU6050_BAND_260_HZ:
        Serial.println("260 Hz");
        break;
      case MPU6050_BAND_184_HZ:
        Serial.println("184 Hz");
        break;
      case MPU6050_BAND_94_HZ:
        Serial.println("94 Hz");
        break;
      case MPU6050_BAND_44_HZ:
        Serial.println("44 Hz");
        break;
      case MPU6050_BAND_21_HZ:
        Serial.println("21 Hz");
        break;
      case MPU6050_BAND_10_HZ:
        Serial.println("10 Hz");
        break;
      case MPU6050_BAND_5_HZ:
        Serial.println("5 Hz");
        break;
      }
    
      Serial.println("");
      delay(100);
    }
    
    void loop()
    {
    
      /* Get new sensor events with the readings */
      sensors_event_t a, g, temp;
      mpu.getEvent(&a, &g, &temp);
    
      /* Print out the values */
      Serial.print("Acceleration X: ");
      Serial.print(a.acceleration.x);
      Serial.print(", Y: ");
      Serial.print(a.acceleration.y);
      Serial.print(", Z: ");
      Serial.print(a.acceleration.z);
      Serial.print(" m/s^2");
    
      Serial.print(" Rotation X: ");
      Serial.print(g.gyro.x);
      Serial.print(", Y: ");
      Serial.print(g.gyro.y);
      Serial.print(", Z: ");
      Serial.print(g.gyro.z);
      Serial.print(" rad/s");
    
      Serial.print("Temperature: ");
      Serial.print(temp.temperature);
      Serial.println(" degC");
    
      delay(100);
    }
    

Earthquake Detection Example

To detect rapid acceleration changes that might indicate an earthquake, you can modify the loop to detect large spikes in acceleration:

// Arduino            MPU6050
// -------            -------
// 3.3V    ---------->   VCC
// GND     ---------->   GND
// SCL     ---------->   SCL
// SDA     ---------->   SDA

#include <Arduino.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

// Settings for earthquake detection
const float gravitationalAccel = 9.80665; // Gravitational acceleration (m/s²)
float previousNetAccel = 0;               // Previous net acceleration value
float accelThreshold = 0.85;              // Threshold value (m/s²)
unsigned long durationThreshold = 500;    // Threshold for earthquake duration (ms)

// Settings for running variables
float readingSensitivity = 0.05; // Reading sensitivity (m/s²)
unsigned long startTime = 0;
int loopDelay = 200; // Loop delay (ms)

void setup()
{
  Serial.begin(115200);
  Wire.begin();

  // Initialize the MPU6050 sensor
  if (!mpu.begin())
  {
    Serial.println("MPU6050 connection failed!");
    while (1)
      ;
  }

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G); // Set the accelerometer range
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);      // Set the gyro range
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);   // Set the filter bandwidth

  Serial.println("MPU6050 ready, starting to read data...");
}

void checkEarthquake()
{
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  // Calculate total acceleration
  float totalAccel = sqrt(pow(a.acceleration.x, 2) + pow(a.acceleration.y, 2) + pow(a.acceleration.z, 2));
  float netAccel = abs(totalAccel - gravitationalAccel); // Calculate net acceleration

  // Check if the net acceleration value has changed by more than 5%
  if (abs(netAccel - previousNetAccel) > previousNetAccel * readingSensitivity)
  {
    Serial.print("Net Acceleration: ");
    Serial.print(netAccel);
    Serial.println(" m/s²");
    previousNetAccel = netAccel; // Update previous net acceleration value
  }

  // Earthquake detection
  if (netAccel > accelThreshold)
  {
    if (startTime == 0)
    {
      startTime = millis(); // Set the start time of the earthquake
    }
  }
  else
  {
    startTime = 0; // No movement
  }

  // Detect earthquake if high acceleration is detected for a certain duration
  if (startTime > 0 && millis() - startTime > durationThreshold)
  {
    Serial.println("Earthquake Detected!");
    // Alarm, logging, etc. can be done here
  }
}

void loop()
{
  checkEarthquake(); // Call the earthquake check function

  // Other operations or conditions can be added here
  delay(loopDelay); // Short delay
}

Earthquake Detection Example with MPU6050 and NodeMCU

Project Configuration (platformio.ini)

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
monitor_speed = 115200
lib_deps =
    Adafruit MPU6050
    Adafruit Unified Sensor
// NodeMCU (ESP8266)            MPU6050
// -------                      -------
// 3.3V       ------------>       VCC
// GND        ------------>       GND
// D1         ------------>       SCL
// D2         ------------>       SDA

#include <Arduino.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

// Settings for earthquake detection
const float gravitationalAccel = 9.80665; // Gravitational acceleration (m/s²)
float previousNetAccel = 0;               // Previous net acceleration value
float accelThreshold = 0.85;              // Threshold value (m/s²)
unsigned long durationThreshold = 500;    // Threshold for earthquake duration (ms)

// Settings for running variables
float readingSensitivity = 0.05; // Reading sensitivity (m/s²)
unsigned long startTime = 0;
int loopDelay = 200; // Loop delay (ms)

void setup()
{
  Serial.begin(115200);
  Wire.begin();

  // Initialize the MPU6050 sensor
  if (!mpu.begin())
  {
    Serial.println("MPU6050 connection failed!");
    while (1)
      ;
  }

  mpu.setAccelerometerRange(MPU6050_RANGE_2_G); // Set the accelerometer range
  mpu.setGyroRange(MPU6050_RANGE_250_DEG);      // Set the gyro range
  mpu.setFilterBandwidth(MPU6050_BAND_260_HZ);  // Set the filter bandwidth

  Serial.println("MPU6050 ready, starting to read data...");
}

void checkEarthquake()
{
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  // Calculate total acceleration
  float totalAccel = sqrt(pow(a.acceleration.x, 2) + pow(a.acceleration.y, 2) + pow(a.acceleration.z, 2));
  float netAccel = abs(totalAccel - gravitationalAccel); // Calculate net acceleration

  // Check if the net acceleration value has changed by more than 5%
  if (abs(netAccel - previousNetAccel) > previousNetAccel * readingSensitivity)
  {
    Serial.print("Net Acceleration: ");
    Serial.print(netAccel);
    Serial.println(" m/s²");
    previousNetAccel = netAccel; // Update previous net acceleration value
  }

  // Earthquake detection
  if (netAccel > accelThreshold)
  {
    if (startTime == 0)
    {
      startTime = millis(); // Set the start time of the earthquake
    }
  }
  else
  {
    startTime = 0; // No movement
  }

  // Detect earthquake if high acceleration is detected for a certain duration
  if (startTime > 0 && millis() - startTime > durationThreshold)
  {
    Serial.println("Earthquake Detected!");
    // Alarm, logging, etc. can be done here
  }
}

void loop()
{
  checkEarthquake(); // Call the earthquake check function

  // Other operations or conditions can be added here
  delay(loopDelay); // Short delay
}