MPU6050

MPU6050 (GY-521) and Micropython interactively

The Internet of Things (IoT) continues to reshape how we interact with the world, enabling smart devices to collect and transmit data with ease. Among the many powerful tools available for IoT development, MicroPython stands out for its simplicity and efficiency, particularly when paired with the versatile ESP32 microcontroller. One common application involves gathering motion and orientation data using the MPU6050, a popular accelerometer and gyroscope sensor.

In this article, we’ll explore how to leverage MicroPython on the ESP32 to read data from the MPU6050. Whether you're a beginner or an experienced developer, this guide will help you set up the hardware, configure the software, and retrieve valuable sensor data for use in a variety of applications, from robotics to wearable devices.

Reading Data from the MPU6050 with MicroPython

Once the hardware connections are complete and the ESP32 is running MicroPython, the next step is to interact with the MPU6050 to obtain sensor data. The MPU6050 provides both accelerometer and gyroscope readings, which can be accessed over the protocol.

### Prerequisites

Before diving into the code, ensure the following:

  • The MPU6050 is correctly wired to the ESP32.
  • The fimware microPython for your ESP32 device;
  • You have access to a MicroPython-compatible library for the MPU6050.
    • A popular choice is mpu6050.py, which simplifies communication with the sensor.

Step 1: Install the MPU6050 Library

You can upload the library to your ESP32 using tools like ampy or the Thonny IDE:

  • Download the mpu6050.py library.
  • Use the following command to upload the file (if using ampy):
ampy --port /dev/ttyUSB0 put mpu6050.py

Step 2: Initialize the Sensor in MicroPython

Open a new Python script and connect to the sensor:

import machine  
import mpu6050  
import time

# Setup the I2C device
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21))

# Initialize the sensor
mpu = mpu6050.MPU6050(i2c)

# reading data from the sensor
while True:  
    accel_data = mpu.get_accel()  
    gyro_data = mpu.get_gyro()  

    print("Accelerometer: ", accel_data)  
    print("Gyroscope: ", gyro_data)  

    time.sleep(1)  

Advanced Techniques: Using Interrupts, Calibrating the Sensor, and Resetting Position

In addition to reading basic accelerometer and gyroscope data, you can enhance your project by incorporating interrupts for event detection, calibrating the sensor for improved accuracy, and resetting its position during runtime.

Using Interrupts with the MPU6050

The MPU6050 features an interrupt pin (INT) that can signal events like motion detection or data readiness. By configuring and handling interrupts, your ESP32 can respond immediately to changes, reducing the need for constant polling.

Step 1: Wiring for Interrupts

Connect the MPU6050’s INT pin to a digital pin on the ESP32 (e.g., GPIO 25):

  • INT (MPU6050) GPIO 25 (ESP32)

Step 2: Configuring the Interrupt in Code

MicroPython allows you to attach an interrupt handler to the pin:

from machine import Pin, I2C  
import mpu6050  

i2c = I2C(0, scl=Pin(22), sda=Pin(21))  
mpu = mpu6050.MPU6050(i2c)  
mpu.enable_interrupts()

# Interrupt handler
int_pin = Pin(25, Pin.IN)  

def handle_interrupt(pin):  
    print("Motion detected!")  
    accel = mpu.get_accel()  
    print("Accelerometer data:", accel)  

# Attach handler  
int_pin.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt) 

Step 3: Configuring Interrupts on the MPU6050

You’ll need to enable the MPU6050’s interrupt features:

mpu.enable_interrupts()  

Calibrating the MPU6050

Calibration is essential to remove biases and offsets in the accelerometer and gyroscope readings. This can be done by capturing a series of readings while the sensor is stationary and computing the average offsets.

Step 1: Capture Offsets

Place the MPU6050 on a flat surface and capture a few seconds of data:

def calibrate_mpu():  
    accel_offset = {'x': 0, 'y': 0, 'z': 0}  
    gyro_offset = {'x': 0, 'y': 0, 'z': 0}  

    for _ in range(100):  
        accel = mpu.get_accel()  
        gyro = mpu.get_gyro()  

        for axis in accel_offset:  
            accel_offset[axis] += accel[axis]  
            gyro_offset[axis] += gyro[axis]  

    # Calculate average offsets  
    for axis in accel_offset:  
        accel_offset[axis] /= 100  
        gyro_offset[axis] /= 100  

    print("Accelerometer offsets:", accel_offset)  
    print("Gyroscope offsets:", gyro_offset)  
    return accel_offset, gyro_offset  

Step 2: Apply Offsets

Subtract these offsets from future readings:

