Pulling what's left of my hair out

Been trying to get the MPU6050 6 DOF accelerometer/gyroscope working in MRL.

I can get it to attach and even return some data, except the data doesn't make sense.

With the MPU6050 held stationary, the should always be an acceleration in the downward direction of 1G or between 9.8 and 10 m/s depending on where on the planet you are located. (the lower value closer to the equator)
There should also be a constant low speed rotation of about 0.00416 degrees per second (the planet turns fully once per day)

What I'm getting back from the MPU6050 service varies from 1.9G to 0.00G and no rotation at all or NAN results.

The code used in the Java is complex, I think there has been an attempt to use the onboard DMP to process the raw data from the sensors.

In any case, this isn't working.

I was about to swap out the MPU6050 with another one when I looked up and tested a python script on the Raspberry Pi without MRL running.
The MPU6050 was working, output was noisy, but around what I was expecting.
tilting the robot also changed the values being returned and the X/Y angle relative to the ground.

That's when it occurred to me that Mats who normally does a good service, created it back when Manticore was being developed. :-)
So I tried it using a Manticore version of MRL.

It works :-)

So it would seem the issue is with the way Nixie 1.1.443 tries to use the service.

As a reference, Below is a Python version of a script that works to read the MPU6050.

#!/usr/bin/python
import smbus
import math
 
# Register
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c
 
def read_byte(reg):
    return bus.read_byte_data(address, reg)
 
def read_word(reg):
    h = bus.read_byte_data(address, reg)
    l = bus.read_byte_data(address, reg+1)
    value = (h << 8) + l
    return value
 
def read_word_2c(reg):
    val = read_word(reg)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val
 
def dist(a,b):
    return math.sqrt((a*a)+(b*b))
 
def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)
 
def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)
 
bus = smbus.SMBus(1) # bus = smbus.SMBus(0) fuer Revision 1
address = 0x68       # via i2cdetect
 
# Aktivieren, um das Modul ansprechen zu koennen
bus.write_byte_data(address, power_mgmt_1, 0)
 
print "Gyroskop"
print "--------"
 
gyroskop_xout = read_word_2c(0x43)
gyroskop_yout = read_word_2c(0x45)
gyroskop_zout = read_word_2c(0x47)
 
print "gyroskop_xout: ", ("%5d" % gyroskop_xout), " skaliert: ", (gyroskop_xout / 131)
print "gyroskop_yout: ", ("%5d" % gyroskop_yout), " skaliert: ", (gyroskop_yout / 131)
print "gyroskop_zout: ", ("%5d" % gyroskop_zout), " skaliert: ", (gyroskop_zout / 131)
 
print
print "Beschleunigungssensor"
print "---------------------"
 
beschleunigung_xout = read_word_2c(0x3b)
beschleunigung_yout = read_word_2c(0x3d)
beschleunigung_zout = read_word_2c(0x3f)
 
beschleunigung_xout_skaliert = beschleunigung_xout / 16384.0
beschleunigung_yout_skaliert = beschleunigung_yout / 16384.0
beschleunigung_zout_skaliert = beschleunigung_zout / 16384.0
 
print "beschleunigung_xout: ", ("%6d" % beschleunigung_xout), " skaliert: ", beschleunigung_xout_skaliert
print "beschleunigung_yout: ", ("%6d" % beschleunigung_yout), " skaliert: ", beschleunigung_yout_skaliert
print "beschleunigung_zout: ", ("%6d" % beschleunigung_zout), " skaliert: ", beschleunigung_zout_skaliert
 
print "X Rotation: " , get_x_rotation(beschleunigung_xout_skaliert, beschleunigung_yout_skaliert, beschleunigung_zout_skaliert)
print "Y Rotation: " , get_y_rotation(beschleunigung_xout_skaliert, beschleunigung_yout_skaliert, beschleunigung_zout_skaliert)
 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
GroG's picture

I took a quick look ... 

I took a quick look ...  there is basically no differences between Manticore's and Nixie's Mpu6050 Service.
So, I suspect the problematic differences is between the RasPi service.
I know there is a version change from the Pi4J library, but I'd need help chasing down the issue.  
Manticore uses 1.1-snapshot, and Nixie uses 1.2 (formally released) Pi4J.

Heh, I just bought a couple of Mpu6050's .... they'll take a few days to come to me.

Ray.Edgley's picture

Somewhere to look :-)

It would make sense,

I couldn't see any faults as such, but the code was far more complex that I thought it needed to be, but testing in Manticore showed it to be more stable than the Python one I tested with.

 

GroG's picture

If the 0s and NaNs were

If the 0s and NaNs were filtered out - would then the data seem usable ?
I could imagine perhaps some default read timeouts for i2c adjusted in the Pi4j libraries...
Perhaps they are more unforgiving in Pi4J 1.2 ?

kwatters's picture

NaN NaN NaN....

Ok.. so interesting.. i reproduced this issue locally using an arduino. 

but oddly i had it working at first... and it is really just a luck that i got it working the first time...

I started by uploading a simple sketch to the arduino that verified that i could get some data from the mpu.  check, i saw data flowing.. check.

then. i uploaded mrlcomm to the arduino...   started mrl.. created a mpu service an arduino service, and attached them... magically it worked.

 

then i unplugged the serial port.. plugged it back in.. tried to test with MRL again.. and I was getting all 0s .. or NaN  ..(depending on if i was looking at the gyro angles or the filtered x,y,z) ...

