← How-Tos
electronics 56 min ago ◯ 5 min read

I2C Multiplexers for Makers: TCA9548A Wiring and Reading Multiple Identical-Address Sensors

i2ctca9548amultiplexersensorsesp32raspberry pivl53l0xbme280

The I2C wiring guide on this site covers the bus fundamentals, but it doesn't solve one of the most common problems makers actually run into: what happens when you want four identical distance sensors on a robot, or three BME280s in different rooms, and every single one shares the same fixed I2C address? You can't just wire them all to the same bus — the first one to respond is the only one you'll ever talk to. The TCA9548A I2C multiplexer is the standard fix, and this guide covers wiring it, addressing it, and the gotchas that trip people up the first time.

The Problem It Solves

Many I2C sensors have a fixed address burned into silicon with no way to change it (or, at best, one or two address-select pins giving you two or four possible addresses). The VL53L0X time-of-flight sensor is a classic example on Adafruit/generic breakouts — most inexpensive breakout boards default to the same 0x29 address with no easy hardware address change. Put two on the same bus and only one will ever answer. Your options are: separate physical I2C buses (the ESP32 has two hardware I2C peripherals, and you can bit-bang more in software, but this doesn't scale well past 2-3 buses), sensors with hardware address-select pins wired to different levels (works for some parts, not others), or a multiplexer that switches which downstream bus segment is connected to the host at any given moment. For more than two or three identical sensors, the multiplexer is almost always the cleanest answer.

How the TCA9548A Works

The TCA9548A is itself an I2C device (default address range 0x70-0x77, selected by three address pins A0-A2) that acts as an 8-way switch for the I2C bus. You talk to the mux first, over the main bus, telling it which of its eight downstream channels to connect. Only that one channel is electrically joined to the main SDA/SCL lines at any moment — the others are isolated. You then talk to whatever device sits on that channel exactly as if it were the only device on the bus, because as far as it and the host controller are concerned, it is. Switch channels, and you're now talking to the sensor on the next channel, with all eight downstream channels able to host identical-address devices without conflict.

Wiring

Software Pattern

The core sequence in firmware is always: write a single byte to the mux's address with only one bit set (selecting the channel), then perform your normal I2C transaction with the target sensor's address. Libraries like Adafruit's TCA9548A driver wrap this into a simple tcaSelect(channel) call you make before every read from a given sensor. A typical polling loop looks like: select channel 0, read sensor, select channel 1, read sensor, and so on — the mux adds a small amount of latency per switch (a single I2C write, generally well under a millisecond) but this is negligible for sensor polling at typical rates.

Bus Capacitance and Speed

Because each channel is isolated when not selected, you don't pay a capacitance penalty for having many devices wired up simultaneously the way you would on one giant shared bus — only the currently selected channel's capacitance matters. This is one of the mux's underrated benefits: it lets you run a longer aggregate wiring harness across many sensor locations (useful for a robot with sensors on multiple arms, or a multi-zone environmental monitor) without the bus speed and reliability problems that come from a single very long, heavily loaded I2C bus.

Common Mistakes

SymptomCauseFix All sensors return the same (or stale) dataForgot to call the channel-select function before each read, or selected the wrong channelAlways explicitly select the channel immediately before each transaction — don't assume the mux "remembers" a previous selection across other bus activity One channel works, others don't respondMissing pull-up resistors on that specific downstream channelVerify pull-ups exist on both SDA and SCL for every channel you use, not just channel 0 Mux itself doesn't respond at its addressAddress pins floating instead of tied firmly high or low, or address conflict with another deviceExplicitly tie A0-A2 with pull-up or pull-down resistors rather than leaving them floating Intermittent bus lockupsA downstream sensor hangs the bus (holding SDA low) while its channel is selectedAdd a bus-recovery routine, or use the mux's reset pin to force all channels back to a known de-selected state

When You Don't Need a Multiplexer

If you only need two of the same sensor and the part has an address-select pin (many BME280, BNO055, and similar breakouts do), just set one high and one low and skip the mux entirely — it's fewer parts and one less thing to debug. Reserve the multiplexer for cases with three or more identical-address devices, or where you specifically want physical bus isolation between sensor groups regardless of address availability.

Once wired correctly, a TCA9548A is close to invisible in normal operation — the extra channel-select call is a minor firmware addition for the ability to run a nearly unlimited number of otherwise address-conflicting I2C sensors off a single microcontroller.