accel, gyro = mpu.get_accel(), mpu.get_gyro()  
calibrated_accel = {axis: accel[axis] - accel_offset[axis] for axis in accel}  
calibrated_gyro = {axis: gyro[axis] - gyro_offset[axis] for axis in gyro}  

Resetting Position (Reinitialization)

In some applications, you may need to reset the sensor’s position during runtime. This can be useful when recalibrating or re-centering the system.

Step 1: Software Reset

You can issue a reset command to the MPU6050:

def reset_mpu():  
    mpu.reset()  
    print("MPU6050 reset complete.")  

Step 2: Zeroing Out the Data

If you need to zero out position data without a hardware reset:

def zero_position():  
    global accel_offset, gyro_offset  
    accel_offset, gyro_offset = calibrate_mpu()  
    print("Position reset to zero.")  

By combining these methods, you can dynamically recalibrate and reposition the MPU6050 during operation, enhancing precision and reliability.

Here's an expanded section with details on using interrupts, calibrating the MPU6050, and resetting its position: Advanced Techniques: Using Interrupts, Calibrating the Sensor, and Resetting Position

In addition to reading basic accelerometer and gyroscope data, you can enhance your project by incorporating interrupts for event detection, calibrating the sensor for improved accuracy, and resetting its position during runtime. Using Interrupts with the MPU6050

The MPU6050 features an interrupt pin (INT) that can signal events like motion detection or data readiness. By configuring and handling interrupts, your ESP32 can respond immediately to changes, reducing the need for constant polling.

Step 1: Wiring for Interrupts

Connect the MPU6050’s INT pin to a digital pin on the ESP32 (e.g., GPIO 25):

  • INT (MPU6050) → GPIO 25 (ESP32)

Step 2: Configuring the Interrupt in Code

MicroPython allows you to attach an interrupt handler to the pin:

from machine import Pin, I2C  
import mpu6050  

i2c = I2C(0, scl=Pin(22), sda=Pin(21))  
mpu = mpu6050.MPU6050(i2c)  

# interrupt pin  
int_pin = Pin(25, Pin.IN)  

def handle_interrupt(pin):  
    print("Motion detected!")  
    accel = mpu.get_accel()  
    print("Accelerometer data:", accel)  

# Attach handler  
int_pin.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)  

You’ll need to enable the MPU6050’s interrupt features:

mpu.enable_interrupts()

This setup allows the ESP32 to respond only when an interrupt is triggered, making your code more efficient. Calibrating the MPU6050

Calibration is essential to remove biases and offsets in the accelerometer and gyroscope readings. This can be done by capturing a series of readings while the sensor is stationary and computing the average offsets.

Step 1: Capture Offsets

Place the MPU6050 on a flat surface and capture a few seconds of data:

def calibrate_mpu():  
    accel_offset = {'x': 0, 'y': 0, 'z': 0}  
    gyro_offset = {'x': 0, 'y': 0, 'z': 0}  

    for _ in range(100):  
        accel = mpu.get_accel()  
        gyro = mpu.get_gyro()  

        for axis in accel_offset:  
            accel_offset[axis] += accel[axis]  
            gyro_offset[axis] += gyro[axis]  

    # Calculate average offsets  
    for axis in accel_offset:  
        accel_offset[axis] /= 100  
        gyro_offset[axis] /= 100  

    print("Accelerometer offsets:", accel_offset)  
    print("Gyroscope offsets:", gyro_offset)  
    return accel_offset, gyro_offset  

Step 2: Apply Offsets

Subtract these offsets from future readings:

accel, gyro = mpu.get_accel(), mpu.get_gyro()  
calibrated_accel = {axis: accel[axis] - accel_offset[axis] for axis in accel}  
calibrated_gyro = {axis: gyro[axis] - gyro_offset[axis] for axis in gyro}  

Resetting Position (Reinitialization)

In some applications, you may need to reset the sensor’s position during runtime. This can be useful when recalibrating or re-centering the system.

Step 1: Software Reset

You can issue a reset command to the MPU6050:

def reset_mpu():  
    mpu.reset()  
    print("MPU6050 reset complete.")  

Step 2: Zeroing Out the Data

If you need to zero out position data without a hardware reset:

def zero_position():  
    global accel_offset, gyro_offset  
    accel_offset, gyro_offset = calibrate_mpu()  
    print("Position reset to zero.")  

By combining these methods, you can dynamically recalibrate and reposition the MPU6050 during operation, enhancing precision and reliability.

These advanced techniques provide greater flexibility and control when working with the MPU6050. Whether you're designing a motion-controlled device or a real-time monitoring system, integrating interrupts, calibrating the sensor, and resetting its position can significantly improve performance.

About

Author