OK, now to code up the example with two TCA9548As and thee BME280s.

Here's the code:

// SPDX-FileCopyrightText: 2022 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <Adafruit_BME280.h>

// for each TCA9548A, add an entry with its address
const uint8_t TCA_ADDRESSES[] = {
  0x70,
  0x71
};
const uint8_t TCA_COUNT = sizeof(TCA_ADDRESSES) / sizeof(TCA_ADDRESSES[0]);

Adafruit_BME280 bme1;  // BME280 #1
Adafruit_BME280 bme2;  // BME280 #2
Adafruit_BME280 bme3;  // BME280 #3

void tcaselect(uint8_t tca, uint8_t channel) {
  if (tca >= TCA_COUNT) return;
  if (channel > 7) return;

  // loop over all TCA's
  for (uint8_t i=0; i<TCA_COUNT; i++) {
    Wire.beginTransmission(TCA_ADDRESSES[i]);
    if (i == tca) {
      // set output channel for selected TCA
      Wire.write(1 << channel);
    } else {
      // for others, turn off all channels
      Wire.write(0);
    }
    Wire.endTransmission();
  }
}


void setup() {
  Serial.begin(9600);
  while(!Serial);
  Serial.println("Multiple BME280 / Multiple TCA9548A Example.");

  Serial.print("Total number of TCA's = "); Serial.println(TCA_COUNT);
  for (uint8_t i=0; i<TCA_COUNT; i++) {
    Serial.print(i); Serial.print(" : 0x"); Serial.println(TCA_ADDRESSES[i], 16);
  }

  // NOTE!!! VERY IMPORTANT!!!
  // Must call this once manually before first call to tcaselect()
  Wire.begin();

  // Before using any BME280, call tcaselect to select its output channel
  tcaselect(0, 0);   // TCA 0, channel 0 for bme1
  bme1.begin();      // use the default address of 0x77

  tcaselect(0, 1);   // TCA 0, channel 1 for bme2
  bme2.begin();      // use the default address of 0x77

  tcaselect(1, 0);   // TCA 1, channel 0 for bme3
  bme3.begin();      // use the default address of 0x77
}

void loop() {
  float pressure1, pressure2, pressure3;

  tcaselect(0, 0);
  pressure1 = bme1.readPressure();
  tcaselect(0, 1);
  pressure2 = bme2.readPressure();
  tcaselect(1, 0);
  pressure3 = bme3.readPressure();

  Serial.println("------------------------------------");
  Serial.print("BME280 #1 Pressure = "); Serial.println(pressure1);
  Serial.print("BME280 #2 Pressure = "); Serial.println(pressure2);
  Serial.print("BME280 #3 Pressure = "); Serial.println(pressure3);

  delay(1000);
}

With that sketch running on the Arduino board, the output in the Serial Monitor will look like this:

The key enabler here is the new tcaselect() helper function. It now takes two parameters - the TCA to use and the channel on that TCA to activate. It's not very complex. It just adds an extra bit of logic to send 0 for the channel to all the other muxers in order to disable their outputs.

There's also a bit of global information setup with these lines:

// for each TCA9548A, add an entry with its address
const uint8_t TCA_ADDRESSES[] = {
  0x70,
  0x71
};
const uint8_t TCA_COUNT = sizeof(TCA_ADDRESSES) / sizeof(TCA_ADDRESSES[0]);

The last line that computes TCA_COUNT can be left alone.

To set things up for more TCA9548As, or for TCA9548As with different addresses, update the entries in the TCA_ADDRESS array. Use the index in this array as the first parameter when calling tcaselect(). For example, to select the channel 3 on the TCA9548A at address 0x71, use:

tcaselect(1, 3);

Since 1 is the index in the TCA_ADDRESS array for the 0x71 address entry. (remember Arduino uses 0 based indexing)

Note that the code is klunky as it was before. The tcaselect() function must be called each time a different BME280 needs to be accessed.

tcaselect(0, 0);   // TCA 0, channel 0 for bme1
  bme1.begin();      // use the default address of 0x77 

  tcaselect(0, 1);   // TCA 0, channel 1 for bme2
  bme2.begin();      // use the default address of 0x77

  tcaselect(1, 0);   // TCA 1, channel 0 for bme3
  bme3.begin();      // use the default address of 0x77

This guide was first published on May 04, 2022. It was last updated on May 04, 2022.

This page (Arduino) was last updated on Jan 09, 2023.

Text editor powered by tinymce.