Report
4 years, 5 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

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 Olieman 08 Feb 2015
Comment on this question

1 Answer

4 years, 5 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 Frank Cerasoli 08 Feb 2015

The 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 Wim Huiskamp 08 Feb 2015

I 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 Frank Cerasoli 08 Feb 2015

Well, 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 Wim Huiskamp 08 Feb 2015

I 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 Frank Cerasoli 08 Feb 2015

According 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 Wim Huiskamp 08 Feb 2015

I 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 Frank Cerasoli 08 Feb 2015

When 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 Wim Huiskamp 08 Feb 2015

One of the VCC pins on my nRF isn't functioning correctly. I switched to a different one and it all works fine. Thanks again!

posted by Frank Cerasoli 08 Feb 2015