1

enter image description hereAnybody here have tried connecting multiple MPU9250 into multiplexer. Anyway, I've used the HD74LS151 as the substitute for the 74HC4051 multiplexer. I already tried running the program and just followed how it is connected as it is connected like in the picture. Please see the attached image in here.

Right after running the code I just only got zeros on the output. I hope someone could help me figure out what's going on with my program or the connections of my pins.

And here is the code I used:

    #include <I2Cdev.h>
    #include <MPU6050.h>

    // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE    implementation
    // is used in I2Cdev.h
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
    #endif

    // class default I2C address is 0x68
    // specific I2C addresses may be passed as a parameter here
    // AD0 low = 0x68 (default for InvenSense evaluation board)
    // AD0 high = 0x69
    MPU6050 mpu_0(0x68);
    MPU6050 mpu_1(0x68);
    MPU6050 mpu_2(0x68);
    MPU6050 mpu_3(0x68);
    //MPU6050 accelgyro(0x69); // <-- use for AD0 high

    int16_t ax_0, ay_0, az_0, ax_1, ay_1, az_1, ax_2, ay_2, az_2, ax_3, ay_3, az_3;
    int16_t gx_0, gy_0, gz_0, gx_1, gy_1, gz_1, gx_2, gy_2, gz_2, gx_3, gy_3, gz_3;

   // uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
  // list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
 // not so easy to parse, and slow(er) over UART.
 #define OUTPUT_READABLE_ACCELGYRO

 // uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
 // binary, one right after the other. This is very fast (as fast as possible
// without compression or data loss), and easy to parse, but impossible to read
// for a human.
//#define OUTPUT_BINARY_ACCELGYRO

 #define LED_PIN 13
 bool blinkState = false;

 //Mux control pins
 int s0 = 5;
 int s1 = 6;
 int s2 = 7;

 //Mux in "SIG" pin
 int SIG_pin = 0;

 const int MPU=0x68;

 void setup() {

  pinMode(s0, OUTPUT); 
  pinMode(s1, OUTPUT); 
  pinMode(s2, OUTPUT); 

  //    delay(5);
  //    Wire.begin();
  //    Wire.beginTransmission(MPU);
  //    Wire.write(0x6B);  // PWR_MGMT_1 register
  //    Wire.write(0);     // set to zero (wakes up the MPU-6050)
  //    Wire.endTransmission(true);
  //    delay(15);
 //
 //    digitalWrite(s0, HIGH);
 //    digitalWrite(s1, LOW);
 //    digitalWrite(s2, LOW);
//    delay(5);
//    
//    Wire.begin();
//    Wire.beginTransmission(MPU);
//    Wire.write(0x6B);  // PWR_MGMT_1 register
//    Wire.write(0);     // set to zero (wakes up the MPU-6050)
//    Wire.endTransmission(true);
//    delay(15);

// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
    Fastwire::setup(400, true);
#endif

// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(38400);

// ================= MPU: 0 =================
digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
delay(5);
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);  // PWR_MGMT_1 register
Wire.write(0);     // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
delay(15);
mpu_0.initialize();
Serial.println("Testing device connections #0 ...");
Serial.println(mpu_0.testConnection() ? "MPU6050 connection #0 successful" :      "MPU6050 connection #0 failed");
delay(5);

// ================= MPU: 1 =================
digitalWrite(s0, HIGH);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
delay(5);
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);  // PWR_MGMT_1 register
Wire.write(0);     // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
delay(15);
mpu_1.initialize();
Serial.println("Testing device connections #1 ...");
Serial.println(mpu_1.testConnection() ? "MPU6050 connection #1 successful" :  "MPU6050 connection #1 failed");
delay(5);

// ================= MPU: 2 =================
digitalWrite(s0, LOW);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
delay(5);
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);  // PWR_MGMT_1 register
Wire.write(0);     // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
delay(15);
mpu_2.initialize();
Serial.println("Testing device connections #2 ...");
Serial.println(mpu_2.testConnection() ? "MPU6050 connection #2 successful" : "MPU6050 connection #2 failed");
delay(5);

// ================= MPU: 3 =================
digitalWrite(s0, HIGH);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
delay(5);
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);  // PWR_MGMT_1 register
Wire.write(0);     // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
delay(15);
mpu_3.initialize();
Serial.println("Testing device connections #3 ...");
Serial.println(mpu_3.testConnection() ? "MPU6050 connection #3 successful" : "MPU6050 connection #3 failed");
delay(5);

// use the code below to change accel/gyro offset values
/*
Serial.println("Updating internal sensor offsets...");
// -76  -2359   1688    0   0   0
Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
Serial.print("\n");
accelgyro.setXGyroOffset(220);
accelgyro.setYGyroOffset(76);
accelgyro.setZGyroOffset(-85);
Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
Serial.print("\n");
*/

// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}

