Friday, April 19, 2024

MPU6050 data in degrees instead of gibberish

For an index to all my stories click this text

Summary:
The MPU6050 is an Accelerometer & Gyroscope that measures movement and rotation. That all sounds great but the information you get from it is in my view pure gibberish. I want simple information like an angle in degrees. The program presented here takes the information from the MPU6050 and translates it in (for me) comprehendible information: just simple degrees.

Please follow this weblog if you go camping with a Caravan or Camper as I have a great story coming up on how this project can help you leveling your Caravan or Camper.

Last summer we went camping and looking at people with caravans and campers I had a great idea. After the holiday I immediately started building the project I had in mind. And then I stumbled upon a small problem.

The project uses an ESP8266 and an MPU6050. The programs used are written in MicroPython.

Wiring them up was no problem at all.



The wiring is so simple that I did not make a breadboard setup but soldered it direct on some stripboard. The final project will be different and battery powered. But let's start with this.

- The MPU6050 needs 3V3 and is powered from the 3V3 pin of the ESP8266

- The SCL pin of the MPU6050 is connected to D1 (pin 5) of the ESP8266

- The SDA pin of the MPU6050 is connected to D2 (pin 4) of the ESP8266

We are going to start with a test and for that connect the ESP8266 with a USB cable to your computer and start Thonny.

The MPU6050 Library

Thonny has a convenient tool to install libraries. But unfortunately that did not supply any library for the MPU6050 that works on a microcontroller. So I turned to the web for a search and there I found a nice library. The library was used by multiple websites but unfortunately I could not find the original developer. So I can not give credit to the developer. Neither can I point to a Github page where you can find that library.

However that library was too extensive for what I needed. Therefore I edited it heavily. I left a lot of things out that I did not need and rewrote a large part of the output. And here is the result:

'''
Luc Volders library for MPU6050
'''

from machine import Pin, I2C
import time
 
def init_mpu(i2c, address=0x68):
    i2c.writeto_mem(address, 0x6B, b'\x00')
    time.sleep_ms(100)
    i2c.writeto_mem(address, 0x19, b'\x07')
    i2c.writeto_mem(address, 0x1B, b'\x00')
    i2c.writeto_mem(address, 0x1B, b'\x00')
    i2c.writeto_mem(address, 0x1C, b'\x00')
 
def read_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_data(i2c):
    readx = read_data(i2c, 0x3B) / 16384.0
    ready = read_data(i2c, 0x3B + 2) / 16384.0
    readz = read_data(i2c, 0x3B + 4) / 16384.0
    
    return readx, ready, readz

This library only returns the acceleration values as that is what I need.
The MPU6050 also has a Gyro inside and a temperature meter. I do not need the Gyro values so they are omitted. The temperature sensor only measures the temperature inside the chip and that is totally different from the temperature in your room. So I don't use that either.

How to use this library.

To use this library we need to copy it to the ESP8266's memory.

So copy the above code and paste it in Thonny.



Choose save as.



Then choose save to MicroPython Device



When the file selector opens choose to save in the lib folder with the name lucsmpulib.py

The library is now ready for use.

The standard MPU6050 program.

Here is the program that reeds the MPU6050 data and writes that data in the shell:

from machine import Pin, I2C
import time
import math
from lucsmpulib import init_mpu, get_data

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # esp8266
init_mpu(i2c)

while True:
        val_x, val_y, val_z = get_data(i2c)
        print ("x = " ,val_x)
        print ("y = " ,val_y)
        print ("z = " ,val_z)
        time.sleep(1)


I will not go into the details as the program almost speaks for itself.
Just mind the pin connections:
- D1 (pin 5) to SCL
- D2 (pin 4) to SDA   

The standard output:

And here is a screenshot of the data we get from the MPU6050.



Like said: pure gibberish.
Not what we want. We want clear understandable data. 



MicroPython program that gives angles in degrees.

