Using MUX with SHTC3 Sensors

I’m attempting to use 12 SHTC3 sensors in one project. I’m doing an iterative process and am able to use one SHTC3 sensor connected directly to the Red Board. When I try to access the SHTC sensor through a MUX board based on a combination of the example SHTC3 code and MUX code (below), I get the following output:

Qwiic Mux Shield Read Example

Enabled: 0

Beginning sensor. Result = Unknown return code

Disabled: 0

Mux Shield online

Enabled: 0

0 RH = 14.12%, T = -4.53 deg F

Disabled: 0

Enabled: 0

0 RH = 14.12%, T = -4.53 deg F

Disabled: 0

I have the Enabled and Disabled lines just to verify that I got through the enableMUXPort and disableMUXPort functions without error.

Here is my current setup:

Boards:

Red Board - https://www.sparkfun.com/products/15123

MUX - https://www.sparkfun.com/products/16784

SHTC3 - https://www.sparkfun.com/products/16467

Code:

#include <Wire.h>
#include "SparkFun_SHTC3.h" // Click here to get the library: http://librarymanager/All#SparkFun_SHTC3

SHTC3 mySHTC3;              // Declare an instance of the SHTC3 class

#define NUMBER_OF_SENSORS 1
#define MUX_ADDR 0x70 //7-bit unshifted default I2C Address


void setup()
{
  Serial.begin(115200);
  while(Serial == false){};                                   // Wait for the serial connection to start up
  Serial.println("Qwiic Mux Shield Read Example");
  Wire.begin();

  //Initialize all the sensors
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to port X
    delay(250);
    //mySHTC3.begin();
    Serial.print("Beginning sensor. Result = ");           // Most SHTC3 functions return a variable of the type "SHTC3_Status_TypeDef" to indicate the status of their execution 
    errorDecoder(mySHTC3.begin());
    Serial.println("");
    disableMuxPort(x);
  }

  Serial.println("Mux Shield online");
}

void loop()
{
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to this port, and this port only

    SHTC3_Status_TypeDef result = mySHTC3.update();             // Call "update()" to command a measurement, wait for measurement to complete, and update the RH and T members of the object
    printInfo(x);                                               // This function is used to print a nice little line of info to the serial port

    disableMuxPort(x); //Tell mux to disconnect from this port
    delay(250); //Wait for next reading
  }
}



///////////////////////
// Utility Functions //
///////////////////////
void printInfo(int num)
{
  if(mySHTC3.lastStatus == SHTC3_Status_Nominal)              // You can also assess the status of the last command by checking the ".lastStatus" member of the object
  {
    Serial.print(num);  
    Serial.print("   RH = "); 
    Serial.print(mySHTC3.toPercent());                        // "toPercent" returns the percent humidity as a floating point number
    Serial.print("%, T = "); 
    Serial.print(mySHTC3.toDegF());                           // "toDegF" and "toDegC" return the temperature as a flaoting point number in deg F and deg C respectively 
    Serial.println(" deg F"); 
  }
  else
  {
    Serial.print("Update failed, error: "); 
    errorDecoder(mySHTC3.lastStatus);
    Serial.println();
  }
}

void errorDecoder(SHTC3_Status_TypeDef message)                             // The errorDecoder function prints "SHTC3_Status_TypeDef" resultsin a human-friendly way
{
  switch(message)
  {
    case SHTC3_Status_Nominal : Serial.print("Nominal"); break;
    case SHTC3_Status_Error : Serial.print("Error"); break;
    case SHTC3_Status_CRC_Fail : Serial.print("CRC Fail"); break;
    default : Serial.print("Unknown return code"); break;
  }
}

//Enables a specific port number
void enableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Set the wanted bit to enable the port
  settings |= (1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
  Serial.print("Enabled: ");
  Serial.println(portNumber);
}

