How to Connect Multiple I2C Sensors with the TCA9548A I2C Multiplexer
In this article, I’m going to take you through all you need to know about using an I2C Multiplexer. We’ll be covering the following:
- What is the I2C Communication Protocol?
- Why use an I2C Multiplexer?
- How does an I2C Multiplexer work?
- How to use an I2C Multiplexer with Arduino
Recap: What is I2C?
I2C, pronounced I-squared-C, stands for inter-integrated circuit. I2C is a flexible multi-master, multi-slave serial communication protocol that combines the best features of SPI (Serial Peripheral Interface) and UART (Universal Asynchronous Receiver / Transmitter).
Compared to UART, I2C is able to support faster and more simultaneous connections with peripheral devices. At the same time, it tackles the weaknesses of SPI by still only requiring two wires and allowing for multi-master interfaces.
As a result, I2C is a very popular communication protocol that is in many hardware modules. For example, here are some popular Grove modules that use I2C communication.
- Grove – I2C Motor Driver with L298
- Grove – AHT20 I2C Industrial Grade Temperature and Humidity Sensor
- Grove – I2C Color Sensor V2
To read more in depth about I2C, be sure to read our I2C Communication Guide.
If you’re confused about the differences between I2C and other protocols like UART and SPI, you’ll also benefit from reading this article, where we explain the differences between each of the communication protocols and their uses.
Why use an I2C Multiplexer? – I2C Addressing
Since I2C allows for a single controller (master) to communicate with multiple peripherals (slaves), there must be some way to identify which peripheral each message is meant for. In I2C, this is done through addressing. Each device that uses I2C has an I2C address.
The controller sends the address of the peripheral that it wants to communicate with to every connected peripheral device. Each peripheral then compares the received address to its own, sending an acknowledgement bit back to the controller if there is a match. Otherwise, the message is ignored. Following this, data is sent from the controller to the peripheral, which is once again acknowledged.
That sounds nice and straightforward, but what happens when we want to use two I2C modules in the same system? Most I2C devices have a fixed address, so if you want to use more than one of the same device, you’re going to run into an addressing conflict.
That’s where the multiplexer comes in!
How does an I2C Multiplexer work?
As a direct example to today’s guide, we’re going to look at the TCA9548A-based Grove 8-Channel I2C Hub. Grove is a standardised, modular prototyping system that makes hardware and electronics more accessible by removing the need for complicated wiring or solder. To date, Grove has over 300+ compatible modules, allowing anyone to get into building any kind of project easily.
The Grove 8-Channel I2C Hub uses the TCA9548A I2C Multiplexer Chip. As the name suggests, it can interface with 8 different channels.
The hub itself has an I2C address of 0x70. But by writing data to this address, we can select which channel we want to open or close on the fly. When we plug in devices with conflicting I2C addresses, we can simply adjust the desired channels prior to transmitting data as usual. In doing so, we ensure that there is technically only one ‘active’ device at a given I2C address, hence eliminating the conflict.
Using an I2C Multiplexer with the Arduino IDE
Fortunately, like all Grove modules, the Grove 8-Channel I2C Hub comes with an Arduino software library that allows you to interface with it quickly and conveniently with any Arduino-compatible microcontroller. Let’s take a look at how we can control the hub to interface with multiple modules that have conflicting I2C addresses.
Step 1: Download & Install the Grove 8 Channel I2C Hub Library.
Step 2: Include the Following Code in Your Arduino Sketch.
#include "TCA9548A.h"
// if you use the software I2C to drive, you can uncomment define SOFTWAREWIRE in TCA9548A.h.
#ifdef SOFTWAREWIRE
#include <SoftwareWIRE.h>
SoftwareWire myWIRE(3, 2);
TCA9548A<SoftwareWire> TCA;
#define WIRE myWIRE
#else
#include <Wire.h>
TCA9548A<TwoWire> TCA;
#define WIRE Wire
#endif
Step 3: Open the Connection to the TCA Multiplexer on the Grove Hub in Setup().
TCA.begin(WIRE);
Step 4: Write the code!
Let’s say we want to use two of the Grove – AHT20 I2C Temperature and Humidity Sensor that have an I2C address of 0x38, plugged in at ports 0 and 1. To make things easier, let’s first also include the Grove library for the AHT20 sensor, which can be downloaded here.
#include "AHT20.h"
Also initialise each sensor separately, taking care to open and close the corresponding channels.
TCA.openChannel(TCA_CHANNEL_0);
AHT.begin();
TCA.closeChannel(TCA_CHANNEL_0);
TCA.openChannel(TCA_CHANNEL_1);
AHT.begin();
TCA.closeChannel(TCA_CHANNEL_1);
As you might guess, retrieving the readings from each sensor can be done in a similar way. The resulting code reads and prints out the temperature and humidity readings from each sensor consecutively to the serial monitor. Naturally, you can easily extend this method to use any other kind of Grove I2C sensors with conflicting addresses!
void loop()
{
float humi1, temp1, humi2, temp2;
// First AHT20 Sensor
TCA.openChannel(TCA_CHANNEL_0);
int ret1 = AHT.getSensor(&humi1, &temp1);
if(ret1) // GET DATA FROM AHT20 1 OK
{
Serial.print("humidity: ");
Serial.print(humi1*100);
Serial.print("%\t temerature: ");
Serial.println(temp1);
}
else
{
Serial.println("GET DATA FROM AHT20 1 FAIL");
}
TCA.closeChannel(TCA_CHANNEL_0);
// Second AHT20 Sensor
TCA.openChannel(TCA_CHANNEL_1);
int ret2 = AHT.getSensor(&humi2, &temp2);
if(ret2) // GET DATA FROM AHT20 2 OK
{
Serial.print("humidity: ");
Serial.print(humi2*100);
Serial.print("%\t temerature: ");
Serial.println(temp2);
}
else
{
Serial.println("GET DATA FROM AHT20 2 FAIL");
}
TCA.closeChannel(TCA_CHANNEL_1);
delay(100);
}
Summary
This concludes our tutorial on I2C multiplexers! As you can see, with the Grove 8-Channel I2C Multiplexer and some additional lines of code, we can not only resolve I2C address conflicts but also make use of multiple sensors with the same I2C address easily!
If you’re simply looking for an I2C hub without multiplexing capabilities, the Grove I2C Hub (6 Port) or Grove I2C Hub with 4 ports may suit your needs better.
Are you in the market for an Arduino board? Check out our Arduino Buying Guide for a comprehensive coverage and comparison! Alternatively, kindly visit the Seeed Online Store to explore more Grove modules.
If you simply want to learn more about communication protocols, don’t forget to read our other guides below.
- I2C Communication – All about I²C with Diagrams
- UART vs I2C vs SPI – Communication Protocols and Uses