Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

Python library to control the TCA9548A I2C multiplexer

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages