One sensor works on your desk. Then you add another of the same kind, perhaps to compare temperatures in two places or to give each side of an interactive object its own input, and the readings stop making sense. Both boards have the same connector, so why can't you plug them into a splitter?
With I2C, the controller calls a device by its address. If two connected devices answer to the same address, a different socket does not help the controller tell them apart. An I2C switch can put them on separate branches and connect one branch at a time.
On our bench we tested a GraftSense four-channel module built on TI's PCA9546A, selecting a DS1307 clock on one branch and an SSD1306 OLED on another. Those two devices have different addresses, so the test proves channel selection, not a finished same-address installation. This note covers that test and how to extend it deliberately.
Another socket, another address, or another bus?
First check whether your sensor has an address pin, solder bridge or documented command to change its address. If two distinct addresses cover the project, that may be all you need. For just two fixed-address devices, a second hardware I2C bus on the controller is also straightforward.
A switch earns its place when you want several devices whose addresses cannot easily change: four temperature sensors on four branches, read in turn, or separate display panels, provided the update rate fits the interaction.
A passive splitter only joins wires. The PCA9546A changes which data and clock branches are connected. It does not rename sensors, create four independent controllers, or make four readings happen at the same instant.
This confusion is common. In a February 2020 NI Community thread, a user reading eight sensors found that the switch itself shared the sensors' address. They reported fixing it by changing the switch address and correcting the channel-selection sequence. Different part, same question: which devices are visible on the bus right now?
Wire the host side and the branches separately
The module has one host connector and four downstream connectors. We connected the host side to the GraftPort-RP2040 board's I2C1 port, the clock to channel 0 and the OLED to channel 1. The channel number printed on the switch board is a branch selection, not an RP2040 hardware-bus number.
Check the electrical details before treating matching plugs as compatibility. The module schematic connects 5 V to the branch power pins, while the switch chip runs from a regulated 3.3 V rail, and the host SDA and SCL lines have 1.6 kohm pull-ups to 3.3 V. A bare 3.3 V-only sensor should not receive the connector's 5 V supply just because its I2C signals use 3.3 V.
The schematic shows no separate pull-ups on the downstream branches. Check each connected sensor board and add suitable pull-ups where needed; not every module has them. Their voltage and combined resistance both matter. Turning a branch off disconnects its signal path, not its 5 V supply.
On the RP2040, I2C1 here uses GP2 for SDA and GP3 for SCL. Our first program had the two reversed relative to the wiring table; the MicroPython RP2 quick reference confirms the mapping below. GP numbers are GPIO identifiers, not physical header pins.
Keep three numbers separate
Track three different things: the switch address, the channel you select, and the device address on that channel. Changing one does not change the others.
| In our test | Value | What it selects |
|---|---|---|
| Switch address | 0x70 | The PCA9546A control register |
| Channel 0 | Control byte 0x01 | The branch with the clock |
| Clock address | 0x68 | The DS1307 on that branch |
| Channel 1 | Control byte 0x02 | The branch with the display |
| Display address | 0x3D | The OLED used in this test |
The switch's three address inputs select a seven-bit address from 0x70 to 0x77. On this board the solder selectors sit in the order A2, A0, A1, so read the labels rather than assuming numerical order. These links set the switch's address, not any sensor's. Check them with power removed before choosing the value in software.
Select a branch, then scan it
Each of the low four bits in the control byte enables one branch: 0x01 for channel 0, 0x02 for channel 1, 0x04 for channel 2 and 0x08 for channel 3. Writing zero disconnects all four. The selection takes effect on the I2C STOP condition, which an ordinary writeto call sends. TI's PCA9546A datasheet, sections 8.5 and 8.6, specifies this behavior.
This example writes the control byte directly through MicroPython's standard I2C API instead of using a driver package. We wrote it for explanation and have not run this exact version on hardware.
from machine import I2C, Pin
from time import sleep_ms
bus = I2C(1, sda=Pin(2), scl=Pin(3), freq=100_000)
switch_address = 0x70 # match the actual address links
def select_only(channel):
if channel not in (0, 1, 2, 3):
raise ValueError("Use channel 0, 1, 2 or 3")
bus.writeto(switch_address, bytes([1 << channel]))
try:
bus.writeto(switch_address, bytes([0]))
print("All branches off:", [hex(a) for a in bus.scan()])
for channel in (0, 1):
select_only(channel)
print("Channel", channel, [hex(a) for a in bus.scan()])
sleep_ms(500)
finally:
bus.writeto(switch_address, bytes([0]))
Use the seven-bit address (0x70), not the address byte with a read/write bit appended. Selecting a single bit each time replaces the previous selection, which avoids leaving two branches active once you try identical sensors. If a bus fault also blocks the final write, the cleanup line cannot guarantee disconnection; recovery needs its own plan.
In our test, channel 0 returned addresses 0x68 and 0x70, and channel 1 returned 0x3D and 0x70. The switch stayed visible in both scans while the downstream address changed with the branch.
A scan only shows that something acknowledged an address. It does not show the clock keeping time or the OLED drawing anything. After identifying a branch, select it and use the device's own driver to do something meaningful, such as reading the time or drawing a known pattern.
Now try two devices with the same address
Once single branches work, put one identical sensor on each of two branches. Select the first branch, initialize that sensor and read it; then select the second and repeat. Seeing the same address in both scans is expected; the branch gives the address its context.
Give each reading a physical identity in your application, such as "inside enclosure" and "outside enclosure," and test it. Change the condition at only one sensor and confirm only its labeled reading responds. That catches swapped cables and wrong-channel reads that a clean scan will never reveal.
Every operation on a sensor, including initialization, must happen while its branch is selected. If several tasks share the bus, keep the branch selection and the following transaction together so another task cannot switch branches in between. Separate sensor objects may still share one I2C bus underneath; creating an object does not reserve its branch.
The PCA9546A can enable several branches at once, but that does not remove a clash between identical devices. For individual reads, keep conflicting devices off the visible bus. The same applies across two switches: giving the switch boards different addresses does not stop their downstream sensors from colliding if both paths stay connected.
Decide whether the arrangement fits the product
For slow environmental readings or separate display updates, sequential access usually fits. If measurements must represent the same instant, specify that timing before choosing the bus arrangement; switching branches adds transactions, and each sensor's conversion timing decides when its measurement was actually taken.
Plan what happens when a branch stops responding. The chip has an active-low reset input, but on this module RESET is pulled high and the four-wire host connector does not carry a reset line. A program cannot assume it can clear every bus fault by sending another command down the same stuck bus. Decide on recovery access while the design is still easy to change.
Test with the intended cables and connectors. A switch manages branches; it is not a fix for long I2C runs. Pull-ups, capacitance, operating voltage and the devices on each active path still have to work together.
Before making several units, record the switch address, the connector-to-channel map, the sensor addresses and the expected scan results. Then test real readings and startup recovery on the assembled prototype, not only on loose boards.