Interfacing the MPU6050 with Raspberry Pi Pico W in C++

 

In this blog, we will explore how to interface the MPU6050 accelerometer and gyroscope sensor with the Raspberry Pi Pico W using C++. If you are new to setting up the Raspberry Pi Pico W with the C++ SDK, you can refer to my previous blog How to Write Your First C++ Script on the Raspberry Pi Pico W for detailed instructions.

Introduction

The MPU6050 is a versatile sensor that combines a 3-axis gyroscope and a 3-axis accelerometer. In this tutorial, we’ll go through the process of setting up the sensor, configuring it, and reading the data from it. We’ll also cover the necessary configuration of the Raspberry Pi Pico W to communicate with the MPU6050 over the I2C protocol.

— — -

Before we delve into the topic, we invite you to support our ongoing efforts and explore our various platforms dedicated to enhancing your IoT projects:

  • Subscribe to our YouTube Channel: Stay updated with our latest tutorials and project insights by subscribing to our channel at YouTube — Shilleh.
  • Support Us: Your support is invaluable. Consider buying me a coffee at Buy Me A Coffee to help us continue creating quality content.
  • Hire Expert IoT Services: For personalized assistance with your IoT projects, hire me on UpWork.

ShillehTek Website (Exclusive Discounts):

https://shillehtek.com/collections/all

ShillehTekAmazon Store:

ShillehTek Amazon Store — US

ShillehTek Amazon Store — Canada

ShillehTek Amazon Store — Japan

Prerequisites

Wiring Information

Connecting the MPU6050 to the Raspberry Pi Pico W requires four connections: VCC (3.3V), GND, SDA, and SCL. The example here uses I2C port 0, which is assigned to GPIO 4 (SDA) and GPIO 5 (SCL) in software. Power is supplied from the 3.3V pin.

Note: There are many different manufacturers who sell boards with the MPU6050. While they may appear slightly different, they all have at least the same four pins required to power and communicate with the sensor. When wiring up a board that looks different from the one in the diagram, ensure you connect the pins as described.

Steps for Connecting the MPU6050

  1. Connect VCC: Connect the VCC pin of the MPU6050 to the 3.3V pin on the Raspberry Pi Pico.
  2. Connect GND: Connect the GND pin of the MPU6050 to a ground (GND) pin on the Raspberry Pi Pico.
  3. Connect SDA: Connect the SDA pin of the MPU6050 to GPIO 4 (SDA) on the Raspberry Pi Pico.
  4. Connect SCL: Connect the SCL pin of the MPU6050 to GPIO 5 (SCL) on the Raspberry Pi Pico.

CMakeLists.txt File

First, let’s look at the CMakeLists.txt file, which is crucial for building the project.

cmake_minimum_required(VERSION 3.13)

# Include the Pico SDK using the environment variable
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)

project(mpu6050_i2c_example)

# Initialize the Raspberry Pi Pico SDK
pico_sdk_init()

# Create an executable for the project
add_executable(mpu6050_i2c_example
main.cpp
)

# Link the necessary libraries
target_link_libraries(mpu6050_i2c_example pico_stdlib hardware_i2c)

# Enable USB output
pico_enable_stdio_usb(mpu6050_i2c_example 1)
# Disable UART output
pico_enable_stdio_uart(mpu6050_i2c_example 0)

# Create map/bin/hex/uf2 files
pico_add_extra_outputs(mpu6050_i2c_example)

Explanation of CMakeLists.txt

  • pico_sdk_init.cmake: This line includes the Pico SDK, allowing us to use its functionalities.
  • pico_sdk_init(): This initializes the Pico SDK for the project.
  • add_executable: This line specifies the main.cpp file as the source file for the executable.
  • target_link_libraries: This links the necessary libraries (pico_stdlib for standard Pico functions and hardware_i2c for I2C communication).
  • pico_enable_stdio_usb: This enables USB output, allowing us to use USB for serial communication.
  • pico_add_extra_outputs: This generates additional output files such as .uf2, .bin, and .hex files which are useful for flashing the firmware.

main.cpp File

Now, let’s dive into the main.cpp file, which contains the actual code to interface with the MPU6050.

#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include <stdio.h>

// I2C defines
#define I2C_PORT i2c0
#define MPU6050_ADDR 0x68

// MPU6050 register addresses
#define REG_PWR_MGMT_1 0x6B
#define REG_ACCEL_XOUT_H 0x3B
#define REG_GYRO_CONFIG 0x1B
#define REG_ACCEL_CONFIG 0x1C
#define REG_SMPLRT_DIV 0x19
#define WHO_AM_I_REG 0x75

