How to Integrate the MPU6050 with the STM32 Blue Pill

If you’re looking to add motion detection to your projects, the MPU6050 sensor is a great option. When combined with the STM32 Blue Pill, a powerful yet affordable microcontroller, you have a versatile solution for accelerometer and gyroscope-based applications. In this tutorial, we’ll guide you through the process of connecting the MPU6050 to the STM32 Blue Pill, setting up the Arduino environment, reading raw data from the sensor, and applying a simple gyroscope calibration.

Where to Buy Components, Pre-Soldered MPU6050 and STM32:

 ShillehTekMicroElectronics Made Easywww.amazon.com

Be sure to watch part 1 if you have not already. Where we show how to get setup with the board in Arduino! This is crucial to watch if you have not.

— — -

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 

Why Choose the STM32 Blue Pill and MPU6050?

The STM32 Blue Pill is a popular microcontroller for hobbyists and professionals alike due to its low cost, high performance, and extensive community support. Paired with the MPU6050, which provides both accelerometer and gyroscope functionalities, you can easily implement motion detection in a variety of projects such as robotics, drones, and wearable devices. 

Step 1: Hardware Connections

The first step is to connect the MPU6050 to the STM32 Blue Pill. Here’s how to wire them together:

Power Supply:

  • Connect the VCC pin of the MPU6050 to the 3.3V pin on the STM32 Blue Pill.
  • Connect the GND pin of the MPU6050 to the GND pin on the STM32 Blue Pill.

I2C Communication:

  • Connect the SCL pin of the MPU6050 to the PB6 pin on the STM32 Blue Pill (default SCL pin for I2C).
  • Connect the SDA pin of the MPU6050 to the PB7 pin on the STM32 Blue Pill (default SDA pin for I2C).

Step 2: Install the MPU6050 Library:

Go to Sketch > Include Library > Manage Libraries and search for “MPU6050.” Install the library compatible with your setup.

Step 3: Writing the Code

Let’s start with the basic version of the code, which initializes the MPU6050 and reads raw accelerometer and gyroscope data.

Code Without Calibration

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

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

// Initialize MPU6050
Serial.println("Initializing MPU6050...");
mpu.initialize();

// Check if the MPU6050 is connected
if (mpu.testConnection()) {
Serial.println("MPU6050 connection successful");
} else {
Serial.println("MPU6050 connection failed");
while (1); // Halt the program if MPU6050 is not connected
}
}

void loop() {
// Variables to hold the raw data
int16_t ax, ay, az;
int16_t gx, gy, gz;

// Read raw accelerometer and gyroscope data
mpu.getAcceleration(&ax, &ay, &az);
mpu.getRotation(&gx, &gy, &gz);

// Print accelerometer raw values
Serial.print("Accel X: "); Serial.print(ax);
Serial.print(" | Accel Y: "); Serial.print(ay);
Serial.print(" | Accel Z: "); Serial.println(az);

// Print gyroscope raw values
Serial.print("Gyro X: "); Serial.print(gx);
Serial.print(" | Gyro Y: "); Serial.print(gy);
Serial.print(" | Gyro Z: "); Serial.println(gz);

delay(100); // Delay for readability
}

Explanation:

  • Initialization: The MPU6050 is initialized, and a connection test is performed to ensure proper setup.
  • Reading Raw Values: The code reads raw values from both the accelerometer and gyroscope and prints them to the Serial Monitor.

This version of the code is straightforward and works well if you don’t need to correct for any offsets in the gyroscope readings. However, for more accurate data, especially in applications where precise motion tracking is crucial, it’s recommended to apply a simple calibration to the gyroscope. 

Code with Gyro Calibration

Now, let’s modify the code to include a basic calibration for the gyroscope.

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t gyroXOffset = 0, gyroYOffset = 0, gyroZOffset = 0;

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

// Initialize MPU6050
Serial.println("Initializing MPU6050...");
mpu.initialize();

// Check if the MPU6050 is connected
if (mpu.testConnection()) {
Serial.println("MPU6050 connection successful");
} else {
Serial.println("MPU6050 connection failed");
while (1); // Halt the program if MPU6050 is not connected
}

// Calibrate gyroscope
Serial.println("Calibrating gyroscope... Please keep the sensor steady.");
calibrateGyro();
Serial.println("Calibration complete.");
}

void loop() {
// Read raw accelerometer and gyroscope data
mpu.getAcceleration(&ax, &ay, &az);
mpu.getRotation(&gx, &gy, &gz);

// Subtract the gyro offsets from the raw values
gx -= gyroXOffset;
gy -= gyroYOffset;
gz -= gyroZOffset;

// Print accelerometer raw values
Serial.print("Accel X: "); Serial.print(ax);
Serial.print(" | Accel Y: "); Serial.print(ay);
Serial.print(" | Accel Z: "); Serial.println(az);

// Print gyroscope raw values
Serial.print("Gyro X: "); Serial.print(gx);
Serial.print(" | Gyro Y: "); Serial.print(gy);
Serial.print(" | Gyro Z: "); Serial.println(gz);

delay(100); // Delay for readability
}