Like said before: the values mean nothing to me. I need human readable angle (x and y) values in degrees. And here is the program that provides that.

'''
Program for reading MPU6050 values
and convert them to x and y angles in degrees

From http://lucstechblog.blogspot.com/
'''

from machine import Pin, I2C
import time
import math
from lucsmpulib import init_mpu, get_data

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # esp8266
init_mpu(i2c)

while True:
    readx, ready, readz = get_data(i2c)

    x = math.atan2(ready, math.sqrt(readx * readx + readz * readz)) * 180 / math.pi
    y = math.atan2(-readx, math.sqrt(ready * ready + readz * readz)) * 180 / math.pi
    z = math.atan2(readz, math.sqrt(readx * readx + ready * ready)) * 180 / math.pi
    
    print("=======================================================")
    
    if (x <= 0):
        x = math.floor(x)
    else:
        x = math.ceil(x)
    if (y <= 0):
        y = math.floor(y)
    else:
        y = math.ceil(y)
    print("x = ", x)
    print("y = ", y)
    time.sleep(2)

The program in itself is not complicated but the math is.

Let's have a look at some details.

from machine import Pin, I2C
import time
import math
from lucsmpulib import init_mpu, get_data

First step is to load the necessary libraries. All libraries are standard included when you install MicroPython except of course the lucsmpulib library. That's the one I discussed above.

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # esp8266
init_mpu(i2c)

The i2c pins are defined for the ESP8266, and the mpu6050 is initialised.

while True:
    readx, ready, readz = get_data(i2c)

    x = math.atan2(ready, math.sqrt(readx * readx + readz * readz)) * 180 / math.pi
    y = math.atan2(-readx, math.sqrt(ready * ready + readz * readz)) * 180 / math.pi
    z = math.atan2(readz, math.sqrt(readx * readx + ready * ready)) * 180 / math.pi

The endless loop constant reads the values of the MPU6050. It gets the x, y and z values for the accellerator. These are the only values we need.

Then some complicated math is used to translate the received gibberish into human readable degrees. As the math is beyond the scope of this web-log I will not go into details. Just use it !!

    if (x <= 0):
        x = math.floor(x)
    else:
        x = math.ceil(x)
    if (y <= 0):
        y = math.floor(y)
    else:
        y = math.ceil(y)
    print("x = ", x)
    print("y = ", y)
    time.sleep(2)

If the x, y or z values are equal to 0 or less then zero the value is down-rounded to it's integer value. If the values are larger then 0 they are up-rounded to the nearest integer value.

If you need more accuracy then leave the rounding part out.

I left the z value out of he print sequence as I do not need it for my project. It can however be interesting for other projects. The drill is the same as for the x and y values.

The result

And this is what the output looks like:



I took a geo-triangle and held the setup against it and look there: right on the nose. Totally accurate on the x-values as the slope of the geo-triangle is indeed 45 degrees.



When I put the MPU6050 on the geo-triangle but on the Y side my y values where off. Why ???



Well look at that. When the MPU6050 was flat on the table it gave 4 degrees at the y value. So obviously my table was not completely level. When pressed to the geo-triangle it said 49 degrees. When flat on the table it said 4 degrees and the difference is 45 degrees which it should be.



So when I changed the orientation of the MPU6050 (just turned it 90 degrees) it gave the accurate angle again. So my table is indeed not leveled.

There you got it !! MPU6050 values in degrees !!! And accurate !!!

What now ??

Like stated in the beginning of this story I have a complete project coming up that helps you leveling your Caravan or Camper.

But you can use this for many more projects. Here are a few Ideas I came up with.

- How about using the MPU6050 as a directional control for a remote controlled car or boat. The x angles for forward and reverse and the y angles for left and right.
- How about using the MPU6050 to stabilise your cam or webcam, so no matter what angle your body is at, the camera always points forward
- How about a simple leveler for your DIY building projects.
- How about a tool for leveling your paintings.

That's it for now.
Till next time
Have fun


Luc Volders