//Disables a specific port number
void disableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Clear the wanted bit to disable the port
  settings &= ~(1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
  Serial.print("Disabled: ");
  Serial.println(portNumber);
}

Is there something unique about the SHTC3 implementation that is different from the MMA8452Q (from the MUX example code) that requires a significantly different method of getting data? Any help would be appreciated.

Do you get the same values if you simply use just the SHTC3?

The read from one SHTC3 sensor connected directly to the redboard just fine, using the exact same code.

Qwiic Mux Shield Read Example

Beginning sensor. Result = Nominal

Mux Shield online

0 RH = 34.29%, T = 63.50 deg F

0 RH = 34.29%, T = 63.49 deg F

0 RH = 34.28%, T = 63.47 deg F

0 RH = 34.29%, T = 63.58 deg F

0 RH = 34.27%, T = 63.47 deg F

0 RH = 34.29%, T = 63.52 deg F

0 RH = 34.28%, T = 63.49 deg F

Out of curiosity, why did you comment out ```
//mySHTC3.begin();

Before I decided to go to the forums, I was looking at if there was an init() function for SHTC3 like the MMA8452Q has. I have since uncommented it, but it does not seem to change the performance.

Okay, this is rather strange. Two things to confirm/try, rotate between all available mux ports try and use a different mux module. I’ll try looking a bit deeper on my end too.

Here is my updated code that visits all 8 ports: (I do have 8 sensors attached now)

#include <Wire.h>
#include "SparkFun_SHTC3.h" // Click here to get the library: http://librarymanager/All#SparkFun_SHTC3

SHTC3 mySHTC3;              // Declare an instance of the SHTC3 class

#define NUMBER_OF_SENSORS 8
#define MUX_ADDR 0x70 //7-bit unshifted default I2C Address


void setup()
{
  Serial.begin(115200);
  while(Serial == false){};                                   // Wait for the serial connection to start up
  Serial.println("Qwiic Mux Shield Read Example");
  Wire.begin();

  //Initialize all the sensors
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to port X
    delay(250);
    mySHTC3.begin();
    Serial.print("Beginning sensor. Result = ");           // Most SHTC3 functions return a variable of the type "SHTC3_Status_TypeDef" to indicate the status of their execution 
    errorDecoder(mySHTC3.begin());
    Serial.println("");
    disableMuxPort(x);
  }

  Serial.println("Mux Shield online");
}

void loop()
{
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to this port, and this port only
    
    SHTC3_Status_TypeDef result = mySHTC3.update();             // Call "update()" to command a measurement, wait for measurement to complete, and update the RH and T members of the object
    printInfo(x);                                               // This function is used to print a nice little line of info to the serial port

    disableMuxPort(x); //Tell mux to disconnect from this port
    delay(250); //Wait for next reading
  }
  Serial.println("");
}



///////////////////////
// Utility Functions //
///////////////////////
void printInfo(int num)
{
  if(mySHTC3.lastStatus == SHTC3_Status_Nominal)              // You can also assess the status of the last command by checking the ".lastStatus" member of the object
  {
    Serial.print(num);  
    Serial.print("   RH = "); 
    Serial.print(mySHTC3.toPercent());                        // "toPercent" returns the percent humidity as a floating point number
    Serial.print("%, T = "); 
    Serial.print(mySHTC3.toDegF());                           // "toDegF" and "toDegC" return the temperature as a flaoting point number in deg F and deg C respectively 
    Serial.println(" deg F"); 
  }
  else
  {
    Serial.print("Update failed, error: "); 
    errorDecoder(mySHTC3.lastStatus);
    Serial.println();
  }
}

void errorDecoder(SHTC3_Status_TypeDef message)                             // The errorDecoder function prints "SHTC3_Status_TypeDef" resultsin a human-friendly way
{
  switch(message)
  {
    case SHTC3_Status_Nominal : Serial.print("Nominal"); break;
    case SHTC3_Status_Error : Serial.print("Error"); break;
    case SHTC3_Status_CRC_Fail : Serial.print("CRC Fail"); break;
    default : Serial.print("Unknown return code"); break;
  }
}

//Enables a specific port number
void enableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Set the wanted bit to enable the port
  settings |= (1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
  //Serial.print("Enabled: ");
  //Serial.println(portNumber);
}

//Disables a specific port number
void disableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Clear the wanted bit to disable the port
  settings &= ~(1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
  //Serial.print("Disabled: ");
  //Serial.println(portNumber);
}

And here is the output I get:

Qwiic Mux Shield Read Example

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Mux Shield online

0 RH = 0.01%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 0.00%, T = -43.92 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 0.05%, T = -43.92 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 0.00%, T = -43.91 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 0.01%, T = -43.91 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

My second board crashed at port 2. I did try different sensors and cords on it, and I think its a bad output, but I am more worried about getting the other 7 ports working rather than figuring out what is wrong with port 2.

Qwiic Mux Shield Read Example

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Mux Shield online

0 RH = 14.12%, T = -4.53 deg F

1 RH = 0.01%, T = -4.53 deg F

Update failed, error: Error

Here’s the second board with port 2 unplugged.

Qwiic Mux Shield Read Example

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Beginning sensor. Result = Unknown return code

Mux Shield online

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 14.12%, T = -4.53 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 14.12%, T = -4.53 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

0 RH = 14.12%, T = -4.53 deg F

1 RH = 14.12%, T = -4.53 deg F

2 RH = 14.12%, T = -4.53 deg F

3 RH = 14.12%, T = -4.53 deg F

4 RH = 14.12%, T = -4.53 deg F

5 RH = 0.01%, T = -4.53 deg F

6 RH = 14.12%, T = -4.53 deg F

7 RH = 14.12%, T = -4.53 deg F

Do you have any other Qwiic sensors that don’t have the default address 0x70?

^change from above: change this line in your code: #define MUX_ADDR 0x70 //7-bit unshifted default I2C Address to reflect: ```
#define MUX_ADDR 0x71 //7-bit unshifted default I2C Address

