Using fourteen MCP9808 sensors with two TCA9548A multiplexer

Hi all

I want to create an experimental incubation system for reptile eggs. Ultimately it will switch on solid state relays for bang-bang controlling the temperature of incubation boxes (yes could have used PID but trying to keep things simple for now). For now, I'm trying to master the use of MCP9808 sensors with TCA9548A multiplexers.

At present I am testing each channel using a single pluggable MCP sensor. I am able to get readings from both multiplexers, at addresses 0x70 and 0x71, but in both cases, only in the Channel 0 position. When I remove the pluggable test MCP sensor and put it into any other SDA/SCL channel from 1 to 7, I get no reading.
Can anyone identify an obvious error in my code, or am I missing something critical regarding the addressing of devices connected through multiplexers?
Yes, I am certain that I could substantially reduce the amount of code by using something like a predefined array, but I'm trying to get to grips with the concepts underlying the use of the multiplexer before I get too clever.

Any assistance, regardless of snark, greatly appreciated.

See code below:

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

// Create the MCP9808 temperature sensor objects. One for each incubator, plus one for the inside of the enclosure, plus one for outside. 
Adafruit_MCP9808 tempsensor1 = Adafruit_MCP9808(); //SD0/SCL0 of MUX 1 - inc1
Adafruit_MCP9808 tempsensor2 = Adafruit_MCP9808(); //SD1/SCL1 of MUX 1 - inc2
Adafruit_MCP9808 tempsensor3 = Adafruit_MCP9808(); //SD2/SCL2 of MUX 1 - inc3
Adafruit_MCP9808 tempsensor4 = Adafruit_MCP9808(); //SD3/SCL3 of MUX 1 - inc4
Adafruit_MCP9808 tempsensor5 = Adafruit_MCP9808(); //SD4/SCL4 of MUX 1 - inc5
Adafruit_MCP9808 tempsensor6 = Adafruit_MCP9808(); //SD5/SCL5 of MUX 1 - inc6
Adafruit_MCP9808 tempsensor7 = Adafruit_MCP9808(); //SD6/SCL6 of MUX 1 - inc7
Adafruit_MCP9808 tempsensor8 = Adafruit_MCP9808(); //SD7/SCL7 of MUX 1 - inc8
Adafruit_MCP9808 tempsensor9 = Adafruit_MCP9808(); //SD0/SCL0 of MUX 2 - inc9
Adafruit_MCP9808 tempsensor10 = Adafruit_MCP9808(); //SD1/SCL1 of MUX 2 - inc10
Adafruit_MCP9808 tempsensor11 = Adafruit_MCP9808(); //SD2/SCL2 of MUX 2 - inc11
Adafruit_MCP9808 tempsensor12 = Adafruit_MCP9808(); //SD3/SCL3 of MUX 2 - inc12
Adafruit_MCP9808 tempsensor13 = Adafruit_MCP9808(); //SD4/SCL4 of MUX 2 - housing
Adafruit_MCP9808 tempsensor14 = Adafruit_MCP9808(); //SD5/SCL5 of MUX 2 - outside

//Define the multiplexer addresses
#define TCA1 0x70 //TCA1 has been set to default address
#define TCA2 0x71 //TCA2 has been set to different address

 //Function that expresses the multiplexer channel to be selected
void tcaselect (uint8_t i) {
  if (i > 7) return;

}


void setup() {
  Serial.begin(9600);
  Wire.begin();
  delay(1000); 
}

