The Texas Instruments TCA9548A is an 8-channel I2C multiplexer: it lets up to 8 downstream I2C buses share the same upstream bus and controller, each addressable independently, even if devices on different channels share the same I2C address.
This library was created for use with the Testomatic PCB test jig system, which uses a TCA9548A to address multiple identical IOMOD modules from one I2C bus, but it is designed to be a self-contained driver that can be used in other projects.
It follows the same injectable-transport design as this project's sibling
ad5593r and
mcp23008 libraries, with one
addition: a channel object exposes that exact same writeto/readfrom/
scan shape, so it can be handed straight to another chip's driver as its
i2c_bus. See the "Behind the Mux" example below, which is this
library's main reason to exist.
Install the required dependency:
pip install -r requirements.txtOr install directly:
pip install smbus2from tca9548a import TCA9548A, TCA9548A_DEFAULT_ADDRESS
# Create instance with I2C address 0x70 (the default, set by the A0-A2 pins)
# bus_number defaults to 1 (for Raspberry Pi)
tca = TCA9548A(TCA9548A_DEFAULT_ADDRESS, bus_number=1)
# Check connection
print(f"Connected: {tca.is_connected()}")
print(f"Address: 0x{tca.get_address():02X}")# Connect only channel 3
tca.select_channel(3)
print(tca.get_selected_channels()) # [3]
# Disconnect everything
tca.deselect_all()
print(tca.get_selected_channels()) # []# tca[n] returns a TCA9548AChannel for channel n, which selects itself
# automatically before each operation
addresses = tca[3].scan()
print(f"Devices on channel 3: {[hex(a) for a in addresses]}")You can use this library as a simple driver for the TCA9548A, but it
can perform a very handy trick because tca[n] behaves like an
I2C bus of its own and can be passed directly as another chip driver's
i2c_bus. For example:
from tca9548a import TCA9548A, TCA9548A_DEFAULT_ADDRESS
from mcp23008 import MCP23008, PinMode
tca = TCA9548A(TCA9548A_DEFAULT_ADDRESS, bus_number=1)
# An MCP23008 at 0x20 on channel 1, addressed through the mux
mcp = MCP23008(0x20, i2c_bus=tca[1])
mcp.pin_mode(0, PinMode.OUTPUT)
mcp.digital_write(0, 1)Every writeto/readfrom/scan call that mcp makes will then
reselect channel 1 first automagically, so other channels' devices
(which may share the same I2C address but be connected to a different
channel) are never accidentally addressed.
# Close I2C bus when done
tca.close()See the examples/ directory:
examples/example_scan_all_channels.py: select each of the 8 channels in turn and scan for devices behind itexamples/example_behind_the_mux.py: drive an MCP23008 that sits behind channel 1, usingtca[1]as itsi2c_busexamples/example_tca9548a_passed_i2c.py: the same channel-scanning example, but with the I2C connection set up externally and passed in
example_scan_all_channels.py and example_tca9548a_passed_i2c.py cover the same operations but show the two ways to set up the I2C connection, so you can compare them directly:
- Let TCA9548A manage it (
bus_number=1, the default) -- the simplest option. TCA9548A lazily opens its ownsmbus2.SMBuson first use, andclose()closes it. This is enough for the common case of a single upstream bus on the Raspberry Pi. - Set it up yourself and pass it in (
i2c_bus=...) -- needed whenever something else has to control the connection: for example, several devices sharing one bus. TCA9548A only needs an object exposingwriteto(address, buffer)/readfrom(address, length)/scan(); since you own the connection's lifecycle, TCA9548A won't open or close it for you.
The control register is a plain 8-bit mask, not a one-hot selector -- more
than one channel can be connected simultaneously if the devices behind
them have distinct addresses. TCA9548AChannel (via tca[n]) always
selects exactly one channel, which is what this project needs and is the
safest default. For multiple channels at once, use write_control()
directly with a combined bitmask (e.g. tca.write_control(0b00000101)
for channels 0 and 2).
This library only supports the genuine 8-channel TCA9548A. It does not support the 4-channel TCA9546A/PCA9546A variant, which has a smaller channel range (0-3) and would need its own bounds checking.
TCA9548A_OK(0x0000): SuccessTCA9548A_CHANNEL_ERROR(0xFF81): Invalid channel numberTCA9548A_I2C_ERROR(0xFF82): I2C communication error
- Make sure I2C is enabled on your system! On Raspberry Pi this is done using
sudo raspi-config->Interface Options->I2C - Uses
smbus2for I2C communication - Default I2C bus is 1 for Raspberry Pi. Modern Raspberry Pi models reserve bus 0
for Pi Hat EEPROMs that are read at startup. Use
bus_number=0for older Raspberry Pi models - The device supports I2C addresses 0x70-0x77, set by the A0-A2 pins
- The default transport's
scan()uses an SMBus quick-write probe on every address from 0x03-0x77.i2cdetectavoids quick-write specifically on 0x30-0x37 and 0x50-0x5F by default, since a write-type probe can disturb some devices in those ranges (e.g. triggering an EEPROM write cycle). Worth checking before relying onscan()on a system with devices in those ranges.
Released under the MIT licence.