You are calling mySHTC3.begin(); twice. That’s probably the cause for the “Unknown return code” error.

My guess is that the SHTC3 driver is not re-entrant. It likely keeps track of some internal state or data and is getting confused when you switch devices behind its back. What I would do is create an array of objects, one per port.

SHTC3 mySHTC3[NUMBER_OF_SENSORS]; // Declare an array of instances of the SHTC3 class, one per mux port

and then in your loops, use the proper object from the array:

void loop()
{
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to this port, and this port only
    
    SHTC3_Status_TypeDef result = mySHTC3[x].update();             // Call "update()" to command a measurement, wait for measurement to complete, and update the RH and T members of the object
    printInfo(x);                                               // This function is used to print a nice little line of info to the serial port

    disableMuxPort(x); //Tell mux to disconnect from this port
    delay(250); //Wait for next reading
  }
  Serial.println("");
}

I don’t have either board to try this with, but it may help…

/mike

Thank you for all the help thus far! I am now able to read multiple sensors from one board. I am now running into two problems, which may be related.

  1. I am now only able to use a MUX board with address 0x71. Even when I use a MUX board with no solder and have in my code: #define MUX_ADDR 0x70, I am unable to read sensors on it.

  2. My project ultimately has me using twelve SHTC3 sensors, so I need to use a second MUX board. Whenever I try to use two boards at the same time (always making sure they have different addresses), my SHTC3 sensors stop responding.

Below is example output when I was using my board with address 0x71. I hooked up a second MUX (0x70) board around 10:59:33.

10:59:22.954 → Qwiic Mux Shield Read Example

10:59:23.227 → Beginning sensor. Result = Nominal

10:59:23.463 → Beginning sensor. Result = Error

10:59:23.733 → Beginning sensor. Result = Error

