TCA9548A I2C Multiplexer Arduino Use Same Address I2C Devices

In this tutorial, we will learn to use TCA9548A I2C multiplexer with Arduino. We will discuss how to use multiple I2C devices with Arduino having the same address by incorporating a hardware solution. By using a TCA9548A I2C Multiplexer, we will be able to increase the I2C addresses range of Arduino and able to connect 8 I2C devices having same address. Additionally, we will interface Arduino with different sensors and devices that communicate via I2C protocol and program our board to run an I2C scanner. This scanner will determine the number of I2C devices connected with Arduino. So let’s begin!

The TCA9548A is a 1-to-8 I2C multiplexer. It allows you to use up to 8 I2C slave devices that have the same address on a single microcontroller by connecting the devices to the multiplexer and selecting the device you want to communicate with through the multiplexer.

We have a similar guide with ESP32:

For detailed information on I2C communication protocol, you can read this post:

Arduino I2C communication Pins

For I2C communication, different boards of Arduino have different pins dedicated as SDA and SCL pins. The below list shows these pin numbers on various boards.

  1. In Arduino UNO, Pin A4 = SDA and Pin A5 = SCL
  2. For Arduino Mega2560, Pin 20 = SDA and Pin 21 = SCL
  3. In Arduino Leonardo, Pin 2 = SDA and Pin 3 = SCL
  4. For Arduino Due, Pin 20 = SDA and Pin 21 = SCL, SDA1, SCL1

The below figure shows SDA and SCL pins in Arduino UNO which will be used in this article.

Arduino I2C Pins

Now let’s see some examples. In the first section, we will see examples to connect different I2C devices which have different I2C addresses with Arduino. After that, we will see an example to connect the same I2C address devices with Arduino using a TCA9548A 1-to-8 I2C multiplexer module.

Using Multiple Different Address Slave I2C Devices with Arduino

In this section, we will first connect three different I2C devices (OLED, SHT32 (temperature sensor), and BME280 (temperature sensor)) with Arduino using the default I2C pins. Then we will program our board to run an I2C scanner.

Components Required

  1. Arduino
  2. SSD1306 OLED Display
  3. BME280 sensor
  4. SHT31 sensor
  5. Breadboard
  6. Connecting Wires

Interface Arduino with OLED, BME280, and SHT31

Arduino with SHT31, BME280 and OLED hardware

Let us see how to connect Arduino with an OLED, BME280 module, and SHT31 module together. We will use a common I2C line to connect all the devices. Arduino will act as a master, and the BME280 sensor, SHT31 sensor, and the OLED will act as slaves.

The connections between the four devices which we are using can be seen in the table below.

ArduinoSSD1306 OLED DisplayBME280SHT31
3.3VVCCVCCVCC
A4SDASDASDA
A5SCLSCLSCL
GNDGNDGNDGND

We have used the same connections as specified in the table above.

Arduino with SHT31, BME280 and OLED schematic diagram

Arduino I2C Scanner Arduino Sketch

Every I2C device has an address associated with it. Arduino uses this address to communicate with the slave via I2C protocol.

Now copy this code and upload it your board with all the I2C devices already connected with it.

This code will scan for any I2C devices connected with Arduino and will specify the number of devices with the address in the serial terminal.

#include <Wire.h>
 
void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");
    byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknown error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);  
  Serial.print("i2c devices found:");
  Serial.println(nDevices); 
}
 
void loop() {
      
}
Arduino I2C scanner serial terminal

The I2C scanner identified 3 devices connected to the I2C interface. The I2C Address of OLED Display is 0x3C, SHT31 is 0x44 and BME280 is 0x76.

As all of these three I2C devices had different addresses therefore it was possible to share the same I2C bus.

Arduino Display BME280 and SHT31 Temperature Readings on OLED

As seen in the I2C scanner, BME280, SHT31 and OLED have different I2C addresses, hence it is possible to share the same I2C bus. Let us show you an Arduino sketch which accesses temperature readings from these two sensors and displays them on the OLED.

