Adafruit TCA9548A I2C Multiplexer addressing

Hi,

I am using the TCA9548A Multiplexer to connect 8 SHT31 sensors to an arduino UNO. However when I use the provided scanner code from the Adafruit tutorial, it returns with "Found I2C 0x0" before "Found I2C 0x44" (the address of the sensor). I initially thought this wouldn't be a problem as the sensor's address was still found, but when I upload my code to use the sensors through the multiplexer, it comes back with "Couldn't find SHT31". Is this a problem with a faulty multiplexer, or is there a problem with my code? I only included one sensor in the code just to test it - the sensor works fine when connected directly to the arduino UNO.

#include <Wire.h>
#include "Adafruit_SHT31.h"

#define TCAADDR 0x70

bool enableHeater = false;
uint8_t loopCnt = 0; //Used to count to 30 for turning the heater on - Don't want heater at all?

Adafruit_SHT31 sht31 = Adafruit_SHT31(0);

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

void setup() {
  Serial.begin(9600);

  while (!Serial)
    delay(10);     // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("SHT31 test");
  
  /* Initialise the 1st sensor */
  tcaselect(0);
  if (! sht311.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT31");
    while (1) delay(1);
  }
  
}
void loop() {
  // put your main code here, to run repeatedly:
  float t1 = sht31.readTemperature();
  float h1 = sht31.readHumidity();

  //Print first sensor readings
  tcaselect(1);
  Serial.print("Sensor 1 - ");
  if (! isnan(t1)) {  // check if 'is not a number'
    Serial.print("Temp *C = "); Serial.print(t1); Serial.print("\t\t"); //Don't know what this "\t\t" was for in example
  } else { 
    Serial.println("Failed to read temperature");
  }
  
  if (! isnan(h1)) {  // check if 'is not a number'
    Serial.print("Hum. % = "); Serial.println(h1);
  } else { 
    Serial.println("Failed to read humidity");
  }

}

I would like to help but I cannot find your schematic that you drew showing how you wired it nor do I see any of the pull up resistors required on the SPI bus. If the hardware is not correct the software cannot be correct.

I doubt that you connect the SHT-31 directly. But you failed yet to link to the breakout board your using. I agree with gilshultz that a wiring diagram is also needed.

Apologies for not including a wiring diagram. My arrangement is demonstrated below. The SHT31 already has 10k pull-up resistors to their Vin.

I followed the Adafruit tutorial for wiring the multiplexer, which is as shown here (using different sensors):

You select output 0 but connected to output 1.

1 Like

Apologies, I tried all the outputs to see if just one was faulty and changed the code accordingly.

Assuming you used the correct bus number in both tcaselect() calls, I don't see a reason why above code shouldn't work, given you removed also the 0 from this call:

Without a Wire instance the code cannot work.

1 Like

I just double checked running the code with the correct bus number in both tcaselect() calls, and with the 0 in that call removed, with the same results. The 0 in that call was to eventually be replaced with the below code for all 8 sensors, to "assign a Unique ID to each sensor" as was done on the multiplexer tutorial. Is this the right way to do that? I didn't really understand what the numbers in those calls represented.

Adafruit_SHT31 sht311 = Adafruit_SHT31(1);
Adafruit_SHT31 sht312 = Adafruit_SHT31(2);
Adafruit_SHT31 sht313 = Adafruit_SHT31(3);
Adafruit_SHT31 sht314 = Adafruit_SHT31(4);
Adafruit_SHT31 sht315 = Adafruit_SHT31(5);
Adafruit_SHT31 sht316 = Adafruit_SHT31(6);
Adafruit_SHT31 sht317 = Adafruit_SHT31(7);
Adafruit_SHT31 sht318 = Adafruit_SHT31(8);

I wrote "remove the 0" and I meant that! You cannot give a unique ID to the sensor by providing a wrong argument to a constructor!

The call must be:

Adafruit_SHT31 sht31 = Adafruit_SHT31();