// Sensitivity scale factors for different ranges
#define ACCEL_SCALE_FACTOR_2G 16384.0 // for ±2g
#define ACCEL_SCALE_FACTOR_4G 8192.0 // for ±4g
#define ACCEL_SCALE_FACTOR_8G 4096.0 // for ±8g
#define ACCEL_SCALE_FACTOR_16G 2048.0 // for ±16g

#define GYRO_SCALE_FACTOR_250DPS 131.0 // for ±250 degrees per second
#define GYRO_SCALE_FACTOR_500DPS 65.5 // for ±500 degrees per second
#define GYRO_SCALE_FACTOR_1000DPS 32.8 // for ±1000 degrees per second
#define GYRO_SCALE_FACTOR_2000DPS 16.4 // for ±2000 degrees per second

// Select the desired scale factor
#define ACCEL_SCALE_FACTOR ACCEL_SCALE_FACTOR_4G // Change this to the desired accelerometer range
#define GYRO_SCALE_FACTOR GYRO_SCALE_FACTOR_250DPS // Change this to the desired gyroscope range

// Corresponding configuration values
#define ACCEL_CONFIG_VALUE 0x08 // for ±4g
#define GYRO_CONFIG_VALUE 0x00 // for ±250 degrees per second
#define SAMPLE_RATE_DIV 1 // Sample rate = 1kHz / (1 + 1) = 500Hz

void mpu6050_reset() {
uint8_t reset[] = {REG_PWR_MGMT_1, 0x80};
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, reset, 2, false);
sleep_ms(200);
uint8_t wake[] = {REG_PWR_MGMT_1, 0x00};
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, wake, 2, false);
sleep_ms(200);
}

void mpu6050_configure() {
// Set accelerometer range
uint8_t accel_config[] = {REG_ACCEL_CONFIG, ACCEL_CONFIG_VALUE};
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, accel_config, 2, false);

// Set gyroscope range
uint8_t gyro_config[] = {REG_GYRO_CONFIG, GYRO_CONFIG_VALUE};
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, gyro_config, 2, false);

// Set sample rate
uint8_t sample_rate[] = {REG_SMPLRT_DIV, SAMPLE_RATE_DIV};
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, sample_rate, 2, false);
}

void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) {
uint8_t buffer[14];
uint8_t reg = REG_ACCEL_XOUT_H;
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, &reg, 1, true);
i2c_read_blocking(I2C_PORT, MPU6050_ADDR, buffer, 14, false);

accel[0] = (buffer[0] << 8) | buffer[1];
accel[1] = (buffer[2] << 8) | buffer[3];
accel[2] = (buffer[4] << 8) | buffer[5];
*temp = (buffer[6] << 8) | buffer[7];
gyro[0] = (buffer[8] << 8) | buffer[9];
gyro[1] = (buffer[10] << 8) | buffer[11];
gyro[2] = (buffer[12] << 8) | buffer[13];
}

int main() {
// Initialize chosen serial port
stdio_init_all();

// Initialize I2C
i2c_init(I2C_PORT, 400 * 1000);
gpio_set_function(4, GPIO_FUNC_I2C);
gpio_set_function(5, GPIO_FUNC_I2C);
gpio_pull_up(4);
gpio_pull_up(5);

// Reset and configure MPU6050
mpu6050_reset();
mpu6050_configure();

uint8_t who_am_i = 0;
uint8_t reg = WHO_AM_I_REG;
i2c_write_blocking(I2C_PORT, MPU6050_ADDR, &reg, 1, true);
i2c_read_blocking(I2C_PORT, MPU6050_ADDR, &who_am_i, 1, false);
printf("MPU6050 WHO_AM_I: 0x%02X\n", who_am_i);

if (who_am_i != 0x68) {
printf("MPU6050 not found!\n");
while (1);
}

int16_t accel[3], gyro[3], temp;

while (1) {
mpu6050_read_raw(accel, gyro, &temp);

// Convert raw accelerometer values to g
float accel_g[3];
accel_g[0] = accel[0] / ACCEL_SCALE_FACTOR;
accel_g[1] = accel[1] / ACCEL_SCALE_FACTOR;
accel_g[2] = accel[2] / ACCEL_SCALE_FACTOR;

// Convert raw gyroscope values to degrees per second
float gyro_dps[3];
gyro_dps[0] = gyro[0] / GYRO_SCALE_FACTOR;
gyro_dps[1] = gyro[1] / GYRO_SCALE_FACTOR;
gyro_dps[2] = gyro[2] / GYRO_SCALE_FACTOR;

// Print converted values
printf("aX = %.2f g | aY = %.2f g | aZ = %.2f g | gX = %.2f dps | gY = %.2f dps | gZ = %.2f dps | temp = %.2f°C\n",
accel_g[0], accel_g[1], accel_g[2], gyro_dps[0], gyro_dps[1], gyro_dps[2], temp / 340.00 + 36.53);

sleep_ms(500);
}

return 0;
}