10:59:23.970 → Beginning sensor. Result = Nominal

10:59:24.242 → Beginning sensor. Result = Nominal

10:59:24.480 → Beginning sensor. Result = Error

10:59:24.718 → Beginning sensor. Result = Error

10:59:24.990 → Beginning sensor. Result = Error

10:59:24.990 → Mux Shield online

10:59:24.990 → 0 RH = 32.51%, T = 63.31 deg F

10:59:25.261 → Update failed, error: Error

10:59:25.499 → Update failed, error: Error

10:59:25.771 → 3 RH = 32.56%, T = 63.45 deg F

10:59:26.043 → 4 RH = 32.51%, T = 63.32 deg F

10:59:26.280 → Update failed, error: Error

10:59:26.518 → Update failed, error: Error

10:59:26.790 → Update failed, error: Error

10:59:27.027 →

10:59:27.061 → 0 RH = 32.54%, T = 63.31 deg F

10:59:27.298 → Update failed, error: Error

10:59:27.570 → Update failed, error: Error

10:59:27.807 → 3 RH = 32.59%, T = 63.43 deg F

10:59:28.079 → 4 RH = 32.49%, T = 63.27 deg F

10:59:28.351 → Update failed, error: Error

10:59:28.589 → Update failed, error: Error

10:59:28.828 → Update failed, error: Error

10:59:29.100 →

10:59:29.100 → 0 RH = 32.59%, T = 63.38 deg F

10:59:29.372 → Update failed, error: Error

10:59:29.610 → Update failed, error: Error

10:59:29.882 → 3 RH = 32.59%, T = 63.42 deg F

10:59:30.120 → 4 RH = 32.49%, T = 63.28 deg F

10:59:30.392 → Update failed, error: Error

10:59:30.630 → Update failed, error: Error

10:59:30.902 → Update failed, error: Error

10:59:31.139 →

10:59:31.139 → 0 RH = 32.55%, T = 63.37 deg F

10:59:31.411 → Update failed, error: Error

10:59:31.649 → Update failed, error: Error

10:59:31.921 → 3 RH = 32.60%, T = 63.46 deg F

10:59:32.192 → 4 RH = 32.50%, T = 63.26 deg F

10:59:32.430 → Update failed, error: Error

10:59:32.702 → Update failed, error: Error

10:59:32.940 → Update failed, error: Error

10:59:33.178 →

10:59:33.212 → 0 RH = 0.00%, T = -48.98 deg F

10:59:33.450 → 1 RH = 14.12%, T = -4.53 deg F

10:59:33.721 → 2 RH = 14.12%, T = -4.53 deg F

10:59:33.992 → 3 RH = 0.05%, T = -48.83 deg F

10:59:34.230 → 4 RH = 0.01%, T = -49.00 deg F

10:59:34.502 → 5 RH = 14.12%, T = -4.53 deg F

10:59:34.740 → 6 RH = 14.12%, T = -4.53 deg F

10:59:35.011 → 7 RH = 14.12%, T = -4.53 deg F

10:59:35.249 →

10:59:35.283 → 0 RH = 0.00%, T = -48.98 deg F

10:59:35.521 → 1 RH = 14.12%, T = -4.53 deg F

10:59:35.793 → 2 RH = 14.12%, T = -4.53 deg F

10:59:36.030 → 3 RH = 0.01%, T = -48.98 deg F

10:59:36.302 → 4 RH = 0.05%, T = -49.00 deg F

10:59:36.574 → 5 RH = 14.12%, T = -4.53 deg F

10:59:36.812 → 6 RH = 14.12%, T = -4.53 deg F

10:59:37.084 → 7 RH = 14.12%, T = -4.53 deg F

Here is my setup when the second MUX is attached.

This is the code I’m using currently, though I do have other code that does change the disable/enableMUXport functions to choose which MUX board I’m talking to. Right now, I am only concerned with having one MUX board continuing SHTC3 transmissions before I try to get two working.

