Skip to main content

TCA9548A Python Library

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.

Installation

Install the required dependency:

pip install -r requirements.txt

Or install directly:

pip install smbus2

Usage

Basic Setup

from 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}")

Selecting Channels Directly

# Connect only channel 3
tca.select_channel(3)
print(tca.get_selected_channels())  # [3]

# Disconnect everything
tca.deselect_all()
print(tca.get_selected_channels())  # []

Scanning a Channel

# 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]}")

Behind the Mux: Driving Another Chip Through a Channel

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.

Cleanup

# Close I2C bus when done
tca.close()

Examples

See the examples/ directory:

  • examples/example_scan_all_channels.py: select each of the 8 channels in turn and scan for devices behind it
  • examples/example_behind_the_mux.py: drive an MCP23008 that sits behind channel 1, using tca[1] as its i2c_bus
  • examples/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 own smbus2.SMBus on first use, and close() 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 exposing writeto(address, buffer)/readfrom(address, length)/scan(); since you own the connection's lifecycle, TCA9548A won't open or close it for you.

Multiple Channels At Once

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).

Scope

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.

Error Codes

  • TCA9548A_OK (0x0000): Success
  • TCA9548A_CHANNEL_ERROR (0xFF81): Invalid channel number
  • TCA9548A_I2C_ERROR (0xFF82): I2C communication error

Notes

  • Make sure I2C is enabled on your system! On Raspberry Pi this is done using sudo raspi-config -> Interface Options -> I2C
  • Uses smbus2 for 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=0 for 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. i2cdetect avoids 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 on scan() on a system with devices in those ranges.

License

Released under the MIT licence.

Metadata

Release files for tca9548a 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tca9548a 0.1.0
File Size Uploaded Provenance Actions
tca9548a-0.1.0.tar.gz 7.7 kB Without provenance Details for tca9548a-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tca9548a 0.1.0
File Interpreter ABI Platform Actions
tca9548a-0.1.0-py3-none-any.whl Python 3 none any Details for tca9548a-0.1.0-py3-none-any.whl

Total release size: 16.0 kB

Release files / tca9548a-0.1.0.tar.gz

Download URL tca9548a-0.1.0.tar.gz
Size 7.7 kB
Tags Source
SHA-256 checksum
How to use checksums
aed7c1a84fd037cea301bdd996a3a88f8c46a00cad2501e3f7054b15d786cec5
BLAKE2b-256 checksum
How to use checksums
e8167e14a1f53ecfaba55a47065d2c817ca87d403a54546c33cccc260deb880a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release files / tca9548a-0.1.0-py3-none-any.whl

Download URL tca9548a-0.1.0-py3-none-any.whl
Size 8.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9bba2e7b839c9b4951c7300b628953233b5c13ff6c51ab3b5dcc63aad4cf69df
BLAKE2b-256 checksum
How to use checksums
093a3c2b6c3fc4c399bbb8a054f4efddcfadfd892d561b1bdff865e4abc85330
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Security for tca9548a 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page