void loop() {

  //MEASURE TEMP FROM INCUBATOR 1
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(0); //Now that we have switched on TCA1, we select channel 0
  
  tempsensor1.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor1.setResolution(3); //Set resolution of tempsensor1
  tempsensor1.wake();   // wake up, ready to read!
  float temp1 = tempsensor1.readTempC();
  Serial.print("Temp on sensor 1: "); 
  Serial.print(temp1, 2); Serial.println(" *C "); 
  tempsensor1.shutdown_wake(1); // shutdown tempsensor1
     
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

    //MEASURE TEMP FROM INCUBATOR 2
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(1); //Now that we have switched on TCA1, we select channel 1
  
  tempsensor2.begin(0x18); //Activate tempsensor2, which is connected to channel 1 of multiplexer 1
  tempsensor2.setResolution(3); //Set resolution of tempsensor2
  tempsensor2.wake();   // wake up, ready to read!
  float temp2 = tempsensor2.readTempC();
  Serial.print("Temp on sensor 2: "); 
  Serial.print(temp2, 2); Serial.println(" *C "); 
  tempsensor2.shutdown_wake(1); // shutdown tempsensor1
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

    //MEASURE TEMP FROM INCUBATOR 3
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(2); //Now that we have switched on TCA1, we select channel 2
  
  tempsensor3.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor3.setResolution(3); //Set resolution of tempsensor1
  tempsensor3.wake();   // wake up, ready to read!
  float temp3 = tempsensor1.readTempC();
  Serial.print("Temp on sensor 3: "); 
  Serial.print(temp1, 2); Serial.println(" *C "); 
  tempsensor3.shutdown_wake(1); // shutdown tempsensor1
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

    //MEASURE TEMP FROM INCUBATOR 4
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(3); //Now that we have switched on TCA1, we select channel 3
  
  tempsensor4.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor4.setResolution(3); //Set resolution of tempsensor1
  tempsensor4.wake();   // wake up, ready to read!
  float temp4 = tempsensor4.readTempC();
  Serial.print("Temp on sensor 4: "); 
  Serial.print(temp4, 2); Serial.println(" *C "); 
  tempsensor4.shutdown_wake(1); // shutdown tempsensor1
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

    //MEASURE TEMP FROM INCUBATOR 5
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(4); //Now that we have switched on TCA1, we select channel 4
  
  tempsensor5.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor5.setResolution(3); //Set resolution of tempsensor1
  tempsensor5.wake();   // wake up, ready to read!
  float temp5 = tempsensor5.readTempC();
 Serial.print("Temp on sensor 5: "); 
 Serial.print(temp5, 2); Serial.println(" *C "); 
  tempsensor5.shutdown_wake(1); // shutdown tempsensor1
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
 delay(100);

    //MEASURE TEMP FROM INCUBATOR 6
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(5); //Now that we have switched on TCA1, we select channel 5
  
  tempsensor6.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor6.setResolution(3); //Set resolution of tempsensor1
  tempsensor6.wake();   // wake up, ready to read!
  float temp6 = tempsensor6.readTempC();
  Serial.print("Temp on sensor 6: "); 
  Serial.print(temp6, 2); Serial.println(" *C "); 
  tempsensor6.shutdown_wake(1); // shutdown tempsensor1
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

  //MEASURE TEMP FROM INCUBATOR 7
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(6); //Now that we have switched on TCA1, we select channel 6
  
  tempsensor7.begin(0x18); //Activate tempsensor1, which is connected to channel 0 of multiplexer 1
  tempsensor7.setResolution(3); //Set resolution of tempsensor1
  tempsensor7.wake();   // wake up, ready to read!
  float temp7 = tempsensor7.readTempC();
  Serial.print("Temp on sensor 7: "); 
  Serial.print(temp7, 2); Serial.println(" *C "); 
  tempsensor7.shutdown_wake(1); // shutdown tempsensor7
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);

  //MEASURE TEMP FROM INCUBATOR 8
  Wire.beginTransmission(TCA1);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA1
  
  tcaselect(7); //Now that we have switched on TCA1, we select channel 7
  
  tempsensor8.begin(0x18); //Activate tempsensor8, which is connected to channel 7 of multiplexer 1
  tempsensor8.setResolution(3); //Set resolution of tempsensor1
  tempsensor8.wake();   // wake up, ready to read!
  float temp8 = tempsensor8.readTempC();
  Serial.print("Temp on sensor 8: "); 
  Serial.print(temp8, 2); Serial.println(" *C "); 
  tempsensor8.shutdown_wake(1); // shutdown tempsensor8
      
  Wire.beginTransmission(TCA1); 
  Wire.write(0);  // switch off TCA1
  Wire.endTransmission();
  delay(100);


//MEASURE TEMP FROM INCUBATOR 9
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(0); //Now that we have switched on TCA 2, we select channel 0 
  tempsensor9.begin(0x18); //activate tempsensor 9, which is connected to channel 0 of TCA2   
  tempsensor9.setResolution(3);
  tempsensor9.wake();   // wake up, ready to read!
  float temp9 = tempsensor9.readTempC();
  Serial.print("Temp on sensor 9: "); 
  Serial.print(temp9, 2); Serial.println(" *C "); 
  tempsensor9.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

  //MEASURE TEMP FROM INCUBATOR 10
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(1); //Now that we have switched on TCA 2, we select channel 1 
  tempsensor10.begin(0x18); //activate tempsensor 10, which is connected to channel 1 of TCA2   
  tempsensor10.setResolution(3);
  tempsensor10.wake();   // wake up, ready to read!
  float temp10 = tempsensor10.readTempC();
  Serial.print("Temp on sensor 10: "); 
  Serial.print(temp10, 2); Serial.println(" *C "); 
  tempsensor10.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