so.. what I think happened for me.. I initialized the mpu board with my sketch.  i never powered off the board, so it was configured as expected.. 

when mrlcomm then tried to read from the mpu.. it was already initialized...  and data was there...  

gah.. so this means, we're missing some i2c commands to make sure the mpu is initialized properly so that we can read the desired data from it...  

good news is.. it's worky for me locally when i run the other arduino sketch first...

hopefully it won't be too hard to trace which i2c command(s) is/are missing...

kwatters's picture

got it!

ok.. turns out we need a call to initialize the board before we can use it..

 

call

mpu6050.dmpInitialize() 

 

before you try to call

mpu6050.refresh() 

 

 

Ray.Edgley's picture

Still have issue.

So I have the latest MRL 1.1.446 installed on the Raspberry Pi

In the start scripts for the MPU6050 I have enabled the MPU6050
 
EnableMPU6050A =True
 
if EnableMPU6050A == True:
    MPU6050A = Runtime.createAndStart("MPU6050A","Mpu6050")
    MPU6050A.attach(MPU6050AAttached, MPU6050APort, "0x68")
    MPU6050A.dmpInitialize()
 
But the data returned when I use MPU6050A.refresh() is still garbage.
Last poll for example is as follows:
AccelX: 0.000 G
AccelY: 0.000 G
AccelZ: 0.000 G
Temperature: 84.718 degrees Celicus
GyroX: 0.000 degrees/s
GyroY: 0.000 degrees/s
GyroZ: 0.000 degrees/s
 
MPU6050A.refresh()
 
AccelX: 0.000 G
AccelY: 0.008 G
AccelZ: -0.987 G
Temperature: 27.745 degrees Celicus
GyroX: 0.000 degrees/s
GyroY: -211.000 degrees/s
GyroZ: 0.000 degrees/s
 
MPU6050A.refresh()
 
AccelX: 0.000 G
AccelY: 0.000 G
AccelZ: 0.000 G
Temperature: 36.530 degrees Celicus
GyroX: 0.000 degrees/s
GyroY: 0.000 degrees/s
GyroZ: 0.000 degrees/s
 

There is no consistant data here, and since the robot isn't moving during these test, the second one means the whole planet must be spinning real fast.
The temperature is also strange.
I started out roasting, then got down to a high be more normal temp before it went back up to uncomfotably hot.
We should always be getting a Accel summing up to around 1.000G give or take a small bit depending on how close to the equator you are.  As you rotate the MPU6050 sensor the Accell should shift the direction so the vectors can show the direction down is.

Apart from the GyroY, the secons reading some 30 secoconds apart (time for me to write down the data) was the closest of what I was expecting.

Under Manticore, the results were reasonably consistant and in the expected range.

Under Nixie 1.1.446 it's not even close and not at all usable to stablise the head of the robot.

Yet running the MPU6050 with the python script in the post, the results were pretty close to expected as they were in Manticore.
The data has to be getting corrupted some where.

Note, the I2C bus used for this is also running two Adafruit16CServoDriver with a total of 11 Servo services attached between them

The servos are working OK.

In Manticore, to test if the MPU6050 was working, I moved the bot with the Torso Roll servos.

Testing has been done using the I2C bus located on the Raspberry Pi 4

 

GroG's picture

RasPi 3  MPU 06050-

RasPi 3 
MPU 06050- connected 5v @ address 68

Running your python example for 3 samples:
 

Gyroskop
--------
gyroskop_xout:    -41  skaliert:  -1
gyroskop_yout:    -40  skaliert:  -1
gyroskop_zout:     -7  skaliert:  -1
 
Beschleunigungssensor
---------------------
beschleunigung_xout:    1284  skaliert:  0.078369140625
beschleunigung_yout:     324  skaliert:  0.019775390625
beschleunigung_zout:   12760  skaliert:  0.77880859375
X Rotation:  1.44722769298
Y Rotation:  -5.74431825281
 
Gyroskop
--------
gyroskop_xout:    -41  skaliert:  -1
gyroskop_yout:    -41  skaliert:  -1
gyroskop_zout:     -8  skaliert:  -1
 
Beschleunigungssensor
---------------------
beschleunigung_xout:    1232  skaliert:  0.0751953125
beschleunigung_yout:     288  skaliert:  0.017578125
beschleunigung_zout:   12760  skaliert:  0.77880859375
X Rotation:  1.28699386025
Y Rotation:  -5.51351605351
 
Gyroskop
--------
gyroskop_xout:    -41  skaliert:  -1
gyroskop_yout:    -43  skaliert:  -1
gyroskop_zout:     -8  skaliert:  -1
 
Beschleunigungssensor
---------------------
beschleunigung_xout:    1380  skaliert:  0.084228515625
beschleunigung_yout:     380  skaliert:  0.023193359375
beschleunigung_zout:   12776  skaliert:  0.77978515625
X Rotation:  1.69381485783
Y Rotation:  -6.16219941564
 
 
 
GroG's picture

Going to try some

Going to try some simplification of some of the RasPi code - specifically there is isWiring switch that I believe could be refactored out. Additionally there is a lot of MPU code that could be refactored out too, lots of it is general methods to handle different read types - most of the mpu data is 2 byte big endian signed ints.

On the good side, there is a useful scan i2c button, which is currently showing the results of my raspi connected to a Adafruit 16C Servo controller and a MPU6050 - interesting the servo controller looks like it publishes 2 addresses ....  learn something everyday ;)