I2C and Invensense MPU6050 Driver

We are using the Invensense MPU6050 IMU on I2C with Beaglebone Black (Angstrom 3.8.13). We can use I2C-tools and file I/O thru /dev/i2c but the read speed is disappointingly slow. We only read the 3x gyros and 3x accels (each one byte at a time plus the 2 byte temperature reading) and it takes ~2msecs. My estimate of the I2C bus cycles for a block read suggests this should take ~160 bus cycles or .38msec on a 400MHz I2C bus.

The distribution includes the Invensense driver inv-mpu6050.ko but there is no indication that reading through /dev/i2c invokes it. This is a very popular IMU and Invensense widely distributes the driver over many Linux platforms. The driver source includes “successful installation will create two directories under /sys/bus/iio/devices” and lists the files there (aka functions). I can never get these to show up.

I can “insmod /lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050/inv-mpu6050.ko” and “echo inv-mpu6050 0x68 > /sys/class/i2c-adapter/i2c-1/new_device”. This causes a new directory named 1-0068 to show in /sys/class/i2c-adapter/i2c-1with entries like name and modalias but no functions. It never shows in /sys/bus/iio/devices.

What constitutes “successful installation”?

What else is needed to get the inv-mpu6050 to expose functions in /sys/bus/iio/devices like the driver sources says?

Beaglebone Black uses bone_capemgr for exposing driver functions for many devices. “echo inv-mpu6050 0x68 > /sys/devices/bone_capmgr.9/slots” raises the gripe “write error: no such file or directory”. (I can successfully load the am33xx_pwm driver this way.) Is this because there is no matching DT fragment in /lib/firmware? Is the inv-mpu6050 driver supposed to be invoked thru cape manager?

Then, most importantly, if I did read and write through the /sys tree using the Invensense driver would it be faster than /dev/i2c?
Help on sorting this out would be much appreciated.

You’re barking at a wrong tree. /sys/devices/bone_capmgr.9/slots is used to load device tree overlays and has nothing to do with devices on I2C bus. The correct place to write to instantiate a new i2c device is /sys/bus/i2c/devices/i2c-X/new_device (substitute X with bus number to which the chip is connected). The echo command in your case would look like something like this:

echo inv-mpu6050 0x68 > /sys/bus/i2c/devices/i2c-X/new_device

j.

You're barking at a wrong tree. /sys/devices/bone_capmgr.9/slots is used to
load device tree overlays and has nothing to do with devices on I2C bus.

This is not quite true. While you can access the I2C bus directly without
a device tree entry, if there is an overlay you can tell the kernel that this
device is expected to be there, and if the driver is DTB enabled you can
get it loaded and configured for you.

David

J.
Ok, but I did the new_device, got a directory entry for 1-0068 (my new address), but didn’t get anything I recognized as the MPU6050 driver functions. Can you guess what caused that? Do they show up in this 1-0068 dir or somewhere else in the /sysfs? or over in /dev/i2c? If I am successful, do you see any reason this will be faster than just file i/o thru /dev/i2c? --Clark

David,
Good for you. I don’t understand that connection. If I get the driver and a DTB loaded, where will it show up? Possible answers are under bone_capmgr, under /sys/…i2c-1, and under /dev/i2c. And do you have any reason to believe this will be faster than simply file i/o-ing thru /dev/i2c? --Clark

David,
Good for you. I don't understand that connection. If I get the driver and a
DTB loaded, where will it show up? Possible answers are under bone_capmgr,
under /sys/...i2c-1, and under /dev/i2c. And do you have any reason to
believe this will be faster than simply file i/o-ing thru /dev/i2c? --Clark

If you want raw file access to the device, then your application is acting
as the device driver so the kernel does not need to know anything other than
how to deal with the I2C hardware - which it clearly does. However if you
want a device driver (and you seemed to be looking for one or rather the
files that is presents) then you need to tell the kernel to load the driver.
This can be done manually, or you can configure it - and the way that seems
to becoming the standard is the device tree. Your choice.

David

Some good info on I2C tools at http://www.acmesystems.it/i2c.

Python and the adafruit BBIO I2C library makes it very easy to use I2C on Beaglebone Black as well. Python import smbus is fairly easy to use too. Some examples of use is available in the code I provide for my radio project here…www.aiwindustries.com.

Not trying to sell the product, but I know that the I2C function was giving me some issues so I’m just trying to help the community. Python code is available to download and look at usage so feel free.

AIW:
I went back thru the adafruit library and didn’t find anything specific on I2C, although it is listed as a topic. I have been looking at their github adafruit-beaglebone-io-python library. I also found and looked thru PyBBIO. Even tho I’m not using Python, I can see the access mechanisms that they use.
I can use the MPU6050 device ok enough just reading via /dev/i2c/i2c-x, but that is too slow.
I’m trying to figure out how to invoke and use the inv-mpu6050 driver and adafruit doesn’t use that.
Thx – Clark

