If you have ever tried to wire two BME280 environmental sensors or three identical OLED displays to a single microcontroller, you have hit the hard wall of I2C address collisions. The I2C multiplexer TCA9548A is the definitive bench solution. It acts as an 8-channel traffic cop, routing your master's SDA/SCL signals to one of eight isolated downstream sub-buses. This solves address clashes instantly and breaks up bus capacitance, allowing you to run longer wires or more devices without signal degradation.
I2C Bus Mechanics and the TCA9548A Spec Sheet
Before routing signals through a multiplexer, you must understand the physical limits of the underlying protocol. I2C (Inter-Integrated Circuit) is a synchronous, multi-master, multi-slave serial bus. It relies on open-drain lines pulled high by resistors, meaning the physical layer is entirely dependent on pull-up sizing and parasitic capacitance.
| Parameter | Standard Mode | Fast Mode | Fast Mode Plus |
|---|---|---|---|
| Wires Required | 2 (SDA, SCL) + GND | 2 (SDA, SCL) + GND | 2 (SDA, SCL) + GND |
| Max Clock Speed | 100 kHz | 400 kHz | 1 MHz |
| Addressing Scheme | 7-bit (128 addrs) or 10-bit | 7-bit or 10-bit | 7-bit or 10-bit |
| Max Bus Capacitance | 400 pF | 400 pF | 550 pF |
| Practical Distance | ~1 meter (unbuffered) | ~0.5 meter (unbuffered) | ~0.25 meter (unbuffered) |
The Texas Instruments TCA9548A sits on the primary bus at address 0x70 (configurable to 0x77 via address pins). When you write a single control byte to it, it closes the internal MOSFET switches to connect the master to the selected sub-bus.
| Specification | Value / Range | Design Note |
|---|---|---|
| VCC Operating Range | 1.65V to 5.5V | Supports both 3.3V and 5V logic natively. |
| Primary I2C Address | 0x70 to 0x77 | Set via A0, A1, A2 pins. 0x70 is default (all low). |
| On-State Resistance (Ron) | 4 Ω (typical) at 4.5V | Low enough to not significantly impact pull-up RC time constants. |
| Standby Current | 6 µA (max) | Excellent for battery-powered ESP32 deep-sleep nodes. |
| Channel Switching Time | ~250 ns | Settles well before the next I2C clock edge at 400kHz. |
| Reset Pin (Active Low) | Internal pull-up | Leave floating or tie to VCC; pull to GND to force bus disconnect. |
Physical Wiring, Pull-Up Resistors, and Classic Failures
The most common mistake when deploying the TCA9548A is assuming the breakout board handles all pull-up duties. It does not. The primary bus (between your MCU and the mux) needs pull-ups, and every active sub-bus needs its own pull-ups if the downstream sensors lack them.
For a standard 100 kHz bus with moderate capacitance (~200pF), use 4.7 kΩ pull-ups to VCC. If you are pushing 400 kHz (Fast Mode), the RC rise time becomes a bottleneck; drop to 2.2 kΩ or even 1 kΩ pull-ups to charge the parasitic capacitance faster. Never use 10 kΩ on a 400 kHz bus unless the wires are under 10 cm.
The Classic I2C Failures (and How the Mux Fixes or Causes Them)
- Address Clash: You want four identical TMP117 temperature sensors. They all default to
0x48. Without a mux, the bus hangs or returns garbage. Fix: Put one sensor on sub-bus 0, one on sub-bus 1, etc. The TCA9548A isolates them completely. - Missing Pull-Ups (Floating Lines): If SDA/SCL are left floating, electromagnetic interference will randomly pull the lines low, causing phantom NACKs. Fix: Verify 2.2kΩ - 4.7kΩ resistors exist between VCC and SDA/SCL on both the primary and secondary sides of the mux.
- Baud Mismatch and Capacitance Overload: Running 12 devices on a single I2C bus pushes capacitance past the 400 pF limit defined in the NXP I2C Specification. The signal edges turn from squares into sharks fins, and the receiver misses the clock edge. Fix: The TCA9548A breaks the capacitance. The master only sees the capacitance of one sub-bus at a time.
Minimal Working Exchange and Debugging the Bus
Below is the physical pin mapping for an ESP32 DevKit V1 to the TCA9548A, followed by a minimal, dependency-free C++ exchange. We avoid heavy libraries here to show exactly how the control byte is constructed.
| ESP32 Pin | TCA9548A Pin | Notes |
|---|---|---|
| 3V3 | VIN / VCC | Ensure your downstream sensors are also 3.3V tolerant. |
| GND | GND | Common ground is mandatory. | GPIO 21 | SDA | Primary I2C Data. Add 4.7kΩ pull-up to 3V3. |
| GPIO 22 | SCL | Primary I2C Clock. Add 4.7kΩ pull-up to 3V3. |
#include <Wire.h>
#define TCA_ADDR 0x70
#define SENSOR_ADDR 0x76 // Example: BME280 default address
// Function to switch the TCA9548A multiplexer channel
void tcaSelect(uint8_t channel) {
if (channel > 7) return; // Sanity check
Wire.beginTransmission(TCA_ADDR);
Wire.write(1 << channel); // Send control byte (e.g., 0x01 for channel 0)
uint8_t error = Wire.endTransmission();
if (error != 0) {
Serial.printf("Mux switch failed on ch %d. Error: %d\n", channel, error);
}
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // ESP32 default I2C pins
Wire.setClock(400000); // Set to 400kHz Fast Mode
Serial.println("Scanning sub-buses via TCA9548A...");
}
void loop() {
for (uint8_t ch = 0; ch < 8; ch++) {
tcaSelect(ch);
Serial.printf("--- Sub-bus %d ---\n", ch);
// Standard I2C scan on the currently active sub-bus
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.printf("Found device at 0x%02X\n", addr);
}
}
delay(500);
}
delay(5000);
}
How to Sniff and Debug the Bus
When the code above returns nothing, or returns devices on the wrong channels, you need to look at the physical layer. Do not guess; measure.
- The Multimeter Test: With the system powered but idle, measure DC voltage between SDA and GND, and SCL and GND. Both should read exactly VCC (e.g., 3.28V). If either reads near 0V, a downstream device is holding the bus low (a short or a crashed sensor).
- The Logic Analyzer: Hook up a $15 DSLogic Plus or a Saleae Logic to SDA and SCL. Trigger on the falling edge of SCL. Look at the 9th clock pulse. If SDA is high during the 9th pulse, that is a NACK (Not Acknowledged). The device is not responding. If SDA is low, it is an ACK.
- Oscilloscope Check: If you see "shark fin" rise times on SDA instead of sharp square waves, your pull-up resistors are too weak for the bus capacitance. Swap 4.7kΩ for 2.2kΩ.
Protocol Selection: When I2C Fits vs. SPI, UART, and CAN
Multiplexing I2C is a fantastic patch for address collisions, but it is not a substitute for choosing the right protocol for your physical environment. Use the decision matrix below to determine if you should be using the TCA9548A, or if you need to pivot to a different bus architecture entirely.
| Criteria | I2C (w/ TCA9548A) | SPI | UART (RS-485) | CAN Bus |
|---|---|---|---|---|
| Max Speed | 400 kHz (Fast) / 1 MHz (FM+) | 10 MHz to 50+ MHz | 1 Mbps to 10 Mbps | 1 Mbps (Classic) |
| Practical Distance | < 1 meter (unbuffered) | < 0.5 meters | > 1000 meters (w/ RS-485) | > 500 meters |
| Device Count | Up to 8x127 (via Mux) | 1 per Chip Select (CS) pin | Up to 32/256 (RS-485) | 110+ nodes |
| Wiring Complexity | 2 wires + GND (Low) | 4 wires + 1 per device (High) | 2 wires (Differential pair) | 2 wires (Differential pair) |
| Best Use Case | On-board sensors, OLEDs, low-speed telemetry | SD cards, high-res ADCs, TFT displays | GPS modules, long-distance industrial nodes | Automotive, noisy industrial environments |
If your sensors are all on the same PCB or inside the same project enclosure, the I2C multiplexer TCA9548A is the most efficient way to scale your device count without running out of GPIO pins. If you are routing wires across a room or through a noisy garage, abandon I2C and look into RS-485 transceivers or CAN bus modules. For a deep dive into practical hobbyist implementations of the TCA9548A with specific sensor libraries, the Adafruit TCA9548A Learning Guide provides excellent supplementary wiring diagrams.






