0

I am using 5 sensors out of which two have the same I2C address and are connected via TCA9548 multiplexer. The remaining 3 sensors are connected to the main arduino I2C bus. In example sketches online I see the following function to choose the specific port/channel on the multiplexer:

#define MPLXADR 0x70 // Address of TCA9548A I2C Multiplexer
void multiplexer (uint8_t ch) {
  if (ch > 7) return;
  Wire.beginTransmission(MPLXADR);
  Wire.write(1 << ch);
  Wire.endTransmission();
}

I understand that this function should be called before executing instructions for the sensors with shared address but how would it still send the data to the right sensor when the last line "Wire.endTransmission();" just closes connection?

Since in my circuit there are sensors which are connected directly to the arduino I2C bus, I wonder if the code related to those sensors comes after the code for sensors with shared address, wouldn't those instructions also be sent to the ensors with shared I2C address? To me it makes more sense if the instructions for the shared address sensors are enclosed inside the above mentioned function as follows:

channel select -> execute instruction -> end transmission

But the usage I see in the tutorials baffles me. Could somebody please clarify these points? Thanks

Here is the complete sketch I am using:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <AHT10.h>
#include <HDC2080.h>

Adafruit_BME280 bme1; // on Arduino I2C bus
Adafruit_BME280 bme2; // on multiplexer I2C bus
Adafruit_BME280 bme3; // on mulitplexer I2C bus
AHT10 AHT(AHT10_ADDRESS_0X38); // on Arduino I2C bus
HDC2080 HDC2080(0x41);// on Arduino I2C bus


#define MPLXADR 0x70 // Address of TCA9548A I2C Multiplexer
void multiplexer (uint8_t ch) {
  if (ch > 7) return;
  Wire.beginTransmission(MPLXADR);
  Wire.write(1 << ch);
  Wire.endTransmission();
}

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

  while (AHT.begin() != true)
  {
    Serial.println(F("AHT10 not connected or fail to load calibration coefficient"));
    delay(5000);
  }
  Serial.println(F("AHT10 OK"));

  HDC2080.begin();

  // Begin with a device reset
  HDC2080.reset();

  // Set up the comfort zone
  HDC2080.setHighTemp(28);         // High temperature of 28C
  HDC2080.setLowTemp(22);          // Low temperature of 22C
  HDC2080.setHighHumidity(55);     // High humidity of 55%
  HDC2080.setLowHumidity(40);      // Low humidity of 40%

  // Configure Measurements
  HDC2080.setMeasurementMode(TEMP_AND_HUMID);  // Set measurements to temperature and humidity
  HDC2080.setRate(ONE_HZ);                     // Set measurement frequency to 1 Hz
  HDC2080.setTempRes(FOURTEEN_BIT);
  HDC2080.setHumidRes(FOURTEEN_BIT);

  //begin measuring
  HDC2080.triggerMeasurement();
  Serial.println();

  Serial.println(F("BME280 test"));

  //BME280 sensor 1
  multiplexer(0);
  if (! bme1.begin(0x77, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // weather monitoring
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme1.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // temperature
                   Adafruit_BME280::SAMPLING_X1, // pressure
                   Adafruit_BME280::SAMPLING_X1, // humidity
                   Adafruit_BME280::FILTER_OFF   );

  //BME280 sensor 2
  multiplexer(1);
  if (! bme2.begin(0x77, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // weather monitoring
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme2.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // temperature
                   Adafruit_BME280::SAMPLING_X1, // pressure
                   Adafruit_BME280::SAMPLING_X1, // humidity
                   Adafruit_BME280::FILTER_OFF   );

  //BME280 sensor 3
  if (! bme3.begin(0x76, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // weather monitoring
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme3.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // temperature
                   Adafruit_BME280::SAMPLING_X1, // pressure
                   Adafruit_BME280::SAMPLING_X1, // humidity
                   Adafruit_BME280::FILTER_OFF   );

  // suggested rate is 1/60Hz (1m)
 }

void loop() {
  bme3.takeForcedMeasurement(); // has no effect in normal mode
  printValuesBME3();
  delay(5000);

  printValuesAHT();
  delay(5000);

  printValuesHDC2080();
  delay(5000);

  multiplexer(0);
  bme1.takeForcedMeasurement(); // has no effect in normal mode
  printValuesBME1();
  delay(5000);

  multiplexer(1);
  bme2.takeForcedMeasurement(); // has no effect in normal mode
  printValuesBME2();
  delay(10000);
}

void printValuesBME1() {

  Serial.println();
  Serial.print("BME1 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme1.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme1.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesBME2() {

  Serial.println();
  Serial.print("BME2 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme2.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme2.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesBME3() {

  Serial.println();
  Serial.print("BME3 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme3.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme3.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesHDC2080() {
  Serial.println("HDC2080 Values");
  Serial.print("Temperature (C): "); Serial.print(HDC2080.readTemp());
  Serial.print("\t\tHumidity (%): "); Serial.println(HDC2080.readHumidity());
}

void printValuesAHT() {
  
  Serial.println(F("AHT10: read 12-bytes, show 255 if communication error is occurred"));
  Serial.print(F("Temperature: ")); Serial.print(AHT.readTemperature()); Serial.println(F(" +-0.3C")); //by default "AHT10_FORCE_READ_DATA"
  Serial.print(F("Humidity...: ")); Serial.print(AHT.readHumidity());    Serial.println(F(" +-2%"));   //by default "AHT10_FORCE_READ_DATA"
}
2

The TCA9548 is a switch.

You begin a transaction to it, change the channel that it allows through, and then end that specific transaction.

From that point on one and only one of the other two sensors are attached to your bus - the other doesn't exist. When you communicate on the address of that sensor it passes through the TCA9548 as if it doesn't exist.

You can think of the TCA9548 as a controller that sits next to the switch:

schematic

simulate this circuit – Schematic created using CircuitLab

Send channel 0 and it flips the switch one way. Send channel 1 and it flips the switch the other way. Once the switch is flipped it stays flipped until you tell it otherwise.

From your sketches perspective the two HDC2080s on the MUX are only one HDC2080. You just flip the switch to the right position to access the specific physical device you want at the time.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.