Multiple MPU6050

Hi,

I need to connect 4 MPU6050 from sparkfun and send acceleration and gyroscope data to my pc simultaneously. I am new to this i2C device so I dont really know how to play with the address thingy (as i only know with AD0 grounded it is 0x68 and AD0 connected to 3.3V it is 0x69).

I used multiplexer 74HC4051N to connect multiple MPU6050 together (as shown in the diagram). I do not really know my connection is correct or not (as i said I am really new in this field). So please advise on the hardware connection part.

Also I modified Jeff Rowberg arduino code and try to communicate with multiple MPU6050. However, all i get is only 0. The below is my arduino code:

//////////////////////////////////////////////////////////////////////////////////////////////////
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgryo;
int16_t ax, ay, az, gx, gy, gz, ax1, ay1, az1, gx1, gy1, gz1;

//ASSIGN DIGITAL PINS (MUX)

int S0 = 3;
int S1 = 2;
int S2 = 1;

unsigned long time;
void out1()
{
digitalWrite(S0, HIGH);
digitalWrite(S1, LOW);
digitalWrite(S2, LOW);

}

void out2()
{
digitalWrite(S0, LOW);
digitalWrite(S1, HIGH);
digitalWrite(S2, LOW);

}

void setup()
{

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif

Serial.begin(36400);

}

void loop()
{
time=millis();
out1();

accelgryo.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

out2();
accelgryo.getMotion6(&ax1, &ay1, &az1, &gx1, &gy1, &gz1);

Serial.print("DATA,TIME,");
Serial.print(time);
Serial.print(",");
Serial.print(ax);
Serial.print(",");
Serial.print(ay);
Serial.print(",");
Serial.print(az);
Serial.print(",");
Serial.print(gx);
Serial.print(",");
Serial.print(gy);
Serial.print(",");
Serial.print(gz);
Serial.print(",");
Serial.print(ax1);
Serial.print(",");
Serial.print(ay1);
Serial.print(",");
Serial.print(az1);
Serial.print(",");
Serial.print(gx1);
Serial.print(",");
Serial.print(gy1);
Serial.print(",");
Serial.println(gz1);

delay(10);

}

//////////////////////////////////////////////////////////////////////////////////////////////

Can anyone advise what went wrong software and hardware, and how can I modify it?

Thank you very much.

Don't run the signals, SDA or SCL through the multiplexer.
Run the Address pin ADO through the multiplexer. Then select the one you want to use with the 74HC4051N address.

Because of the voltage regulator on the MPU-6050 board, you better use the 5V for the Vcc.
When you use 3.3V, the voltage regulator on the MPU-6050 board makes 3.2V, which could be too low for the Uno to detect.

Can you change the i2c_scanner sketch to select every the modules one by one and let the i2c_scanner do a scan ?
http://playground.arduino.cc/Main/I2cScanner

steinie44:
Don't run the signals, SDA or SCL through the multiplexer.
Run the Address pin ADO through the multiplexer. Then select the one you want to use with the 74HC4051N address.

DId you mean connect the AD0 pin to the input of multiplexer? then how should I connected my SDA and SCL??

Peter_n:
Because of the voltage regulator on the MPU-6050 board, you better use the 5V for the Vcc.
When you use 3.3V, the voltage regulator on the MPU-6050 board makes 3.2V, which could be too low for the Uno to detect.

Can you change the i2c_scanner sketch to select every the modules one by one and let the i2c_scanner do a scan ?
Arduino Playground - HomePage

Connect to 5V?? I thought if connect to 5V it will spoil the chip??

Yes, but if you have a module like in the picture, there is a voltage regulator on the board.
However, if you have a Sparkfun module without voltage regulator you do blow the chip indeed.

The 3.3V I2C bus is just barely accepted by the 5V Arduino Uno. And 3.2V for the MPU-6050 SDA and SCL might be too low. So if your board has a voltage regulator, use the 5V pin of the Arduino to power Vcc (which is going to the voltage regulator).

tanminggui:

steinie44:
Don't run the signals, SDA or SCL through the multiplexer.
Run the Address pin ADO through the multiplexer. Then select the one you want to use with the 74HC4051N address.

DId you mean connect the AD0 pin to the input of multiplexer? then how should I connected my SDA and SCL??

No, connect the input to the multiplexer High. then when you select the address, only one of the 4 MPU6050's will be addressed as 0x69. The other 3 will be 0x68. You only use 0x69 to talk to the one selected. Don't use 0x68 at all.