Explanation of main.cpp

Includes and Definitions:

  • We include necessary headers for standard library functions and I2C communication.
  • Define I2C port and MPU6050 I2C address.
  • Define MPU6050 register addresses and scale factors for different ranges.

Sensitivity Scale Factors:

  • Accelerometer:
  • ±2g: 16384 LSB/g
  • ±4g: 8192 LSB/g
  • ±8g: 4096 LSB/g
  • ±16g: 2048 LSB/g
  • Gyroscope:
  • ±250 dps: 131 LSB/dps
  • ±500 dps: 65.5 LSB/dps
  • ±1000 dps: 32.8 LSB/dps
  • ±2000 dps: 16.4 LSB/dps

These scale factors are used to convert the raw sensor readings to physical units. For example, with an accelerometer range of ±4g, a raw reading of 8192 corresponds to 1g.

mpu6050_reset() Function:

  • This function resets the MPU6050 by writing to the power management register. After resetting, it wakes up the device by clearing the sleep bit.

mpu6050_configure() Function:

  • This function configures the accelerometer and gyroscope ranges and sets the sample rate divider. The sample rate is set by writing to the SMPLRT_DIV register. You can change the ACCEL_CONFIG_VALUE and GYRO_CONFIG_VALUE to set different ranges for the accelerometer and gyroscope.

mpu6050_read_raw() Function:

  • This function reads raw accelerometer, gyroscope, and temperature data from the MPU6050. It writes the starting register address and then reads the data from the sensor.

main() Function:

  • Initializes the standard I/O and I2C communication.
  • Calls the reset and configure functions to prepare the MPU6050.
  • Checks the WHO_AM_I register to verify communication with the MPU6050.
  • Continuously reads raw data from the MPU6050, converts it to physical units (g for acceleration and dps for gyroscope), and prints the results.

Conclusion

By following this guide, you have successfully interfaced the MPU6050 sensor with the Raspberry Pi Pico W using C++. You can now read and process accelerometer and gyroscope data for various applications. Adjust the scale factors and sample rates as needed for your specific use case.

For more detailed steps on setting up the C++ SDK for the Raspberry Pi Pico W, refer to my previous blog How to Write Your First C++ Script on the Raspberry Pi Pico W.

Create a free account to access full content.

All access to code and resources on ShillehTek.

Signup Now

Already a member? Sign In

Explore More on Our Blog

Controlling a 5V Laser Diode with Raspberry Pi Pico W

Controlling a 5V Laser Diode with Raspberry Pi Pico W

Learn how to safely control high-power components like a ShillehTek 5V laser diode using the Raspberry Pi Pico W and...

How to Connect and Use the HCSR501 PIR Sensor with a Raspberry Pi Pico/Pico W

How to Connect and Use the HCSR501 PIR Sensor with a Raspberry Pi Pico/Pico W

Learn how to set up the HCSR501 PIR sensor with a Raspberry Pi Pico to detect motion and trigger...

Powering the Raspberry Pi Pico W with the MB102 Power Supply

Powering the Raspberry Pi Pico W with the MB102 Power Supply

Learn how to power your Raspberry Pi Pico W projects easily and flexibly with the MB102 Power Supply Module...

How to Use L298N Motor Driver with Pico W

How to Use L298N Motor Driver with Pico W

Learn how to use the L298N motor driver to control DC motors with the Raspberry Pi Pico W in MicroPython.

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Discover how to set up, code, and activate the LED based on detected sound with the Raspberry Pi...

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

In this tutorial, I’ll guide you through setting up the KY-037 sound sensor with a Raspberry Pi using...

How to Post to Reddit Using Python

How to Post to Reddit Using Python

Post to reddit automatically using a Python script.

How to Create a Time-Lapse Video with a Raspberry Pi Camera

How to Create a Time-Lapse Video with a Raspberry Pi Camera

Learn how to make a timelapse with your Raspberry Pi in Python.

How to Integrate the MPU6050 with the STM32 Blue Pill

How to Integrate the MPU6050 with the STM32 Blue Pill

Learn how to measure acceleration with the STM32 and the MPU6050 in the Arduino IDE.

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

This comprehensive tutorial will guide you through the process of setting up and programming the STM32 Blue Pill...

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.