Multiple MPU6050 Sensors on One Arduino

I am doing a project that requires 14 GY521 IMU sensors, all interfaced through one Arduino Mega 2560. After browsing through Arduino Playground and other forum posts, it seems the only way to interface this many is to assign each AD0 to a separate digital output on the Arduino, and then set one sensor at a time to low to read each one individually. Here is my code:

#include <Wire.h>  //imports Wire library
#include <MPU6050.h>
#include <Servo.h>
MPU6050 gyro;  //creates new MPU6050 object
int16_t ax, ay, az;  //creates angle variables
int16_t gx, gy, gz;

void setup() {  //setup method
  Serial.begin(9600);
  Wire.begin();  //starts I2C communication
  gyro.initialize();  //initializes MPU6050 sensor
  for (int i = 22; i <= 35; i++) {
    pinMode(i, OUTPUT);  //defines pins as output pins
  }
}

void loop() {  //main method
  for (int j = 22; j <= 35; j++) {
    for (int k =  22; k <= 35; k++) {
      digitalWrite(k, HIGH);  //sets all sensors to high address
    }
    digitalWrite(j, LOW);  //sets one sensor to low address
    gyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);  //calls values from sensor
    ax = map(ax, -17000, 17000, 0, 180);  //maps x axis rotation values from 0 to 180
    Serial.println(" ");
    Serial.print(ax);
    ay = map(ay, -17000, 17000, 0, 180);
    Serial.print("  ");
    Serial.print(ay);
    az = map(az, -17000, 17000, 0, 180);
    Serial.print("  ");
    Serial.println(az);
  }
}

For some reason I am not getting any output whatsoever when I run this program. I'm pretty sure all the sensors work, but is this the right way to go about the programming? I'm a bit new to Arduino, but it seems to me that this is the only way to go about this.

How is it supposed to work, that you set pinMode for pins 22-35, then write to pins 0-14?

Wow, I did not realize how stupid that was. However, after I fixed that, it still does not print continuously. It prints 4 lines at most and then stops. Maybe 14 sensors is too much for I2C to take?

matthewclso:
Maybe 14 sensors is too much for I2C to take?

No, but 14 4k7 or 2k2 pull up resistors on the SDA and SCL lines in parallel might be too much.

Always post links to the exact modules you're using.
And a diagram, and/or a clear picture of the setup.
Leo..

Here is the schematic for the IC I am using.

Attached is a basic diagram of my setup. Only 4 sensors are drawn, but it's the same setup with 14. VCC, GND, SDA, SCL are all wired in series to the Arduino. Each AD0 is attached to a different digital output.