Now all 4 SDA lines are connected to the Arduino SDA. As well as all 4 SCL lines to SCL.

You can also use an I2C multiplexer chip:

Handles the different voltage levels as well.

CrossRoads:
You can also use an I2C multiplexer chip:
http://www.dsscircuits.com/index.php/i2c-multiplexer
Handles the different voltage levels as well.

Good option. First time I've seen it.

steinie44:

tanminggui:

steinie44:
Don't run the signals, SDA or SCL through the multiplexer.
Run the Address pin ADO through the multiplexer. Then select the one you want to use with the 74HC4051N address.

DId you mean connect the AD0 pin to the input of multiplexer? then how should I connected my SDA and SCL??

No, connect the input to the multiplexer High. then when you select the address, only one of the 4 MPU6050's will be addressed as 0x69. The other 3 will be 0x68. You only use 0x69 to talk to the one selected. Don't use 0x68 at all.

Now all 4 SDA lines are connected to the Arduino SDA. As well as all 4 SCL lines to SCL.

Ok. This sound like a good idea for me.

Since I am using Sparkfun MPU6050, I need to desoldier the AD0 pin first (which is quite troblesome). But anywhere, thanks for the advise.

I will share my result once I get it done.

Thank you again.

CrossRoads:
You can also use an I2C multiplexer chip:
http://www.dsscircuits.com/index.php/i2c-multiplexer
Handles the different voltage levels as well.

This actually look BRILLIANT!!!!! 4 SDA and 4 SCL pins which can be connected to 4 MPU6050 directly!!!!

If I used this i2c mux, do I need to change the address of the MPU6050? or I do not need to deal with AD0 pin and all MPU6050 will remain 0x68 address?

In that case in my arduino code I only need to use digital pin from the arduino to feed the control signal to mux?

THANK YOU...

You have 3 options:

  • Use a i2c mux chip. This chip handles everything for you. You could create two I2C-sub-busses with 0x68 (AD0 = GND) and 0x69 (AD0 = 3.3V) on each sub-bus. You have to control the i2c mux chip, which means using a library or extra code.
  • Use a mux for the SDA signal. This is what you have, the no-nonsense solution.
  • Use the trick with the AD0, set all to 0x69 and switch one to 0x68 by making AD0 low for just that one. Use only the one at 0x68.

With every option you have to be careful that the chip can't handle 5V signals.

No, you leave the address of the 4 slave devices alone.
Which channel is opened is selected by writing to a register:

"Only one SCx/SDx channel is selected at a time, determined by the contents of the programmable control register."

steinie44:

tanminggui:

steinie44:
Don't run the signals, SDA or SCL through the multiplexer.
Run the Address pin ADO through the multiplexer. Then select the one you want to use with the 74HC4051N address.

DId you mean connect the AD0 pin to the input of multiplexer? then how should I connected my SDA and SCL??

No, connect the input to the multiplexer High. then when you select the address, only one of the 4 MPU6050's will be addressed as 0x69. The other 3 will be 0x68. You only use 0x69 to talk to the one selected. Don't use 0x68 at all.

Now all 4 SDA lines are connected to the Arduino SDA. As well as all 4 SCL lines to SCL.

Hi, I take your advise but sorry for being too dumb and silly because I am not sure I can understand you 100% or not :sweat_smile:.

I had attached a new drawing here. All the AD0 pins are now connected to multiplexer and SDA/SCL pins connected to SDA/SCL on Arduino. Is it the correct connection?
So now I only need to address one of them as 0x69 and use multiplexer to select them?

Sorry for ignorance.

Yes, but I don't see the multiplexer input pin connected high.

You have to select the multiplexer address first before you address the MPU6050 that is selected.

steinie44:
Yes, but I don't see the multiplexer input pin connected high.

You have to select the multiplexer address first before you address the MPU6050 that is selected.

Sorry but I do not quite understand with this statement.

When you said multiplexer input pin connected high, do you mean the common input pin of multiplexer connected to digital port of Arduino Uno as shown in the figure below?

So during coding I need to set the digital port that is connected to common input pin of multiplexer as high only like this?

#include "Wire.h"



#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgryo;
int16_t  ax, ay, az, gx, gy, gz, ax1, ay1, az1, gx1, gy1, gz1,ax2, ay2, az2, gx2, gy2, gz2, ax3, ay3, az3, gx3, gy3, gz3;




int S0 = 3;
int S1 = 2;
int S2 = 1;
int input = 8;

unsigned long time;



//MANUALLY CONTROL THE LINE OF MULTIPLEXER TO SELECT THE PIN CONNECTED TO AD0
void out1()
{
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
   
}

