Issue connecting the MLX90395 sensor to my Arduino MKR WIFI 1010 through the TCA9548A multiplexer

I'm trying to do a data acquisition test of a single MLX90395 sensor with my Arduino MKR WIFI 1010 through the TCA9548A I2C address multiplexer and things are not going well. (To clarify, I obviously want to connect more sensors later, that's why I'm using the TCA9548A address multiplexer, but at the moment I'm only testing with one sensor...)

As for the pre-checks I've done before getting to my problem...

On the one hand, the TCA9548A multiplexer is being well recognized by the arduino, since when doing an i2c scanner it finds a device at address 0x70 which is that of the device in question (addresses 0x60 and 0x6B are from the Arduino MKR WIFI modules 1010, so ignore them), the result is:

Scanning I2C 7-bit address range 0x08 to 0x77.
I2C device found at address 0x60
I2C device found at address 0x6B
I2C device found at address 0x70
Scan complete.  Devices found: 3

On the other hand, the TCA9548A is correctly recognizing that among its 8 possible I2C channels (SD0 SC0, ... , SD7 SC7), my MLX90395 sensor (whose address is 0x0C) is connected to channel 0, the result is:

TCAScanner ready!
TCA Port #0
Found I2C 0x0
Found I2C 0xC
Found I2C 0x60
Found I2C 0x6B
TCA Port #1
Found I2C 0x60
Found I2C 0x6B
TCA Port #2
Found I2C 0x60
Found I2C 0x6B
TCA Port #3
Found I2C 0x60
Found I2C 0x6B
TCA Port #4
Found I2C 0x60
Found I2C 0x6B
TCA Port #5
Found I2C 0x60
Found I2C 0x6B
TCA Port #6
Found I2C 0x60
Found I2C 0x6B

Finally, regarding the sensor, I have already acquired its signal through the I2C protocol directly to my arduino, without the intermediate step of going through the multiplexer, and it works correctly.

Once the previous checks are done, I am trying to execute the following test code to see if I can acquire the output of the sensor passing through the multiplexer. In the program I use the Adafruit_MLX90395 library.

#include "Adafruit_MLX90395.h"
#include "Wire.h"

Adafruit_MLX90395 sensor = Adafruit_MLX90395(); // instance of the Adafruit_MLX90395 class

#define TCAADDR 0x70

void tcaselect(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission(); 
}

void setup(void){
  Serial.begin(9600);
  /* Wait for serial on USB platforms. */
  while (!Serial) {
      delay(10);
  }
  Serial.println("Selecting TCA port...");
  tcaselect(0);
  Serial.println("TCA port selected!");
  if (! sensor.begin_I2C()) {          // hardware I2C mode, can pass in address & alt Wire
    Serial.println("No sensor found ... check your wiring?");
    while (1) { delay(10); }
  }
  sensor.setOSR(MLX90395_OSR_8);
  sensor.setResolution(MLX90395_RES_17);
}

float Bx = 0;
float By = 0;
float Bz = 0;

void loop(void) {
  tcaselect(0);
  /* Get a new sensor event, normalized to uTesla */
  sensors_event_t event;
  sensor.getEvent(&event);
  Bx = event.magnetic.x;
  By = event.magnetic.y;
  Bz = event.magnetic.z;
  Serial.print(Bx);
  Serial.print("\t"); Serial.print(By); 
  Serial.print("\t"); Serial.print(Bz); 
  Serial.print("\t"); Serial.println(sqrt(pow(Bx,2)+pow(By,2 )+pow(Bz,2)));
}

The problem is that when I run it, I only get:

Selecting TCA port...

That is, it gets stuck at the point of tcaselect(0) and I don't understand why. It's like the multiplexer is preventing me from establishing a good I2C connection between my sensor and the Arduino.

The assembly of my project is this by the way:

I guess you used exactly the same code for the TCA9548A channel selection as in the posted sketch. As the hardware must also be the same (otherwise the MLX90395 wasn't found), I cannot see why the board should react that way. So I assume one of my above assumptions is wrong. Did you change the hardware? Did you use another channel selection code?

First of all thank you very much for your answer, the help is much needed :slight_smile:

I guess you used exactly the same code for the TCA9548A channel selection as in the posted sketch

Exactly, same code. More specifically, this is the code that I have used to obtain said output of the port information. Simply try to establish communication and if it is successful it will let you know. As you can see in this code, the tcaselect() does work fine!!!

#include "Wire.h"

#define TCAADDR 0x70

void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}


// standard Arduino setup()
void setup()
{
    while (!Serial);
    delay(1000);

    Wire.begin();
    
    Serial.begin(115200);
    Serial.println("\nTCAScanner ready!");
    
    for (uint8_t t=0; t<8; t++) {
      tcaselect(t);
      Serial.print("TCA Port #"); Serial.println(t);

      for (uint8_t addr = 0; addr<=127; addr++) {
        if (addr == TCAADDR) continue;

        Wire.beginTransmission(addr);
        if (!Wire.endTransmission()) {
          Serial.print("Found I2C 0x");  Serial.println(addr,HEX);
        }
      }
    }
    Serial.println("\ndone");
}

void loop() 
{
}

Did you use another channel selection code?

Yes, I already tried using the remaining 7 channels in addition to channel 0 and I get the same result.

Did you change the hardware?

By this you mean to change the sensor or even the multiplexer itself? If the multiplexer is being detected, and the sensor works fine by itself, I don't think it's the hardware that is failing.

My strongest guess is that I'm not setting up the I2C communication right, but I don't understand why...

Why do you think that? You said earlier:

Was that also with this same code?

Yes, making the direct I2C connection between the arduino and the sensor I have had no problems. In fact, the code is basically identical to the one I attached in the first post, except that I don't use the tcaseselect() function. Meaning, when I call the .begin_I2C() function I don't previously call tcaselect(0) and the same thing when I capture the event and take the measurement of the magnetic field measured by the corresponding sensor.

But I don't understand why by putting the multiplexer in the equation my whole hierarchy to establish the I2C connections falls ... Or at least that's what I think is happening....

If not, I don't know why else the code is failing ...

You could try the exactly identical code, including the tcaseselect(). As long as the sensor is connected directly to the Arduino, the channel setting of the multiplexer should make no difference.

Do you have any other i²c devices that you could test? Other models of sensor, displays, RTC...

The only difference of the two sketches that may have an influence on the output you get is the delay(1000) call. Can you insert that into your new code too and try again? Maybe one of the chips need a bit more time to get ready.