I did find some more python data regarding the MPU6050 here. I believe it was originally designed for R-Pi, but its based off smbus so it should work on BBB as well. Not sure if this will be any faster than how your doing it but just looking at options.

AIW:
I went back thru the adafruit library and didn't find anything specific on
I2C, although it is listed as a topic. I have been looking at their github
adafruit-beaglebone-io-python library. I also found and looked thru PyBBIO.
Even tho I'm not using Python, I can see the access mechanisms that they
use.
I can use the MPU6050 device ok enough just reading via /dev/i2c/i2c-x, but
that is too slow.
I'm trying to figure out how to invoke and use the inv-mpu6050 driver and
adafruit doesn't use that.
Thx -- Clark

Some good info on I2C tools at http://www.acmesystems.it/i2c.

Python and the adafruit BBIO I2C library makes it very easy to use I2C on
Beaglebone Black as well. Python import smbus is fairly easy to use too.
Some examples of use is available in the code I provide for my radio project
here....www.aiwindustries.com.

Not trying to sell the product, but I know that the I2C function was
giving me some issues so I'm just trying to help the community. Python code
is available to download and look at usage so feel free.

We are using the Invensense MPU6050 IMU on I2C with Beaglebone Black
(Angstrom 3.8.13). We can use I2C-tools and file I/O thru /dev/i2c but the
read speed is disappointingly slow. We only read the 3x gyros and 3x accels
(each one byte at a time plus the 2 byte temperature reading) and it takes
~2msecs. My estimate of the I2C bus cycles for a block read suggests this
should take ~160 bus cycles or .38msec on a 400MHz I2C bus.

You are running at 400kHz, not 400MHz, right? I2C doesn't do 400MHz.

The distribution includes the Invensense driver inv-mpu6050.ko but there
is no indication that reading through /dev/i2c invokes it. This is a very
popular IMU and Invensense widely distributes the driver over many Linux
platforms. The driver source includes “successful installation will create
two directories under /sys/bus/iio/devices” and lists the files there (aka
functions). I can never get these to show up.

I can “insmod
/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050/inv-mpu6050.ko” and
“echo inv-mpu6050 0x68 > /sys/class/i2c-adapter/i2c-1/new_device”. This
causes a new directory named 1-0068 to show in
/sys/class/i2c-adapter/i2c-1with entries like name and modalias but no
functions. It never shows in /sys/bus/iio/devices.

I don't have an MPU6050, but I just ordered a couple on express
overnight from Sparkfun.

Here's the behavior I'm seeing without the board connected:

root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050# ls
inv-mpu6050.ko
root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050#
dmesg | tail -1
[ 2992.799594] i2c i2c-1: new_device: Instantiated device inv-mpu6050 at 0x68
root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050# lsmod
Module Size Used by
ip_tables 8294 0
x_tables 15072 1 ip_tables
g_multi 55905 2
libcomposite 15228 1 g_multi
rfcomm 25106 0
ircomm_tty 14503 0
ircomm 8846 1 ircomm_tty
irda 89974 2 ircomm_tty,ircomm
ipv6 229989 14
hidp 10112 0
bluetooth 146100 4 hidp,rfcomm
rfkill 16510 2 bluetooth
autofs4 17432 2

I looked for the installed device:

root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050#
cat /sys/bus/iio/devices/iio*/name
tiadc
root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050#
ls /sys/bus/iio/devices/iio* -d
/sys/bus/iio/devices/iio:device0

It is clearly missing per the documentation
(https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-iio-mpu6050)
that says there should be a sysfs entry there.

Just in case I could get it to show up, I did try manually doing a modprobe.

root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050#
modprobe inv-mpu6050
root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050# lsmod
Module Size Used by
inv_mpu6050 7190 0
ip_tables 8294 0
x_tables 15072 1 ip_tables
g_multi 55905 2
libcomposite 15228 1 g_multi
rfcomm 25106 0
ircomm_tty 14503 0
ircomm 8846 1 ircomm_tty
irda 89974 2 ircomm_tty,ircomm
ipv6 229989 14
hidp 10112 0
bluetooth 146100 4 hidp,rfcomm
rfkill 16510 2 bluetooth
autofs4 17432 2
root@beaglebone:/lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050#
ls /sys/bus/iio/devices/iio* -d
/sys/bus/iio/devices/iio:device0

Of course, this all makes perfect sense since the driver should exit
upon failing the 'probe':
https://github.com/beagleboard/linux/blob/3.8/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c#L658

I'd have to look up how to turn on more debugging statements. I tried
the hints at http://elinux.org/Debugging_by_printing, but I'm
surprised the 'dmesg' log didn't show any extra errors.

What constitutes “successful installation”?