void out2()
{
  digitalWrite(S0, LOW);
  digitalWrite(S1, HIGH);
  digitalWrite(S2, LOW);
   
}

void out3()
{
  digitalWrite(S0, HIGH);
  digitalWrite(S1, HIGH);
  digitalWrite(S2, LOW);
   
}

void out4()
{
  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, HIGH);
   
}



void setup()
{

  
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
 
  Serial.begin(36400);
  Serial.println("CLEARDATA");
  Serial.println("LABEL,Time,time,ax1,ay1,az1,gx1,gy1,gz1,ax2,ay2,az2,gx2,gy2,gz2,ax3,ay3,az3,gx3,gy3,gz3,ax4,ay4,az4,gx4,gy4,gz4");
  
  pinMode (input, OUTPUT);
  
  digitalWrite(input,HIGH);

  
}



void loop()
{
 time=millis();
    out1();
     
    
    accelgryo.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    
    out2();
    accelgryo.getMotion6(&ax1, &ay1, &az1, &gx1, &gy1, &gz1);
    
    out3();
    accelgryo.getMotion6(&ax2, &ay2, &az2, &gx2, &gy2, &gz2);
    
     out4();
    accelgryo.getMotion6(&ax3, &ay3, &az3, &gx3, &gy3, &gz3);
    
    
    Serial.print("DATA,TIME,");
    Serial.print(time);
    Serial.print(",");
    Serial.print(ax); 
    Serial.print(",");
    Serial.print(ay); 
    Serial.print(",");
    Serial.print(az); 
    Serial.print(",");
    Serial.print(gx); 
    Serial.print(",");
    Serial.print(gy); 
    Serial.print(",");
    Serial.print(gz); 
    Serial.print(","); 
    Serial.print(ax1); 
    Serial.print(",");
    Serial.print(ay1); 
    Serial.print(",");
    Serial.print(az1); 
    Serial.print(",");
    Serial.print(gx1); 
    Serial.print(",");
    Serial.print(gy1); 
    Serial.print(",");
    Serial.print(gz1); 
    Serial.print(",");
    Serial.print(ax2); 
    Serial.print(",");
    Serial.print(ay2); 
    Serial.print(",");
    Serial.print(az2); 
    Serial.print(",");
    Serial.print(gx2); 
    Serial.print(",");
    Serial.print(gy2); 
    Serial.print(",");
    Serial.print(gz2); 
    Serial.print(",");
    Serial.print(ax3); 
    Serial.print(",");
    Serial.print(ay3); 
    Serial.print(",");
    Serial.print(az3); 
    Serial.print(",");
    Serial.print(gx3); 
    Serial.print(",");
    Serial.print(gy3); 
    Serial.print(",");
    Serial.println(gz3); 
    
    
     delay(10);
  
}

Isnt all the MPU6050 will set to 0x69 with this connection when the multiplexer is multiplexing? Or do I miss anything with my code?

Just connect it to +5v so its high all the time. That way when you address the multiplexer, that high is passed to the MPU6050 that you want to select.
Just think of it as a 4 way switch. The high signal is passed to the switch that you address.
Not to confuse you, but you can use a Low, if you want to use 0x68 all the time instead of 0x69.

Each time you want to read a MPU6050, you have to address it via the output pins to the multiplexer first.

Like a paper route: go to address and deliver, go to next address and deliver, ....................
Payday: go to address and collect, go to next address and collect, ..................

steinie44:
Just connect it to +5v so its high all the time. That way when you address the multiplexer, that high is passed to the MPU6050 that you want to select.
Just think of it as a 4 way switch. The high signal is passed to the switch that you address.
Not to confuse you, but you can use a Low, if you want to use 0x68 all the time instead of 0x69.

Each time you want to read a MPU6050, you have to address it via the output pins to the multiplexer first.

Like a paper route: go to address and deliver, go to next address and deliver, ....................
Payday: go to address and collect, go to next address and collect, ..................

Hi,

So far what I have done and understand from you:
Use the 5V to set the 4 MPU6050 to HIGH one at the time by using multiplexer digital control. When the selected MPU6050 is address high 0x69, the arduino board will only read the selected IMU. So this process will continue to loop until I stop.

I hope the attached figure is finally correct.

For multiplexer, now I connected
-The common input to 5V
-Supply voltage Vcc to 3.3V
-Ground to ground
-S0,S1,S2 (select input) to digital port 1,2,3
-Y0,Y1,Y2,Y3 (Independent output) to AD0 pin of each MPU6050 respectively