//MEASURE TEMP FROM INCUBATOR 11
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(2); //Now that we have switched on TCA 2, we select channel 2 
  tempsensor11.begin(0x18); //activate tempsensor 11, which is connected to channel 2 of TCA2   
  tempsensor11.setResolution(3);
  tempsensor11.wake();   // wake up, ready to read!
  float temp11 = tempsensor11.readTempC();
  Serial.print("Temp on sensor 11: "); 
  Serial.print(temp11, 2); Serial.println(" *C "); 
  tempsensor11.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

  //MEASURE TEMP FROM INCUBATOR 12
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(3); //Now that we have switched on TCA 2, we select channel 3 
  tempsensor12.begin(0x18); //activate tempsensor 12, which is connected to channel 3 of TCA2   
  tempsensor12.setResolution(3);
  tempsensor12.wake();   // wake up, ready to read!
  float temp12 = tempsensor12.readTempC();
  Serial.print("Temp on sensor 12: "); 
  Serial.print(temp12, 2); Serial.println(" *C "); 
  tempsensor12.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

 //MEASURE TEMP FROM INSIDE INCUBATOR HOUSING
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(4); //Now that we have switched on TCA 2, we select channel 4 
  tempsensor13.begin(0x18); //activate tempsensor 13, which is connected to channel 4 of TCA2   
  tempsensor13.setResolution(3);
  tempsensor13.wake();   // wake up, ready to read!
  float temp13 = tempsensor13.readTempC();
  Serial.print("Temp inside incubator housing: "); 
  Serial.print(temp13, 2); Serial.println(" *C "); 
  tempsensor13.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

   //MEASURE OUTSIDE TEMP
  Wire.beginTransmission(TCA2);
  Wire.write(1);
  Wire.endTransmission(); //Switch on TCA2
  
  tcaselect(5); //Now that we have switched on TCA 2, we select channel 5 
  tempsensor14.begin(0x18); //activate tempsensor 14, which is connected to channel 5 of TCA2   
  tempsensor14.setResolution(3);
  tempsensor14.wake();   // wake up, ready to read!
  float temp14 = tempsensor14.readTempC();
  Serial.print("Outside temp: "); 
  Serial.print(temp14, 2); Serial.println(" *C "); 
  tempsensor14.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
 
  Wire.beginTransmission(TCA2);
  Wire.write(0);  // shut down TCA2
  Wire.endTransmission();
  delay(100);

The MCP9808 can be configured for 8 different I2C addresses, so you only need one TCA9548A multiplexer and two channels of it to control 14 MCP9808 sensors. Why do you do it the complicated way?

tcaselect(0); //Now that we have switched on TCA1, we select channel 0

I don't know why the comment is there but the corresponding function does nothing. This isn't necessary as the code

already selected channel 1 of TCA1.

It seems that your approach wanted to have all MCP sensors to have address 0x18 and the select the corresponding TCA output to access only one of them. This is possible as long as you leave one of the TCA outputs unconnected to have a dummy output that must be selected while the other TCA is used.

BTW, you definitely should learn to use arrays, that would make your code much more lightweight and maintainable.

1 Like

Hi there Pylon. Thank you very much for your assistance. Yes, I'll definitely try and use an array for this, but right now it adds another dimension of understanding to my problem which I'm not quite ready to approach until I've got the sensors all reading properly and I can be sure my hardware is all working.

The MCP9808 can be configured for 8 different I2C addresses, so you only need one TCA9548A multiplexer and two channels of it to control 14 MCP9808 sensors. Why do you do it the complicated way?
You are of course quite correct, and this would have been an option. However, I did it this way so that I could simply plug any MCP9808 sensors (regardless of address) into any of the ports from the TCA, without specifying location and address. That way, I could more easily test a larger number of sensors that I actually needed, and select those that varied the smallest amount from the mean temperature in order to reduce sensor-induced temperature variance.

I don't know why the comment is there but the corresponding function does nothing. This isn't necessary as the code already selected channel 1 of TCA1

 Wire.beginTransmission(TCA1);
 Wire.write(1);
 Wire.endTransmission(); //Switch on TCA1

OK, thanks this is useful. I thought you had to first switch on the TCA you wanted, then select the channel of the switched-on TCA you wanted, then query your sensor, then switch off the TCA. So you're saying this is conceptually wrong? Which part of the code selects channel 1? Is it this?

Wire.write(1);

And how do you select channel 0, since Wire.write(0) should switch off that TCA, shouldn't it?

Thanks again for the help.

Solution found, thank you very much for your assistance.
Best regards,

Geoff

No, it's the complete code part above (3 lines).

You're right, I was wrong, the channels are selected by the bits. So the value 1 is selecting channel 0, a value 2 would select channel 1, a value 3 would select both channel 0 and 1 (but that doesn't make sense in your case).

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