#include <Wire.h>
#include "SparkFun_SHTC3.h" // Click here to get the library: http://librarymanager/All#SparkFun_SHTC3

#define NUMBER_OF_SENSORS 8
#define MUX_ADDR 0x71 //7-bit unshifted default I2C Address

SHTC3 mySHTC3[NUMBER_OF_SENSORS]; // Declare an array of instances of the SHTC3 class, one per mux port

void setup()
{
  Serial.begin(115200);
  while(Serial == false){};                                   // Wait for the serial connection to start up
  Serial.println("Qwiic Mux Shield Read Example");
  Wire.begin();

  //Initialize all the sensors
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to port X
    delay(250);
    Serial.print("Beginning sensor. Result = ");           // Most SHTC3 functions return a variable of the type "SHTC3_Status_TypeDef" to indicate the status of their execution 
    errorDecoder(mySHTC3[x].begin());
    Serial.println("");
    disableMuxPort(x);
  }

  Serial.println("Mux Shield online");
}

void loop()
{
  for (byte x = 0 ; x < NUMBER_OF_SENSORS ; x++)
  {
    enableMuxPort(x); //Tell mux to connect to this port, and this port only
    
    SHTC3_Status_TypeDef result = mySHTC3[x].update();
    printInfo(x);                                               // This function is used to print a nice little line of info to the serial port

    disableMuxPort(x); //Tell mux to disconnect from this port
    delay(250); //Wait for next reading
  }
  Serial.println("");
}



///////////////////////
// Utility Functions //
///////////////////////
void printInfo(int num)
{
  if(mySHTC3[num].lastStatus == SHTC3_Status_Nominal)              // You can also assess the status of the last command by checking the ".lastStatus" member of the object
  {
    Serial.print(num);  
    Serial.print("   RH = "); 
    Serial.print(mySHTC3[num].toPercent());                        // "toPercent" returns the percent humidity as a floating point number
    Serial.print("%, T = "); 
    Serial.print(mySHTC3[num].toDegF());                           // "toDegF" and "toDegC" return the temperature as a flaoting point number in deg F and deg C respectively 
    Serial.println(" deg F"); 
  }
  else
  {
    Serial.print("Update failed, error: "); 
    errorDecoder(mySHTC3[num].lastStatus);
    Serial.println();
  }
}

void errorDecoder(SHTC3_Status_TypeDef message)                             // The errorDecoder function prints "SHTC3_Status_TypeDef" resultsin a human-friendly way
{
  switch(message)
  {
    case SHTC3_Status_Nominal : Serial.print("Nominal"); break;
    case SHTC3_Status_Error : Serial.print("Error"); break;
    case SHTC3_Status_CRC_Fail : Serial.print("CRC Fail"); break;
    default : Serial.print("Unknown return code"); break;
  }
}

//Enables a specific port number
void enableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Set the wanted bit to enable the port
  settings |= (1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
}

//Disables a specific port number
void disableMuxPort(byte portNumber)
{
  if (portNumber > 7) portNumber = 7;

  Wire.beginTransmission(MUX_ADDR);
  //Read the current mux settings
  Wire.requestFrom(MUX_ADDR, 1);
  if (!Wire.available()) return; //Error
  byte settings = Wire.read();

  //Clear the wanted bit to disable the port
  settings &= ~(1 << portNumber);

  Wire.write(settings);
  Wire.endTransmission();
}

Even when I use a MUX board with no solder and have in my code: #define MUX_ADDR 0x70, I am unable to read sensors on it.

Yes, when your program writes 0x70 on the SDA (Data) line both the sensor and the Mux board will respond which results in gobbledy guck. Both of your Mux boards will have to be different addresses than 0x70 (physically modified and accounted for in code).

That was it, thanks Brandon!

No worries :slight_smile: there’s always some small hangup that’s easy to overlook. Best of luck with your project!