The only acceptable argument is the default argument and believe me the compiler does include that better and with less typos than you ever can (that why I don't repeat it here).

1 Like

Nice picture but Power source is not shown, Required Pull Ups for the I2C are not shown and other items.

The I2C multiplexer has pullups on the main I2C bus (SDA and SCL). The sensor module has pullups for SDA0 and SCL0. So both sides have pullups somewhere. I think that is okay.

I see the confusion.
The phrase "Assign a unique ID to this sensor" comes from this sketch: https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout/wiring-and-test.
However, the example is with the "Adafruit_HMC5883_Unified" class, which takes an identifier as parameter and you use the "Adafruit_SHT31" which does not have that identifier (it does have a parameter, but that can not be used for the multiplexer).

1 Like

Hi, yes what Koepel has said was exactly why I am confused. I have now made changes to the code as such:

//Okay this is "full running" for 3 sensors

#include <Arduino.h>
#include <Wire.h>
#include "Adafruit_SHT31.h"

#define TCAADDR 0x70

bool enableHeater = false;
uint8_t loopCnt = 0; //Used to count to 30 for turning the heater on - Don't want heater at all?

//Assign a unique ID to each sensor?
Adafruit_SHT31 sht311 = Adafruit_SHT31();
Adafruit_SHT31 sht312 = Adafruit_SHT31();
Adafruit_SHT31 sht313 = Adafruit_SHT31();


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

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  while (!Serial)
    delay(10);     // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("All 8 SHT31 test");
  
  /* Initialise the 1st sensor */
  tcaselect(0);
  if (! sht311.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT311");
    while (1) delay(1);
  }
  
  /* Initialise the 2nd sensor */
  tcaselect(1);
  if (! sht312.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT312");
    while (1) delay(1);
  }
  
  /* Initialise the 3rd sensor */
  tcaselect(2);
  if (! sht313.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT313");
    while (1) delay(1);
  }

}

void loop() {
  // put your main code here, to run repeatedly:
  float t1 = sht311.readTemperature();
  float h1 = sht311.readHumidity();
  float t2 = sht312.readTemperature();
  float h2 = sht312.readHumidity();
  float t3 = sht313.readTemperature();
  float h3 = sht313.readHumidity();

  //Print first sensor readings
  tcaselect(0);
  Serial.print("Sensor 1 - ");
  if (! isnan(t1)) {  // check if 'is not a number'
    Serial.print("Temp *C = "); Serial.print(t1); Serial.print("\t\t"); //Don't know what this "\t\t" was for in example
  } else { 
    Serial.println("Failed to read temperature");
  }
  
  if (! isnan(h1)) {  // check if 'is not a number'
    Serial.print("Hum. % = "); Serial.println(h1);
  } else { 
    Serial.println("Failed to read humidity");
  }

  //Print second sensor readings
  tcaselect(1);
  Serial.print("Sensor 2 - ");
  if (! isnan(t2)) {  // check if 'is not a number'
    Serial.print("Temp *C = "); Serial.print(t2); Serial.print("\t\t"); //Don't know what this "\t\t" was for in example
  } else { 
    Serial.println("Failed to read temperature");
  }
  
  if (! isnan(h2)) {  // check if 'is not a number'
    Serial.print("Hum. % = "); Serial.println(h2);
  } else { 
    Serial.println("Failed to read humidity");
  }
  
  //Print third sensor readings
  tcaselect(2);
  Serial.print("Sensor 3 - ");
  if (! isnan(t3)) {  // check if 'is not a number'
    Serial.print("Temp *C = "); Serial.print(t3); Serial.print("\t\t"); //Don't know what this "\t\t" was for in example
  } else { 
    Serial.println("Failed to read temperature");
  }
  
  if (! isnan(h3)) {  // check if 'is not a number'
    Serial.print("Hum. % = "); Serial.println(h3);
  } else { 
    Serial.println("Failed to read humidity");
  }

  delay(1000); //Delay between each reading?
  }

The problem I am having now is that whilst the code is running, the temperature/humidity readings for all three sensors are showing the third sensor readings. Would anybody be able to help? I would assume it is still a problem with the Unique ID for each sensor. The diagram is the same, just with three sensors wired in.

Every time !
You have to select the right I2C bus every time you want to use a sensor.

void loop() {
  tcaselect(0);
  float t1 = sht311.readTemperature();
  float h1 = sht311.readHumidity();
  tcaselect(1);
  float t2 = sht312.readTemperature();
  float h2 = sht312.readHumidity();
  tcaselect(2);
  float t3 = sht313.readTemperature();
  float h3 = sht313.readHumidity();

The sht311,sht312,sht313 can be put together in an array. That makes the code smaller, easier to read and easier to maintain.

// Create an array objects, the constructor is called for every element.
Adafruit_SHT31 sht31[3];

void setup()
{
  for( int i=0; i<3; i++)
  {
    if( ! sht31[i].begin(0x44) ...
1 Like

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