We will use Arduino IDE to program our Arduino development board. Thus, you should have the latest version of Arduino IDE.

Arduino Multiple I2C devices with different addresses Display temperature on OLED

Installing SSD1306 OLED Library in Arduino IDE

To use the OLED display in our project, we have to install the Adafruit SSD 1306 library in Arduino IDE. Follow the steps below to successfully install it.

Open Arduino IDE and click on Sketch > Library > Manage Libraries. The following window will open up.

search library Arduino IDE

Type ‘SSD1306’ in the search tab and install the Adafruit SSD1306 OLED library.

Install OLED SSD1306 Library Arduino IDE

Installing BME280 Arduino Library

As we are connecting the BME280 sensor with Arduino. Therefore, we will have to install BME280 libraries to our module. We will require two libraries for this project:

  1. Adafruit_BME280 library
  2. Adafruit_Sensor library

We will use the Library Manager in our Arduino IDE to install the latest versions of the libraries. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type Adafruit BME280 library name in the search bar and install them both.

Adafruit BME280 library Arduino IDE

Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type Adafruit unified sensor library name in the search bar and install it.

Adafruit unified sensor library install

Install SHT31 Arduino Library

As we are connecting the SHT31 sensor module with Arduino, therefore, we will have to install the libraries to access the sensor data. We will require two libraries for this project:

  1. Adafruit SHT31
  2. Adafruit BusIO

We will use the Library Manager in our Arduino IDE to install the latest versions of the libraries. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type Adafruit SHT31 in the search bar and install the latest version.

Install Adafruit SHT31 Library

Type Adafruit BusIO in the search bar and install it as well.

Install Adafruit BusIO Library

Arduino Display BME280 and SHT31 Temperature Readings on OLED Code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_BME280 bme; 
Adafruit_SHT31 sht31 = Adafruit_SHT31();

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
unsigned long delayTime;

void setup() {
  Serial.begin(115200);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
   // init done
  display.display();
  delay(100);
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  
  bool status;
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  if (! sht31.begin(0x44)) {   
    Serial.println("Check circuit. SHT31 not found!");
    while (1) delay(1);
  }

  Serial.println();
}


void loop() { 
  
  display.setCursor(0,0);
  
  Serial.print("Temperature BME280 = "); Serial.print(bme.readTemperature()); Serial.println(" °C");
  display.print("Temperature: "); display.print(bme.readTemperature()); display.println(" C");

  display.setCursor(0,20);
   
  Serial.print("Temperature SHT31 = "); Serial.print(sht31.readTemperature()); Serial.println(" °C");
  display.print("Temperature: "); display.print(sht31.readTemperature()); display.println(" C");

  Serial.println();
  display.display();
  display.clearDisplay();

  delay(1000);
}

How the Code Works?

Now, let us understand how each part of the code works.

The code starts with including all the necessary libraries which are needed for the proper functionality of the code. The Wire.h will allow us to communicate through the I2C protocol. The rest of the libraries are the ones that we just installed for the functionality of the BME280 sensor, SHT31 sensor and OLED.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Then, we define the Adafruit_BME280 object named ‘bme’ by setting it on the default I2C GPIO pins and create the Adafruit_SHT31 object called ‘sht31.’

Adafruit_BME280 bme; 
Adafruit_SHT31 sht31 = Adafruit_SHT31();

Now, we create another object named display which will be handling the OLED display. Also, define the size of the OLED display by passing arguments to the Adafruit_SSD1306() function.

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);

setup()

Open the serial communication at a baud rate of 115200.

Serial.begin(115200);

Initialize the OLED display by calling the begin() method on the display object.

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 

Next, we will clear the OLED screen by calling clearDisplay() function. Also, we set the color of the text using setTextColor() function and pass WHITE as an argument. If we have a dark background, we will display our text in white and if we have a bright background then we will display the text in black. Also, we set the font size using setTextSize().

  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(WHITE);