void calibrateGyro() {
int32_t gyroXSum = 0, gyroYSum = 0, gyroZSum = 0;
const int numReadings = 1000;

for (int i = 0; i < numReadings; i++) {
mpu.getRotation(&gx, &gy, &gz);
gyroXSum += gx;
gyroYSum += gy;
gyroZSum += gz;
delay(3); // Delay to allow for a reasonable calibration time
}

// Calculate the average offsets
gyroXOffset = gyroXSum / numReadings;
gyroYOffset = gyroYSum / numReadings;
gyroZOffset = gyroZSum / numReadings;

Serial.print("Gyro X Offset: "); Serial.println(gyroXOffset);
Serial.print("Gyro Y Offset: "); Serial.println(gyroYOffset);
Serial.print("Gyro Z Offset: "); Serial.println(gyroZOffset);
}

Explanation:

  • Calibration Function: The calibrateGyro() function averages 1000 readings from the gyroscope while the sensor is stationary. These average values (offsets) are then subtracted from the subsequent readings to correct any bias.
  • Applying Offsets: In the loop() function, after reading the gyroscope data, the offsets are subtracted from the raw values to correct them.
  • Output: The calibrated gyroscope values, along with the raw accelerometer values, are printed to the Serial Monitor.

Step 4: Running the Code

Upload either version of the code to your STM32 Blue Pill using the Arduino IDE. After the upload is complete:

  • Open the Serial Monitor from the Arduino IDE (Tools > Serial Monitor).
  • Set the baud rate to 115200.
  • Observe the raw accelerometer and gyroscope values being printed. If using the calibrated version, the gyroscope readings should now be corrected for any static offset.

Conclusion

By following this guide, you’ve successfully integrated the MPU6050 sensor with the STM32 Blue Pill and implemented a simple calibration method for the gyroscope. Whether you’re working on a robotics project, a drone, or any other motion-based application, this setup provides accurate motion detection for a variety of applications.

This tutorial gives you a solid foundation to build upon, and you can further explore by experimenting with different settings or adding additional sensors. If you found this tutorial helpful, be sure to check out our video on the topic and subscribe for more tutorials!

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

Build a Real-Time Azure IoT Sensor Pipeline with Raspberry Pi Pico W + BME280

Build a Real-Time Azure IoT Sensor Pipeline with Raspberry Pi Pico W + BME280

How to send live environmental sensor data to Azure IoT Hub and visualize it in Azure Data Explorer.

How to Connect an Arduino Sensor to ROS 2 on a Raspberry Pi

How to Connect an Arduino Sensor to ROS 2 on a Raspberry Pi

Learn how to connect a BME280 sensor to an Arduino and publish real-time sensor data into ROS...

How to Install ROS 2 Humble on Raspberry Pi (Ubuntu 22.04.5 LTS)

How to Install ROS 2 Humble on Raspberry Pi (Ubuntu 22.04.5 LTS)

Learn how to install ROS 2 Humble on a Raspberry Pi 4B running Ubuntu 22.04.5 LTS. This step-by-step guide walks...

Part 5: Building a Wi-Fi Control Interface for Remote Control Robot

Part 5: Building a Wi-Fi Control Interface for Remote Control Robot

Part 4: Adding Obstacle Detection - Raspberry Pi Pico W Robotics Course

Part 4: Adding Obstacle Detection - Raspberry Pi Pico W Robotics Course

Part 3: Motor Control Programming - Raspberry Pi Pico W Robotics Course

Part 3: Motor Control Programming - Raspberry Pi Pico W Robotics Course

Part 2: Robot Assembly - Raspberry Pi Pico W Robotics Course

Part 2: Robot Assembly - Raspberry Pi Pico W Robotics Course

Build a Wi-Fi-Controlled Obstacle-Avoidance Robot with Raspberry Pi Pico W

Build a Wi-Fi-Controlled Obstacle-Avoidance Robot with Raspberry Pi Pico W

Learn how to build a remote-control robot using the Raspberry Pi Pico W and a few simple hardware components. This...

Simple Guide: Build a Reverse Geolocator with Raspberry Pi Pico W and GPS Module

Simple Guide: Build a Reverse Geolocator with Raspberry Pi Pico W and GPS Module

Reverse Geolocator Tutorial with Raspberry Pi Pico W and GPS Module

Learn how to create a reverse...

LoRa and Raspberry Pi Pico W: Building a Sender-Receiver Communication System

LoRa and Raspberry Pi Pico W: Building a Sender-Receiver Communication System

function toggleAuthorBio() { var bio = document.getElementById('authorBio'); var button = document.querySelector('.toggle-button'); if (bio.style.display === 'none') { bio.style.display = 'block'; button.textContent = '▼ About this Author'; // Using Unicode character directly button.classList.add('expanded'); } else { bio.style.display = 'none'; button.textContent = '▶ About this Author'; // Using Unicode character directly button.classList.remove('expanded'); } }