void loop() {
// read raw accel/gyro measurements from device
//    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

// these methods (and a few others) are also available
//accelgyro.getAcceleration(&ax, &ay, &az);
//accelgyro.getRotation(&gx, &gy, &gz);

// ================= MPU: 0 =================
digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
delay(5);
mpu_0.getMotion6(&ax_0, &ay_0, &az_0, &gx_0, &gy_0, &gz_0);
#ifdef OUTPUT_READABLE_ACCELGYRO
    Serial.print("#0\ta/g:\t");
    Serial.print(ax_0); Serial.print("\t");
    Serial.print(ay_0); Serial.print("\t");
    Serial.print(az_0); Serial.print("\t");
    Serial.print(gx_0); Serial.print("\t");
    Serial.print(gy_0); Serial.print("\t");
    Serial.println(gz_0);
  #endif
  delay(5);

// ================= MPU: 1 =================
digitalWrite(s0, HIGH);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
delay(5);
mpu_1.getMotion6(&ax_1, &ay_1, &az_1, &gx_1, &gy_1, &gz_1);
#ifdef OUTPUT_READABLE_ACCELGYRO
    Serial.print("#1\ta/g:\t");
    Serial.print(ax_1); Serial.print("\t");
    Serial.print(ay_1); Serial.print("\t");
    Serial.print(az_1); Serial.print("\t");
    Serial.print(gx_1); Serial.print("\t");
    Serial.print(gy_1); Serial.print("\t");
    Serial.println(gz_1);
#endif
delay(5);

// ================= MPU: 2 =================
digitalWrite(s0, LOW);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
delay(5);
mpu_2.getMotion6(&ax_2, &ay_2, &az_2, &gx_2, &gy_2, &gz_2);
#ifdef OUTPUT_READABLE_ACCELGYRO
    Serial.print("#2\ta/g:\t");
    Serial.print(ax_2); Serial.print("\t");
    Serial.print(ay_2); Serial.print("\t");
    Serial.print(az_2); Serial.print("\t");
    Serial.print(gx_2); Serial.print("\t");
    Serial.print(gy_2); Serial.print("\t");
    Serial.println(gz_2);
   #endif
   delay(5);

   // ================= MPU: 3 =================
   digitalWrite(s0, HIGH);
   digitalWrite(s1, HIGH);
   digitalWrite(s2, LOW);
   delay(5);
   mpu_3.getMotion6(&ax_3, &ay_3, &az_3, &gx_3, &gy_3, &gz_3);
   #ifdef OUTPUT_READABLE_ACCELGYRO
    Serial.print("#3\ta/g:\t");
    Serial.print(ax_3); Serial.print("\t");
    Serial.print(ay_3); Serial.print("\t");
    Serial.print(az_3); Serial.print("\t");
    Serial.print(gx_3); Serial.print("\t");
    Serial.print(gy_3); Serial.print("\t");
    Serial.println(gz_3);
    #endif
    delay(5);

   //    #ifdef OUTPUT_BINARY_ACCELGYRO
     //        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax &    0xFF));
     //        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
     //        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
      //        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
      //        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
     //        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
     //    #endif

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
   }

Cheers!

16
  • What attached image? What code?
    – Nick Gammon
    Feb 1, 2016 at 4:18
  • What sort of Arduino is it?
    – Nick Gammon
    Feb 1, 2016 at 4:21
  • @NickGammon I posted the codes and the photo above. Thanks :) It's arduino mega..
    – Thomas
    Feb 1, 2016 at 4:48
  • This seems remarkably similar to your other question
    – Nick Gammon
    Feb 1, 2016 at 5:26
  • Yes, @NickGammon but this time I tried connecting it to a multiplexer.
    – Thomas
    Feb 1, 2016 at 5:33

1 Answer 1

1

Your concept sounded sensible enough so I gave it a try-out.

Multiplexed I2C

First point is: The master always generates the clock so we don't need to multiplex that. We only need to multiplex the data (SDA).

Code snippet:

// the multiplexer address select lines (A/B/C)
const byte addressA = 6; // low-order bit
const byte addressB = 5;
const byte addressC = 4; // high-order bit

int selectTarget (const byte which)
  {
  // select correct MUX channel
  digitalWrite (addressA, (which & 1) ? HIGH : LOW);  // low-order bit
  digitalWrite (addressB, (which & 2) ? HIGH : LOW);
  digitalWrite (addressC, (which & 4) ? HIGH : LOW);  // high-order bit
  }  // end of readSensor

All you have to do is call selectTarget(n) where n is 0 to 7, and you redirect SDA to the desired chip. I suggest a 4.7k pull-up on the target side so that the line is pulled high when not selected.

I tested it out and it seems to work OK.


The beauty of this setup is that you can multiplex 8 devices (eg. sensors) which happen to have the same I2C address, with only one additional chip. And, you can get 16-channel multiplexers if you want to take this further. Of course, in the code you still have to select the correct I2C address for the chip.

3
  • Oh great, @NickGammon ! :D You've given me hope to continue this project. But, can I ask you the whole code you used? I tried reediting the code I used with the one you added, and I'm still confused on where should I put the selectTarget you are telling me to do. Thanks.
    – Thomas
    Feb 2, 2016 at 6:26
  • I think it is important to emphasize that 74LS151 cannot replace the HC4051 in the circuit above. The HC4051 is acting as a switch and the I2C slave device can drive the signal. If using a 74LS151 the clock signal can be multiplexed instead. The data signal is then common. The third alternative is to use a digital pin to control the MPU9X50 AD0 pin. Feb 2, 2016 at 6:34
  • My code was just testing talking to a couple of other Arduinos using the code on my I2C page - with modifications. I don't know about the 74LS151. Your original schematic in the question has 74HCT4051 on it.
    – Nick Gammon
    Feb 2, 2016 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.