Then, the BME280 sensor gets initialized using and in case of failure, an error message is printed on the serial monitor. Similarly, the SHT31 sensor is initialized as well. If the sensor initialization is not a success, a relevant message will be printed on the serial monitor.

  bool status;
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  if (! sht31.begin(0x44)) {   
    Serial.println("Check circuit. SHT31 not found!");
    while (1) delay(1);
  }

loop()

Inside the loop() function, we acquire the BME280 and SHT31 temperature readings using bme.readTemperature() and sht31.readTemperature respectively. These are then displayed in the Arduino serial monitor and the OLED after every second.


void loop() { 
  
  display.setCursor(0,0);
  
  Serial.print("Temperature BME280 = "); Serial.print(bme.readTemperature()); Serial.println(" °C");
  display.print("Temperature: "); display.print(bme.readTemperature()); display.println(" C");

  display.setCursor(0,20);
   
  Serial.print("Temperature SHT31 = "); Serial.print(sht31.readTemperature()); Serial.println(" °C");
  display.print("Temperature: "); display.print(sht31.readTemperature()); display.println(" C");

  Serial.println();
  display.display();
  display.clearDisplay();

  delay(1000);
}

Demonstration

To see the demonstration of the above code, upload the code to Arduino. But, before uploading code, make sure to select the Arduino board from Tools Board and also select the correct COM port to which the Arduino board is connected from Tools Port.

Once the code is successfully uploaded to the board, the OLED will start displaying the temperature readings from the two sensors as shown below:

Arduino Mutliple I2C devices with different addresses Display temperature on OLED demo

Moreover, you can also view the temperature readings in the Arduino serial terminal. Remember to set the baud rate at 115200.

Arduino Multiple I2C devices with different addresses Display temperature terminal
Serial Monitor

TCA9548A Multiple I2C Devices of same addresses with Arduino

In the previous section, we were able to connect three different I2C devices on the same I2C pins of Arduino. This was because the Arduino was able to identify them due to their unique address. However, what happens when we want to connect multiple devices with Arduino for I2C communication but they have the same address? For example, two BME280 sensors connected with Arduino or two OLEDs connected with Arduino.

To use the same I2C devices with the Arduino, we would either have to change the I2C address of the device or use an I2C multiplexer. However, it is not that simple to change the address of a device and it only allows limited devices to be used on the same I2C bus. Hence we can use a multiplexer eg. TCA9548A that will allow a maximum of eight devices with the same addresses to be connected to the same I2C bus. It operates on a range of 3-5.5 volts, therefore, making it convenient to use with microcontrollers having 3.3/5V logic pins.

The diagram below shows the TCA9548A multiplexer that we will use with I2C devices having the same address in order to communicate with Arduino.

TCA9548A 1-to-8 I2C Multiplexer ic
TCA9548A Multiplexer

It is an electronic switching device that enables the users to connect multiple I2C busses with itself. All the slaves which have the same address need to be on connected to different busses. In order to communicate with the slave, the bus that is connected to the slave is switched by the user and then addressed.

TCA9548A Multiplexer Pinout

The diagram below shows the pinout of the TCA9548A multiplexer which acts as an I2C expander.

TCA9748A Multiplexer Pinout
  • Vin: This is the pin that provides power to the module. Connect 3.3V or 5V pin of Arduino with this pin.
  • GND: This is the pin which provides the common ground.
  • SDA: This is the I2C serial data pin which is connected with the master device.
  • SCL: This is the I2C serial clock pin which is connected with the master device.
  • RST: This pin is responsible for resetting the multiplexer.
  • A0, A1, A2: These three pins are used to change the I2C address of the multiplexer. By default, its address is 0x70 when these pins are unconnected. With the help of this module, a single I2C address can be expanded to a maximum of eight I2C addresses.
  • SDx, SCx: These are the external I2C channels Channel 0 to Channel 7. Connect SDA pin with SDx and SCL pin with SCx for each I2C device having same address.

Arduino Display Text on OLEDs using TCA9548A Multiplexer

