erabapi
Posts: 1
Joined: Sat Aug 25, 2018 1:27 pm

Using MPU9250 with SPI

Sat Aug 25, 2018 1:57 pm

Hello everyone! Total beginner here, so I apologize beforehand if I ask trivial/stupid questions.

For an assignment, I need to use the MPU9250 (https://www.invensense.com/wp-content/u ... 0-v1.6.pdf) to measure accelerations in z direction and use SPI to transfer the data to the pi. I have enabled SPI on my RPI.
I have connected:
RPI | MPU9250
17 -> VCC
19 -> SDA/SDI
21 -> ADO/SDO
23 -> SCLK
24 -> NCS
25 -> GND

So far I have tried using the spidev library based on the example here (http://tightdev.net/SpiDev_Doc.pdf) and wrote:

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 1)

i=0
while i<10
resp = spi.xfer([0x3F])
print(resp)
i +=1

as I understood(please correct me if I am wrong) this should start a transaction with the device and read me the values on the register 0x3F(z acceleration) but it returns something like this:
[15]
[15]
[31]
[15]
[31]
[31]
[31]
[15]
[15]
[31]

every time I run the code it returns a different set of numbers. I have no idea what the value in the brackets mean. I need acceleration values measured in g's, what do I need to do to get that?

And also, (I haven't tried it yet because I couldn't even get any measurements), I need to set the sampling rate to around 4kHz. How can I do that? Is my approach so far completely wrong, am I missing something obvious?

As I said earlier, I am a complete beginner and have almost no background in coding, so I apologize if I am asking silly questions. If you could help me I would appreciate it a lot.

Thanks in advance

Brandon92
Posts: 616
Joined: Wed Jul 25, 2018 9:29 pm
Location: Netherlands

Re: Using MPU9250 with SPI

Sat Aug 25, 2018 2:42 pm

erabapi wrote:
Sat Aug 25, 2018 1:57 pm
For an assignment, I need to use the MPU9250 (https://www.invensense.com/wp-content/u ... 0-v1.6.pdf) to measure accelerations in z direction and use SPI to transfer the data to the pi. I have enabled SPI on my RPI.
When I look in the document that you provided they talk about the I2C protocol and not the SPI protocal. They are not the same.
Here they talk also about the I2C protocol.

So, are you sure it is a spi device?

DirkS
Posts: 9602
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: Using MPU9250 with SPI

Sat Aug 25, 2018 3:27 pm


meinkea
Posts: 1
Joined: Sun Jan 13, 2019 8:43 pm

Re: Using MPU9250 with SPI

Sun Jan 13, 2019 10:00 pm

erabapi wrote:
Sat Aug 25, 2018 1:57 pm
Hello everyone! Total beginner here, so I apologize beforehand if I ask trivial/stupid questions.

For an assignment, I need to use the MPU9250 (https://www.invensense.com/wp-content/u ... 0-v1.6.pdf) to measure accelerations in z direction and use SPI to transfer the data to the pi. I have enabled SPI on my RPI.
I have connected:
RPI | MPU9250
17 -> VCC
19 -> SDA/SDI
21 -> ADO/SDO
23 -> SCLK
24 -> NCS
25 -> GND

So far I have tried using the spidev library based on the example here (http://tightdev.net/SpiDev_Doc.pdf) and wrote:

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 1)

i=0
while i<10
resp = spi.xfer([0x3F])
print(resp)
i +=1

as I understood(please correct me if I am wrong) this should start a transaction with the device and read me the values on the register 0x3F(z acceleration) but it returns something like this:
[15]
[15]
[31]
[15]
[31]
[31]
[31]
[15]
[15]
[31]

every time I run the code it returns a different set of numbers. I have no idea what the value in the brackets mean. I need acceleration values measured in g's, what do I need to do to get that?

And also, (I haven't tried it yet because I couldn't even get any measurements), I need to set the sampling rate to around 4kHz. How can I do that? Is my approach so far completely wrong, am I missing something obvious?

As I said earlier, I am a complete beginner and have almost no background in coding, so I apologize if I am asking silly questions. If you could help me I would appreciate it a lot.

Thanks in advance
I am not an expert on programming (my back ground is mechanical/aerospace) but I remember how frustrating it when I was learning spidev until I had a friend (computer engineer) explain to me how SPI worked.

I think I know some problems your having, and I have 1 or 2 side notes. BTW I am assuming your using Python.

Something you'll need
I would recommend going to InvenSense's website and download the documentation (specifically "Register Maps" and "Datasheet"). I don't necessarily recommend reading all of the Datasheet as being a beginner it might be overwhelming and it's not really need. However by glancing through, and seeing something making you wonder "What's this?" will lead you to lots of googling and learning new things (and there is a lot that the datasheet will expose you too). The Register Maps is your best friend!!!

1 - Read vs Write Command
I would like you to look at page 36 of the Datasheet. It should be labeled 7.5 SPI Interface. It describes how you do the read and write commands over SPI. It describes the "SPI Address format" as an 8 bit number with the first bit describing (0) for write and (1) for read, and the last 7 bits being for the address.

In your case, you wanted to read address 3F (hex) or 63 (dec).
Using 7 bits, 63 decimal form is 0111111, but you wanted to read this address so you have to tag on a 1 in front, giving you 10111111 (bin), 191 (dec), or BF (hex). In general, you'll always have to add a number to the address you want to read.
This is 10000000 (for bin), 128 (dec), or 80 (hex). Notice how this is not needed for the write command. Therefore it is 63 to read or 191.

Side note
Spidev can either take either hex number or decimal numbers, so 191 is perfectly fine to use instead of 0x3F, which I will be doing for the rest of this reply.

2 - Addresses
Take a look at the Register Maps. After a short investigation, you'll notice that register 63 (the High byte) and 64 (the Low byte) contain reading of the acceleration in the Z-direction. Therefore, your list must be [63+128, 64+128] or [191, 192].

3 - SPI Transaction
When you did, the Raspberry Pi sent 00111111 the the mpu9250 but, to receive data over SPI, you must send data. Therefore, the mpu9250 just sends garbage (typically this is either 00000000 or 11111111 but it can be even an old number stored).
So if you want to read 63, you need to send 63 and than some other number let the chip send back what is stored in that address.
For example "resp = spi.xfer([63, 129])" would work (I did 129 as I would rather leave the chip hanging on a read command rather than a write command). The chip also supports burst reads, so you can receive data from a previous read command while sending a new one.
So if you want to get both 63 and 64, you need to do "resp = spi.xfer([191, 192, 129])". This will return [ garbage, High Byte, Low Byte].

From when I worked with spidev, I made my list outside of the spi.xfer command as it did unwanted behavior.
So I recommend doing.
L = [191, 192, 129]
resp = spi.xfer(L)

After your transaction, you can put the two bytes together using a binary shift.
zAccel = (L[1] << 8) + L[2]

4 - Flavor of SPI
There are different flavors of SPI (about 4). You can google them but add this to your code.

spi.open(0, 0) <- check your wiring and do a google... I thought it was pin 8 or 7 for SPI slave 0 or 1 (but i'm running out of time to check)
spi.mode = 3
spi.cshigh = False




In the End
In total it should look something like this

spi = spidev.SpiDev()
spi.open(0, 0)
spi.mode = 3
spi.cshigh = False

L = [191, 192, 129]
resp = [ ]
resp = spi.xfer(L)

spi.close()

zAccel = (L[1] << 8) + L[2]
print(zAccel)


Good luck and hope this helped.

Return to “Interfacing (DSI, CSI, I2C, etc.)”