Multiple TCA9548A Multiplexers on Arduino Mega 2560

I am trying to connect 16 MPU6050's to two TCA9458A multiplexers (8 MPUs on each).
I have tested my MPUs, my TCA9548A's and they are all working correctly. Using one TCA9548A has worked for reading 8 MPU's, yet the issue is when I try to use two TCA9548A's.
The following code, and my first trial is:
Connecting 1 MPU6050 to channel 0 on the first TCA9548A (Address = 0x70)
Connecting 1 MPU6050 to channel 0 on the second TCA9548A (Address = 0x71)
The SDAs & SCLs of each TCA9548A is connected in the series and then connected to the SDA and SCL ports on the Arduino (Pins 20 & 21) respectively.
The problem is that both print statements of the MPUs are identical, even if I keep one still and tilt the other, they both output the tilted values. Essentially both MPU outputs identical values and there seems to be some sort of cross interference/communication. Any suggestions to fix this?

#include <Wire.h>
#include <MPU6050.h>

#define TCA1_ADDRESS 0x70 // Address of first TCA9548A
#define TCA2_ADDRESS 0x71 // Address of second TCA9548A

MPU6050 mpu[2];

void setup() {
  Wire.begin();
  Serial.begin(115200);
  delay(1000);
  Serial.println("Begin");
  
  // Initialize the first MPU
  TCASelect(TCA1_ADDRESS, 0);
  mpu[0].initialize();
  
  // Initialize the second MPU
  TCASelect(TCA2_ADDRESS, 0);
  mpu[1].initialize();
}

void loop() {
  int16_t ax, ay, az, gx, gy, gz;
  
  // Select channel 0 on first TCA9548A
  TCASelect(TCA1_ADDRESS, 0);
  
  // Read from MPU connected to channel 0 on first TCA9548A
  mpu[0].getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // Print acceleration values
  Serial.print("Y1: ");
  Serial.print(ay);

  // Select channel 0 on second TCA9548A
  TCASelect(TCA2_ADDRESS, 0);
  
  // Read from MPU connected to channel 0 on second TCA9548A
  mpu[1].getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // Print acceleration values
  Serial.print(", Y2: ");
  Serial.println(ay);
}

void TCASelect(uint8_t i2c_address, uint8_t bus) {
  Wire.beginTransmission(i2c_address);
  Wire.write(1 << bus);
  Wire.endTransmission();
}

One problem I noticed right off is you are initializing the second MPU on Port 1 but then trying to read Port 0.

// Initialize the second MPU
  TCASelect(TCA2_ADDRESS, 1);
// Select channel 0 on second TCA9548A
  TCASelect(TCA2_ADDRESS, 0);

Good catch, thanks. Although I made this change and the issue is still apparent. The outputs are interfering with each other, and I can't read them separately.

I've seen this problem many times before. The problem is that both multiplexers are connecting one channel to the bus, and each channel has an identical sensor with the same address, so you have 2 sensors with the same address visible on the bus at the same time.

Your code needs to make sure that only one of the two multiplexers has a channel selected at any time.

But do you need 2 multiplexers? Most MPU6050 boards have an address select pin, so you can put 2 sensors on each channel of a single multiplexer.

If you have 16 Mega pins free, you can connect 16 MPU without a multiplexer.

1 Like

You can de-select all channels on a TCA9548A by writing 0 to the multiplexer.

  Wire.beginTransmission(i2c_address);
  Wire.write(0);
  Wire.endTransmission();
1 Like

Alternatively

TCASelect(TCA2_ADDRESS, 8);

will probably also work.

Welcome to the forum.

If I combine what the others wrote and add the known 'trick' and the software I2C, then I get these options:

  1. Sixteen MPU-6050 modules at the same address. Two multiplexers. Disable the other multiplexer as david_2018 wrote. No problem with 3.3/5V on the I2C bus, because the multiplexer can solve that. It is easier to overcome a longer cable for the I2C bus, because the I2C bus is activated for just one path to one sensor.
  2. One multiplexer, each with 2 sensors on a (sub) I2C bus as PaulRB wrote. One sensor at address 0x68, the other at 0x69. No problem with 3.3/5V on the I2C bus, because the multiplexer can solve that.
  3. Using the known 'trick'. No multiplexer. Connect 16 digital output pins of the Arduino to each AD0 of each sensor module. Keep them all at I2C address 0x69. Bring one sensor to 0x68 and use that sensor. When you are ready with that sensor, then set it to 0x69 again. It is not allowed to use a 5V digital Arduino output to the AD0 of the sensor. You need a 3.3V Arduino board. I suggest the Raspberry Pi Pico.
  4. With software I2C. It is possible to share the SCL signal. You would need 9 digital pins for 8 software I2C buses, each I2C bus with a sensors are at 0x68 and 0x69. This is almost not possible with a 5V board, therefor you also need a 3.3V board for this option.

If you look at your MPU-6050 modules, what do you see :thinking: You are probably looking at a bunch of counterfeit cheap modules.
The official standard give you a length for the I2C bus of about 6mm to each module when there are 16 devices on the same I2C bus. That is six millimeters. If you want more length, then you must know how to do that. How long are the wires ? Can you tell what the project is about ?
Did you know that with 16 sensors on the I2C bus, you can read al of them at about 10 times per second if you are lucky. I think it will be 5 times per second.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.