Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 9 months ago.
MPU3050 I2C Communication
Hello all,
Currently I am developing on a nRF 51822. I have been banging my head against the wall trying to read the Who am I ID from the 0x00 register off of an MPU3050. I'm afraid that I don't understand the I2C protocol well enough to put this algorithm together. I only want to load the 6 bit ID into the value that I define as "wai".
Here is the code that I have so far. It assumes the includes, the serial in/out, "sc", definition and definition of i2c on pins p13 & p15.
int main() { char *wai = (char*)calloc(sizeof(char),1); while(1) { i2c.start(); i2c.write((0x68<<1)); i2c.write(0x00); i2c.start(); i2c.read(((0x68<<1)|1),wai,sizeof(char),0); i2c.stop(); sc.printf("Test: %i\n", (char)(*wai)); wait(4); } }
I always get output of
Test: 0
I believe that I am handling i2c incorrectly and I need some guidance. Please help!
Best regards, Frank
1 Answer
9 years, 9 months ago.
Something like this should work when all hardware & wiring is OK
const int addr = (0x68 << 1); char cmd[2]; char data[2]; int main() { while (1) { // Select the WAI register and select Repeated Start option cmd[0] = 0x00; i2c.write(addr, cmd, 1, true); // Read the WAI register i2c.read(addr, data, 1); sc.printf("Test: %d\n", data[0]); wait(4); } }
I notice that you never send the stop command. Why is that ok? Also, even with your code, I still get "Test: 0" for every output. I was under the impression that I should get the hex number 0x34. Should I now assume that I have a broken MPU3050?
posted by 08 Feb 2015The block read and block write operations include the Start and Stop commands plus all the byte send/receives that are indicated by the 'length' parameter. In your case the first block write operation skips the Stop and the following block read performs a so-called Repeated Start. Note that these block operations abort when the slave does not respond. You can check the return values to see if all is good.
const int addr = (0x68 << 1); char cmd[2]; char data[2]; int result; int main() { while (1) { // Select the WAI register and select Repeated Start option cmd[0] = 0x00; result = i2c.write(addr, cmd, 1, true); sc.printf("I2C Write Result: %d\n\r", result); // Read the WAI register result = i2c.read(addr, data, 1); sc.printf("I2C Read Result: %d\n\r", result); sc.printf("Test: %d\n\r", data[0]); wait(4); } }
You have to check the I2C wiring, pullups, the slave addressbit and the slave powersupply. In case result indicates a problem. Note that I have not yet tested I2C on the nRF. There may still be problems in the I2C mbed lib.
posted by 08 Feb 2015I see. Well both the read and write results both came back as 1 (which I assume means that they were successfully completed), but data[0] is still getting the value 0. This means that my MPU is functioning correctly, but possibly the I2C library is not?
EDIT:: I see now that non-0 is failure. So it is either my MPU or the wiring. I really don't believe that my wiring is off. Ill try the code on a 6050 and modify the registers to see if that functions.
posted by 08 Feb 2015Well, actually a result not equal to 0 indicates a problem. See here. Check the wiring, are you sure that the MPU has the SA0 address bit at 0?
posted by 08 Feb 2015I just saw that non-0 is failure. =\ What do you mean by the SA0 bit? Sorry for the ignorant questions. I'm still trying to learn I2C
posted by 08 Feb 2015According to the MPU datasheet pin 9 is for AD0. This is LSB of the slaveaddress. So the address is either (0x68<<1) or (0x69<<1) depending on how pin9 is wired. This feature allows you have two MPU3050s on the same bus without any conflicts.
posted by 08 Feb 2015I understand what you're saying about running two MPU's together, but I don't know when to choose (0x68<<1) vs (0x69<<1). I have now tried with my MPU6050 using this code.
#include "mbed.h" Serial sc(USBTX, USBRX); I2C i2c(p13,p15); const int addr = (0x68 << 1); char cmd[2]; char data[2]; int result; int main() { while (1) { // Select the WAI register and select Repeated Start option cmd[0] = 0x75; // For the MPU-6050 result = i2c.write(addr, cmd, 1, true); sc.printf("I2C Write Result: %i\n\r", result); // Read the WAI register result = i2c.read(addr, data, 1); sc.printf("I2C Read Result: %i\n\r", result); sc.printf("Test: %i\n\r", data[0]); wait(4); } }
I still get failures to read or write i2c.
EDIT: Works on one of my 6050's but not my 2nd.... Doesn't work on my 3050. Must be my hardware. =( Thanks for all of the advice.
posted by 08 Feb 2015When it works on one 6050 this means that the i2C libs are OK and that the wiring is OK. This first device must have AD0 wired at logic low level since the address is (0x68 << 1). Have you tried the other address (0x69 << 1) on the second 6050. Maybe that has AD0 wired at logic high level. Also try both addresses on the 3050. You cant break anything.
posted by 08 Feb 2015
First of all, put code tags (
<<code>> and <</code>>
) around your code, then it is properly formatted and we can read it.Second, I would advice to use the full i2c statements, like what you do use for the read, but not for the write.
posted by Erik - 08 Feb 2015