So you're using a module with 4k7 pull up resistors.
That's a combined pull up resistance of 4700 / 14 = ~335 ohm,
while the minimum value for 3.3volt standard I2C is 1100ohm (3mA).
But wait, you're using a 5volt Arduino (Mega) for a 3.3volt module. How did you solve that.
Or did you use modules with I2C level shifters (I asked for a link to the modules you're using).
Leo..

This is the unit I bought:
https://m.aliexpress.com/item/32276121395.html

I'm a bit new to electronics, won't it still work with 5V?

Module seems to have a 3.3volt regulator (5-pin chip), but no level shifters on the I2C and address lines.
You might already have damaged the module(s) by connecting it to a 5volt processor.

The SDA and SCL lines have 2k2 resistors, so a combined pull up resistance of 2200/14 = 157 ohm.

I think the easiest way to solve this is with two translating (level shifting) I2C muxers.

If you go that way, you can also use a much smaller Arduino Nano/ProMini.
Leo..

If 5V was pushed into the AD0 of all the MPU-6050, then they all might be broken / damaged / no longer reliable.

Can you buy new sensors ?
You could also buy a 3.3V Arduino board.

How often do you want the data ? The I2C bus is slow and 14 sensors means 14 times slower.

What about a 3.3V Arduino board like the Arduino Due and the MPU-9250 in SPI mode ?

I understand - because the Arduino has 5V outputs, but sensor requires 3.3V signals, it's not working?

So, assuming that all my sensors are working, if I replace the Arduino's voltage regulator to a 3.3V one, following this procedure: 3.3V Conversion | Arduino Tips, Tricks, and Techniques | Adafruit Learning System , it should work?

Thanks for the replies.

The Arduino Mega 2560 has pins that can deliver 5V up to 40 mA. Pushing that into a pin of the MPU-6050 can damage it, because the MPU-6050 runs at 3.3V.

I don't like that Adafruit conversion. They remove the polyfuse. The ATmega328P can not run at 16 MHz at 3.3 V according to the datasheet. In most cases it will work though.

If you use a 3.3volt Arduino, then you still have the problem of the I2C pull up resistors.
You can only leave two 2k2 sets.
Leo..

I am doing a project that requires 14 GY521 IMU sensors

What project could possibly require 14 IMUs, and even if so, why does it have to go through one Arduino? You can buy a Pro Mini on eBay for $2!

jremington:
What project could possibly require 14 IMUs, and even if so, why does it have to go through one Arduino? You can buy a Pro Mini on eBay for $2!

I'm making a motion tracker as input for a robotic hand. I figured it'd be easier to route all the data through one device, instead of say, 7 Pro Minis.

Wawa:
If you use a 3.3volt Arduino, then you still have the problem of the I2C pull up resistors.
You can only leave two 2k2 sets.
Leo..

I still don't understand what you mean by the I2C pull up resistors. Using 3.3V Arduino, you can set the AD0 on the sensors, no?

I still don't understand what you mean by the I2C pull up resistors.

Every sensor, and possibly also the Arduino, has a pullup resistor on each of the I2C lines. They are all in parallel, and that demands far too much current from the I/O lines.

You will have to remove both pullup resistors on at least 13 of the 14 sensors if you insist on this arrangement.

I figured it'd be easier to route all the data through one device, instead of say, 7 Pro Minis.

Obviously, it is not so easy.

jremington:
You will have to remove both pullup resistors on at least 13 of the 14 sensors if you insist on this arrangement.

As said, you can leave two sets, as this works out to 1k1. The minimum value for standard (3mA) 3.3volt I2C.

Is the translating muxer out of the picture?
That could solve both pull up and 5volt Arduino problems.
Leo..

I'd really like to avoid using translating muxer, only as a last resort. I read on the Arduino Playground that all I have to do is connect each AD0 to a digital output:

"Using more than two MPU-6050 sensors can be achieved by connecting each of the AD0 pins to a separate output of the Arduino.
At this moment (15 July 2014) it is not known if this trick works for the MPU-6050.

Update March 25 2016: This trick is confirmed working nicely using three GY-521 breakouts along with an ESP8266 wifi/microcontroller (NodeMCU)."

(Arduino Playground - MPU-6050)

How is this able to work?

The pin AD0 sets the MPU-6050 at I2C address 0x68 or 0x69.

It turns out that this is not done at power up, but AD0 can change the I2C address at any time to 0x68 or 0x69.
If all AD0 pins of all MPU-6050 chips are set HIGH (3.3V), then all the MPU-6050 chips are at I2C address 0x69.

That I2C address of 0x69 is not used at all.
The AD0 of only one MPU-6050 is turned low, and the sketch communicates via de I2C bus to I2C address 0x68.
After that, the AD0 is set HIGH, and an other MPU-6050 is selected by setting it at address 0x68.

Koepel:
The pin AD0 sets the MPU-6050 at I2C address 0x68 or 0x69.

It turns out that this is not done at power up, but AD0 can change the I2C address at any time to 0x68 or 0x69.
If all AD0 pins of all MPU-6050 chips are set HIGH (3.3V), then all the MPU-6050 chips are at I2C address 0x69.

That I2C address of 0x69 is not used at all.
The AD0 of only one MPU-6050 is turned low, and the sketch communicates via de I2C bus to I2C address 0x68.
After that, the AD0 is set HIGH, and an other MPU-6050 is selected by setting it at address 0x68.

This is what my sketch does, correct? So, if I convert my Arduino to 3.3V, it should theoretically be able to work, right?

Yes, more or less.

I prefer this:

void setup() {  //  setup method
  Serial.begin(9600);
  Wire.begin();  //starts I2C communication

  for (int i = 22; i <= 35; i++) {
    pinMode(i, OUTPUT);  // defines pins as output pins
    digitalWrite( i, HIGH);   // park the sensor at 0x69
  }

  for (int i = 22; i <= 35; i++) {
    digitalWrite( i, LOW);    // set this sensor at 0x68
    gyro.initialize();  //initializes MPU6050 sensor at 0x68
    digitalWrite( i, HIGH);   // park this sensor at 0x69
  }
}

void loop() {  //main method
  for (int i = 22; i <= 35; i++) {
    digitalWrite( i, LOW);    // set this sensor at 0x68
    gyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);  //calls values from sensor at 0x68
    digitalWrite( i, HIGH);   // park this sensor at 0x69

    ax = map(ax, -17000, 17000, 0, 180);  //maps x axis rotation values from 0 to 180
    ...

I don't know which library you use, but I assume that gyro.initialize has to be done for every sensor.