-Supply voltage unconnected
-Enable input unconnected

For MPU6050
-AD0 pin to multiplexer independent output (Y0,Y1,Y2,Y3)
-Vcc to 3.3V
-GND to ground
-SCL connected together with other MPU6050 on breadboard and connected to arduino A5
-SDS connected together with other MPU6050 on breadboard and connected to arduino A4
-Int to digital port (4,5,6,7 for each MPU6050 respectively)
-Vio to 3.3V

#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgryo(MPU6050_ADDRESS_AD0_HIGH) ;
int16_t  ax, ay, az, gx, gy, gz, ax1, ay1, az1, gx1, gy1, gz1,ax2, ay2, az2, gx2, gy2, gz2, ax3, ay3, az3, gx3, gy3, gz3;
//ASSIGN DIGITAL PINS (MUX)

int S0 = 3;
int S1 = 2;
int S2 = 1;

unsigned long time;

//MANUALLY CONTROL THE LINE OF MULTIPLEXER TO SELECT THE PIN CONNECTED TO AD0
void out1()
{
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
   
}

void out2()
{
  digitalWrite(S0, LOW);
  digitalWrite(S1, HIGH);
  digitalWrite(S2, LOW);
   
}

void out3()
{
  digitalWrite(S0, HIGH);
  digitalWrite(S1, HIGH);
  digitalWrite(S2, LOW);
   
}

void out4()
{
  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, HIGH);
   
}
void setup()
{

  
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
 
  Serial.begin(36400);
  Serial.println("CLEARDATA");
  Serial.println("LABEL,Time,time,ax1,ay1,az1,gx1,gy1,gz1,ax2,ay2,az2,gx2,gy2,gz2,ax3,ay3,az3,gx3,gy3,gz3,ax4,ay4,az4,gx4,gy4,gz4");
    
}



void loop()
{
 time=millis();
    out1();
     
    
    accelgryo.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    
    out2();
    accelgryo.getMotion6(&ax1, &ay1, &az1, &gx1, &gy1, &gz1);
    
    out3();
    accelgryo.getMotion6(&ax2, &ay2, &az2, &gx2, &gy2, &gz2);
    
     out4();
    accelgryo.getMotion6(&ax3, &ay3, &az3, &gx3, &gy3, &gz3);
    
    
    Serial.print("DATA,TIME,");
    Serial.print(time);
    Serial.print(",");
    Serial.print(ax); 
    Serial.print(",");
    Serial.print(ay); 
    Serial.print(",");
    Serial.print(az); 
    Serial.print(",");
    Serial.print(gx); 
    Serial.print(",");
    Serial.print(gy); 
    Serial.print(",");
    Serial.print(gz); 
    Serial.print(","); 
    Serial.print(ax1); 
    Serial.print(",");
    Serial.print(ay1); 
    Serial.print(",");
    Serial.print(az1); 
    Serial.print(",");
    Serial.print(gx1); 
    Serial.print(",");
    Serial.print(gy1); 
    Serial.print(",");
    Serial.print(gz1); 
    Serial.print(",");
    Serial.print(ax2); 
    Serial.print(",");
    Serial.print(ay2); 
    Serial.print(",");
    Serial.print(az2); 
    Serial.print(",");
    Serial.print(gx2); 
    Serial.print(",");
    Serial.print(gy2); 
    Serial.print(",");
    Serial.print(gz2); 
    Serial.print(",");
    Serial.print(ax3); 
    Serial.print(",");
    Serial.print(ay3); 
    Serial.print(",");
    Serial.print(az3); 
    Serial.print(",");
    Serial.print(gx3); 
    Serial.print(",");
    Serial.print(gy3); 
    Serial.print(",");
    Serial.println(gz3); 
    
    
     delay(10);
  
}

I hope what I have done so far is correct and I will like to hear an approval from you. :slight_smile:

Thank you so much for your time.

Connect pin 3 to 3.3V not 5v Sorry.

The use of pin 1. I would move pins 1 through 7 up one pin to 2 through 8.
Pins 0 and 1 are used by USB.

Also why are the interrupt lines connected to 4 through 7?

steinie44:
Connect pin 3 to 3.3V not 5v Sorry.

The use of pin 1. I would move pins 1 through 7 up one pin to 2 through 8.
Pins 0 and 1 are used by USB.

Also why are the interrupt lines connected to 4 through 7?

The default setting for interrupt line is to connected to digital pin 2, but since I have 4, so I simply connected them to other digital pin. Is that alright?