What else is needed to get the inv-mpu6050 to expose functions in
/sys/bus/iio/devices like the driver sources says?

I don't think anything else should be required. To build the kernel
properly, there are a few things that need to be enabled
(https://github.com/beagleboard/linux/blob/3.8/drivers/iio/imu/inv_mpu6050/Kconfig):

INV_MPU6050_IIO, I2C, SYSFS, IIO_BUFFER, IIO_TRIGGERED_BUFFER

And they are all there:
https://github.com/beagleboard/kernel/blob/3.8/configs/beaglebone#L3676

Beaglebone Black uses bone_capemgr for exposing driver functions for many
devices. “echo inv-mpu6050 0x68 > /sys/devices/bone_capmgr.9/slots” raises
the gripe “write error: no such file or directory”. (I can successfully
load the am33xx_pwm driver this way.) Is this because there is no matching
DT fragment in /lib/firmware?

Yes.

Is the inv-mpu6050 driver supposed to be
invoked thru cape manager?

No, because the I2C bus software provides another mechanism. I believe
you could create a DT fragment, but I think it is pointless.

Then, most importantly, if I did read and write through the /sys tree
using the Invensense driver would it be faster than /dev/i2c?
Help on sorting this out would be much appreciated.

Yes, because the driver running in kernel mode is going to be higher
performance than your pokes from userspace.

> AIW:
> I went back thru the adafruit library and didn't find anything specific on
> I2C, although it is listed as a topic. I have been looking at their github
> adafruit-beaglebone-io-python library. I also found and looked thru PyBBIO.
> Even tho I'm not using Python, I can see the access mechanisms that they
> use.
> I can use the MPU6050 device ok enough just reading via /dev/i2c/i2c-x, but
> that is too slow.
> I'm trying to figure out how to invoke and use the inv-mpu6050 driver and
> adafruit doesn't use that.
> Thx -- Clark
>
>>
>> Some good info on I2C tools at http://www.acmesystems.it/i2c.
>>
>> Python and the adafruit BBIO I2C library makes it very easy to use I2C on
>> Beaglebone Black as well. Python import smbus is fairly easy to use too.
>> Some examples of use is available in the code I provide for my radio project
>> here....www.aiwindustries.com.
>>
>> Not trying to sell the product, but I know that the I2C function was
>> giving me some issues so I'm just trying to help the community. Python code
>> is available to download and look at usage so feel free.
>>
>>>
>>> We are using the Invensense MPU6050 IMU on I2C with Beaglebone Black
>>> (Angstrom 3.8.13). We can use I2C-tools and file I/O thru /dev/i2c but the
>>> read speed is disappointingly slow. We only read the 3x gyros and 3x accels
>>> (each one byte at a time plus the 2 byte temperature reading) and it takes
>>> ~2msecs. My estimate of the I2C bus cycles for a block read suggests this
>>> should take ~160 bus cycles or .38msec on a 400MHz I2C bus.

You are running at 400kHz, not 400MHz, right? I2C doesn't do 400MHz.

>>>
>>> The distribution includes the Invensense driver inv-mpu6050.ko but there
>>> is no indication that reading through /dev/i2c invokes it. This is a very
>>> popular IMU and Invensense widely distributes the driver over many Linux
>>> platforms. The driver source includes “successful installation will create
>>> two directories under /sys/bus/iio/devices” and lists the files there (aka
>>> functions). I can never get these to show up.
>>>
>>> I can “insmod
>>> /lib/modules/3.8.13/kernel/drivers/iio/imu/inv_mpu6050/inv-mpu6050.ko” and
>>> “echo inv-mpu6050 0x68 > /sys/class/i2c-adapter/i2c-1/new_device”. This
>>> causes a new directory named 1-0068 to show in
>>> /sys/class/i2c-adapter/i2c-1with entries like name and modalias but no
>>> functions. It never shows in /sys/bus/iio/devices.

I don't have an MPU6050, but I just ordered a couple on express
overnight from Sparkfun.

I bought https://www.sparkfun.com/products/11028 and played with it
briefly before being distracted and again today, but I don't
understand why I'm not able to get it to reply to me.

I have the following connections:
VCC: P9_4 (VDD_3V3)
GNC: P9_1 (GND)
INT: P9_11 (GPIO)
FSYNC: -
SCL: P9_19 (I2C2_SCL)
SDA: P9_20 (I2C2_SDA)
VIO: P9_3 (VDD_3V3)
CLK: -
ASCL: -
ASDA: -

I then perform:

root@beaglebone:~# i2cdetect -y -r 1
     0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Very confused why it doesn't show up.

Since you have it responding to you, how do you have it wired?

So I’ve been struggling with I2C. Somebody on this list gave me the tip to do:

echo BB-I2C1 > /sys/devices/bone_capemgr.???/slots

which enables the third I2C bus and my device then was visible via i2cdetect -y -r 1 on pins P9_19 and P9_20. Although, after doing that, you’ll have an i2c1 and a i2c2 bus, so might want to check both. But, I’m not quite sure why this works :slight_smile:

In my case, I don’t think there is device tree entry for the device I’m using, so I was planning on interacting with it over raw I2C.

Hope this helps,

Josh

Nevemind, that may be unrelated. I just rebooted and my device enumerated fine. I think what’s confusing (me) is the I2C2 by the SRM (P9_19/20) shoes up as I2C1…

some output:

ebian@arm:~$ ls -l /sys/bus/i2c/devices/i2c-*
lrwxrwxrwx 1 root root 0 Nov 1 04:02 /sys/bus/i2c/devices/i2c-0 → …/…/…/devices/ocp.2/44e0b000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Nov 1 04:02 /sys/bus/i2c/devices/i2c-1 → …/…/…/devices/ocp.2/4819c000.i2c/i2c-1
debian@arm:~$ su
Password:
root@arm:/home/debian# i2cdetect -r 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: – -- – -- – -- – -- – -- – -- –
10: – -- – -- – -- – -- – -- – -- – -- – --
20: – -- – -- – -- – -- – -- – -- – -- – --
30: – -- – -- – -- – -- – -- – -- – -- – --
40: – -- – -- – -- – -- 48 – -- – -- – -- –
50: – -- – -- UU UU UU UU – -- – -- – -- – --
60: – -- – -- – -- – -- – -- – -- – -- – --
70: – -- – -- – -- – --

Nevemind, that may be unrelated. I just rebooted and my device enumerated
fine. I think what's confusing (me) is the I2C2 by the SRM (P9_19/20) shoes
up as I2C1...

Yeah, this is a really confusing (well-known) issue where the latest
Linux kernels assign the bus names in order of them being enumerated,
despite whatever hardware name is given to them. So, I2C0, enumerated
first, becomes, i2c0 and I2C2, enumerated second, becomes i2c1. If you
then enumerate I2C1, you'll get an i2c2. Kinda confusing, got to give
you that.

some output:

ebian@arm:~$ ls -l /sys/bus/i2c/devices/i2c-*
lrwxrwxrwx 1 root root 0 Nov 1 04:02 /sys/bus/i2c/devices/i2c-0 ->
../../../devices/ocp.2/44e0b000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Nov 1 04:02 /sys/bus/i2c/devices/i2c-1 ->
../../../devices/ocp.2/4819c000.i2c/i2c-1
debian@arm:~$ su
Password:
root@arm:/home/debian# i2cdetect -r 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
     0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

I need hints on how the MPU6050 should be wired up or assume that I've
got a bad device. I can probably try hooking it up to something else.

If you’re curious as to how to figure out what I2C interface maps to which bus, take a look at this post I wrote yesterday:

https://groups.google.com/d/msg/beagleboard/v9r8UkN7klk/h3rFKFJDLnUJ

Jason,
I apologize for taking so long to answer. It wasn’t quick to figure out which breakout board we had with the MPU6050 on it. It is apparently a Kootek® Arduino GY-521 MPU-6050 Module from Amazon.

Itis wired:

P9_1->Gnd

P9_3->VCC

P9_19 ->SCL

P9_20 → SDA

Your P9_19 SCL and P9_20 SDA should be fine.

Later posts suggest you can talk to you device and have shown us via W Smith the way to straighten out which bus is which.

Clark

Did anyone every get the inv-mpu6050 kernel driver to work? I have the device on the i2c bus and I can read and write registers using i2cset/i2cget, but modprobe inv-mpu605 doesn’t make anything appear.

–Mark

Mark,
Near as I can tell, no one has done better than just file i/o via /dev/i2c/… This works, but doesn’t seem to expose or take advantage of the Invensense kernel driver functionality. Plus it seems to be very slow. Jason Kridner was tackling it a couple weeks ago, but didn’t report any success. I haven’t made any progress either.
Seems we are stuck. I wish someone could figure out how to ping the author at Invensense. I tried writing via thier support web page but didn’t get a reply.
Clark

It looks like someone has done a nice port to Andriod[1]. How hard would it be to port it to Angstrom?

–Mark

[1] https://android.googlesource.com/kernel/tegra/+/74f15aa73e1d999368e3a8287cdb85718e987d48/drivers/staging/iio/imu/mpu/README

Mark,
I poked briefly at the reference you provided. The write up looks very much the same as the Invensense MPU6050 driver in the Angstrom on the Black. This seems reasonable. The Invensense author has done a good job of getting it into the Linux tree and the various distributions have picked it up. Apparently, the MPU 60x0 family of MEMS IMUs is widely used and popular.
The Anstrom driver reads nice. No one here has yet to get it to load and respond.
Clark