Let’s show you how to connect and program two OLEDs having the same address 0x3C with Arduino using the TCA9548A multiplexer. We will require the following components:

Components Required

  1. Arduino
  2. Two SSD1306 OLEDs
  3. TCA9548A Multiplexer
  4. Four 10k ohm pullup resistors
  5. Breadboard
  6. Connecting Wires

Interface Arduino with TCA9548A multiplexer with OLEDs

Let’s show you how to connect the TCA9548A multiplexer with Arduino and the OLEDs. Arduino will act as a master, and the OLEDs will act as slaves.

Follow the schematic diagram below to connect all the devices.

Arduino with TCA9748A Multiplexer with OLEDs schematic diagram

The table below shows the pins of TCA9548A connected with Arduino and the two OLEDs.

TCA9548AConnections with rest of the devices
Vin3.3V of Arduino, VCC of both OLEDs
GNDGND of Arduino, GND of both OLEDs
SDAA4 of Arduino
SCLA5 of Arduino
SD0SDA of OLED1 with 10k ohm pullup resistor
SC0SCL of OLED1 with 10k ohm pullup resistor
SD1SDA of OLED2 with 10k ohm pullup resistor
SC1SCL of OLED2 with 10k ohm pullup resistor
Arduino with TCA9748A Multiplexer and OLEDs hardware

Arduino Display Text on OLEDs using TCA9548A Multiplexer Code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);

void TCA9548A(uint8_t bus) //activate particular channel
{
  Wire.beginTransmission(0x70);  // TCA9548A address is 0x70
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
}

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  delay(100);

  TCA9548A(0);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(20, 10);
  display.setTextColor(WHITE);
  display.println("OLED #1");
  display.display(); 

  TCA9548A(1);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(20, 10);
  display.setTextColor(WHITE);
  display.println("OLED #2");
  display.display(); 

}

void loop() {
  
}

How does the Code Works?

Now, let us understand how each part of the code works.

The code starts with including all the necessary libraries needed for the proper code functionality. The Wire.h will allow us to communicate through the I2C protocol and Adafruit_GFX.h and Adafruit_SSD1306.h are the OLED libraries.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Now, we create an object named display which will be handling the OLED display. Also, define the size of the OLED display by passing arguments to the Adafruit_SSD1306() function.

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);

Next we define a function for TCA9548A() that takes in a single parameter which is the I2C bus channel. This function is called whenever we want to activate a particular I2C channel.

void TCA9548A(uint8_t bus) 
{
  Wire.beginTransmission(0x70);  // TCA9548A address is 0x70
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
}

setup()

Open the serial communication at a baud rate of 115200 and initiate the I2C communication.

  Serial.begin(115200);
  Wire.begin();

Next we activate I2C channel 0 by calling TCA9548A() function as pass 0 as a parameter inside it. Our first OLED is connected with I2C channel 0. After that we initialize the OLED display, clear the screen, set the color of the text, set the font size and the cursor position. Then we print the text ‘OLED #1’ on the display.

  TCA9548A(0);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(20, 10);
  display.setTextColor(WHITE);
  display.println("OLED #1");
  display.display(); 

Next we activate I2C channel 1 by calling TCA9548A() function as pass 1 as a parameter inside it. Our second OLED is connected with I2C channel 1. After that we initialize the OLED display, clear the screen, set the color of the text, set the font size and the cursor position. Then we print the text ‘OLED #2’ on the display.

TCA9548A(1);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(20, 10);
  display.setTextColor(WHITE);
  display.println("OLED #2");
  display.display(); 

Demonstration

To see the demonstration of the above code, upload the code to Arduino. But, before uploading code, make sure to select the Arduino board from Tools Board and also select the correct COM port to which the Arduino board is connected from Tools Port.

Once the code is successfully uploaded to the board, the two OLEDs will start displaying their respective texts as shown below:

Arduino with TCA9748A Multiplexer and OLEDs demo

You may also like to read:

Leave a Comment