Overview
This guide is on utilizing the powerful MPU6050 MEMS module with the versatile Raspberry Pi Pico with MicroPython. In this guide, we will delve into the world of motion sensing and measurement by learning how to obtain accelerometer, gyroscope, and temperature values using the MicroPython firmware. Using the accelerometer and gyroscope data we can calculate the tilt angle as well as pitch, roll, and yaw values.
Th guide will take you through understanding the key aspects of the MPU6050, such as its pinout diagram and pin configuration. We will then explore the process of uploading the MPU6050 MicroPython library to the Raspberry Pi Pico using the Thonny IDE. Lastly, we will demonstrate how to acquire accurate and reliable readings from the MPU6050 module, enabling you to harness its full potential in your projects.
You may refer to previous guide about Accelerometer Sensor:
- ADXL335 Analog Accelerometer with Raspberry Pi Pico
- ADXL345 Digital Accelerometer with Raspberry Pi Pico
Bill of Materials
| S.N. | Components | Quantity | Purchase Link |
|---|---|---|---|
| 1 | Raspberry Pi Pico | 1 | Amazon | AliExpress |
| 2 | MPU6050 Module | 1 | Amazon | AliExpress |
| 3 | Breadboard | 1 | Amazon | AliExpress |
| 4 | Connecting Wires | 1 | Amazon | AliExpress |
MPU6050 Accelerometer Gyroscope Sensor
The MPU6050 is a popular, low-cost, and compact 6-axis MotionTracking sensor, designed by InvenSense.
The sensor combines a 3-axis gyroscope, 3-axis accelerometer, and a Digital Motion Processor (DMP) in a single integrated circuit (IC) package. The MPU6050 is widely used in various applications such as robotics, smartphones, gaming devices, and wearable technology, thanks to its accurate motion tracking capabilities and high sensitivity.
The MPU6050 sensor works by combining the functionalities of a 3-axis accelerometer, a 3-axis gyroscope, and a Digital Motion Processor (DMP) to measure and process motion data. The accelerometer measures linear acceleration, while the gyroscope measures angular velocity. Together, these sensors provide a comprehensive understanding of an object’s motion in six degrees of freedom (DOF).
The data is converted into digital signals, processed by the DMP, and communicated to a host microcontroller via the I2C interface for further analysis and application-specific processing.
MPU6050 Features & Speicifications
The MPU6050 has a wide range of features and specifications that make it suitable for motion tracking and sensing applications:
- 3-axis gyroscope with a programmable full-scale range of ±250, ±500, ±1000, and ±2000 degrees per second (dps).
- 3-axis accelerometer with a programmable full-scale range of ±2g, ±4g, ±8g, and ±16g.
- 16-bit analog-to-digital converters (ADCs) for both accelerometer and gyroscope, providing high-resolution data.
- Digital Motion Processor (DMP) for on-chip motion processing, reducing the load on the host processor.
- I2C (Inter-Integrated Circuit) and SPI (Serial Peripheral Interface) communication interfaces.
- Power supply voltage range: 2.375V to 3.46V
- Low power consumption: 3.9mA in normal mode and 5μA in sleep mode.
- Temperature sensor with a range of –40°C to 85°C.
- Interrupt functionality for data-ready and motion detection.
- Small package size: 4x4x0.9mm QFN.
MPU6050 I2C Interface
The MPU6050 uses the I2C interface for communication with microcontrollers or other devices. I2C is a synchronous, bidirectional, two-wire communication protocol, which allows multiple devices to be connected to a single bus. The two wires in the I2C bus are Serial Data Line (SDA) and Serial Clock Line (SCL).
The MPU6050 acts as a slave device on the I2C bus, and its 7-bit I2C address can be either 0x68 or 0x69, depending on the logic level of the AD0 pin.
MPU6050 Pinout
The MPU6050 module is typically mounted on a breakout board to facilitate easier access to its pins and connections. The breakout board may have additional components like voltage regulators or pull-up resistors for the I2C lines, which makes it more user-friendly for prototyping purposes.
The pinout for the MPU6050 module consists of the following pins:
- VCC: Power supply pin, usually accepts input voltage in the range of 3.3V to 5V (depending on the onboard voltage regulator). The MPU6050 IC itself has a supply voltage range of 2.375V to 3.46V.
- GND: Ground reference pin.
- SCL: I2C serial clock line, used for communication with the host microcontroller.
- SDA: I2C serial data line, used for communication with the host microcontroller.
- XDA: Auxiliary I2C data line, for connecting external I2C sensors.
- XCL: Auxiliary I2C clock line, for connecting external I2C sensors.
- AD0 (or ADDR): I2C address selection pin. Depending on its logic level (0: 0x68, 1: 0x69), the 7-bit I2C address of the MPU6050 can be changed.
- INT: Interrupt pin, used to indicate data-ready or motion-detection events to the host microcontroller.
Interfacing MPU6050 with Raspberry Pi Pico
Now, let us interface MPU6050 Gyroscope Accelerometer sensor with Raspberry Pi Pico using the MicroPython Code. The connection is straightforward.
Make the connections between the Raspberry Pi Pico and the MPU6050:
- Connect the VCC pin of the MPU6050 to the 3.3V (Pin 36) of the Raspberry Pi Pico.
- Connect the GND pin of the MPU6050 to the GND (Pin 38) of the Raspberry Pi Pico.
- Connect the SDA pin of the MPU6050 to the SDA (Pin 1 – GP0) of the Raspberry Pi Pico.
- Connect the SCL pin of the MPU6050 to the SCL (Pin 2 – GP1) of the Raspberry Pi Pico.
MPU6050 MicroPython Library
There are several MicroPython libraries available for the MPU6050. But we have created our own library for measuring various accelerometer and gyroscope parameters.
Copy the following code code and paste it on your Thonny IDE. Save the file as ‘mpu6050.py‘ on your Raspberry Pi Pico.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
from machine import Pin, I2C import utime PWR_MGMT_1 = 0x6B SMPLRT_DIV = 0x19 CONFIG = 0x1A GYRO_CONFIG = 0x1B ACCEL_CONFIG = 0x1C TEMP_OUT_H = 0x41 ACCEL_XOUT_H = 0x3B GYRO_XOUT_H = 0x43 def init_mpu6050(i2c, address=0x68): i2c.writeto_mem(address, PWR_MGMT_1, b'\x00') utime.sleep_ms(100) i2c.writeto_mem(address, SMPLRT_DIV, b'\x07') i2c.writeto_mem(address, CONFIG, b'\x00') i2c.writeto_mem(address, GYRO_CONFIG, b'\x00') i2c.writeto_mem(address, ACCEL_CONFIG, b'\x00') def read_raw_data(i2c, addr, address=0x68): high = i2c.readfrom_mem(address, addr, 1)[0] low = i2c.readfrom_mem(address, addr + 1, 1)[0] value = high << 8 | low if value > 32768: value = value - 65536 return value def get_mpu6050_data(i2c): temp = read_raw_data(i2c, TEMP_OUT_H) / 340.0 + 36.53 accel_x = read_raw_data(i2c, ACCEL_XOUT_H) / 16384.0 accel_y = read_raw_data(i2c, ACCEL_XOUT_H + 2) / 16384.0 accel_z = read_raw_data(i2c, ACCEL_XOUT_H + 4) / 16384.0 gyro_x = read_raw_data(i2c, GYRO_XOUT_H) / 131.0 gyro_y = read_raw_data(i2c, GYRO_XOUT_H + 2) / 131.0 gyro_z = read_raw_data(i2c, GYRO_XOUT_H + 4) / 131.0 return { 'temp': temp, 'accel': { 'x': accel_x, 'y': accel_y, 'z': accel_z, }, 'gyro': { 'x': gyro_x, 'y': gyro_y, 'z': gyro_z, } } |
MicroPython Code to measure Gyroscope, Accelerometer Values
Now let us create a simple MicroPython Code to get the value of the Gyroscope, Accelerometer in the X, Y & Z axis along with the temperature value.
Paste the following code to the Thonny Editor and save it to the Raspberry Pi Pico with the name ‘main.py‘.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from machine import Pin, I2C import utime from mpu6050 import init_mpu6050, get_mpu6050_data i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=400000) init_mpu6050(i2c) while True: data = get_mpu6050_data(i2c) print("Temperature: {:.2f} °C".format(data['temp'])) print("Acceleration: X: {:.2f}, Y: {:.2f}, Z: {:.2f} g".format(data['accel']['x'], data['accel']['y'], data['accel']['z'])) print("Gyroscope: X: {:.2f}, Y: {:.2f}, Z: {:.2f} °/s".format(data['gyro']['x'],data['gyro']['y'], data['gyro']['z'])) utime.sleep(0.5) |
Now Run the Code. After running the code, the Thonny Shell will display the Accelerometer, Gyroscope and Temperature values.
You will see the Accelerometer, Gyroscope, and Temperature values on the Shell constantly changing as you move the sensor in different orientations.
MicroPython Code to measure Tilt Angles, Pitch, Roll, Yaw
This code calculates the tilt angles using the accelerometer data. However, it’s important to note that calculating pitch, roll, and yaw usually requires more complex algorithms and sensor fusion, like using a Kalman filter or a complementary filter. The gyroscope data alone is not enough to calculate these angles as it provides angular velocities rather than absolute angles, and integrating the gyroscope data to obtain angles may lead to significant drift over time.
To calculate pitch, roll, and yaw values, we can use a complementary filter that combines accelerometer and gyroscope data to improve the accuracy of the calculated angles. Here’s the updated ‘main.py‘ code with the complementary filter implementation:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
from machine import Pin, I2C import utime import math from mpu6050 import init_mpu6050, get_mpu6050_data def calculate_tilt_angles(accel_data): x, y, z = accel_data['x'], accel_data['y'], accel_data['z'] tilt_x = math.atan2(y, math.sqrt(x * x + z * z)) * 180 / math.pi tilt_y = math.atan2(-x, math.sqrt(y * y + z * z)) * 180 / math.pi tilt_z = math.atan2(z, math.sqrt(x * x + y * y)) * 180 / math.pi return tilt_x, tilt_y, tilt_z def complementary_filter(pitch, roll, gyro_data, dt, alpha=0.98): pitch += gyro_data['x'] * dt roll -= gyro_data['y'] * dt pitch = alpha * pitch + (1 - alpha) * math.atan2(gyro_data['y'], math.sqrt(gyro_data['x'] * gyro_data['x'] + gyro_data['z'] * gyro_data['z'])) * 180 / math.pi roll = alpha * roll + (1 - alpha) * math.atan2(-gyro_data['x'], math.sqrt(gyro_data['y'] * gyro_data['y'] + gyro_data['z'] * gyro_data['z'])) * 180 / math.pi return pitch, roll i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=400000) init_mpu6050(i2c) pitch = 0 roll = 0 prev_time = utime.ticks_ms() while True: data = get_mpu6050_data(i2c) curr_time = utime.ticks_ms() dt = (curr_time - prev_time) / 1000 tilt_x, tilt_y, tilt_z = calculate_tilt_angles(data['accel']) pitch, roll = complementary_filter(pitch, roll, data['gyro'], dt) prev_time = curr_time print("Temperature: {:.2f} °C".format(data['temp'])) print("Tilt angles: X: {:.2f}, Y: {:.2f}, Z: {:.2f} degrees".format(tilt_x, tilt_y, tilt_z)) print("Pitch: {:.2f}, Roll: {:.2f} degrees".format(pitch, roll)) print("Acceleration: X: {:.2f}, Y: {:.2f}, Z: {:.2f} g".format(data['accel']['x'], data['accel']['y'], data['accel']['z'])) print("Gyroscope: X: {:.2f}, Y: {:.2f}, Z: {:.2f} °/s".format(data['gyro']['x'], data['gyro']['y'], data['gyro']['z'])) utime.sleep(1) |
Run the Code now. In the Thonny Shell Console, you will be able to see Accelerometer, Gyroscope, Temperature value along with Tilt Angle in X, Y and Z axis. Apart from this you will also see the Pitch and Roll value. But Yaw value still remain absent.
Please note that this code calculates pitch and roll angles using a complementary filter. However, calculating the yaw angle requires a Magnetometer since it involves heading information, which cannot be accurately derived from an accelerometer and gyroscope alone.
The MPU-6050 does not have a built-in magnetometer, so it is not possible to accurately calculate yaw using the MPU-6050 alone. If you want to calculate yaw, you’ll need to use an additional sensor like an HMC5883L or use an IMU with a built-in magnetometer, such as the MPU-9250 or MPU-9255.














3 Comments
great code – once question – my device is giving a reading of 0.8g in z axis even when stationary. Is there a way to calibrate it (I’m assuming its a calibration issue)
No this is gravity pulling on the imu. If you would rotate your sensor you would see the value decrease on the z axis and increase on another
Traceback (most recent call last):
File “”, line 7, in
File “mpu6050.py”, line 14, in init_mpu6050
OSError: [Errno 5] EIO
I’m facing above error, I checked with connection. by i2c.scan(), I can get device address for the same hardware, but can’t read values.
Kindly help me out.
Thanks.