Electronic – Multiple I²C slaves with different addresses VS. using a multiplexer

busi2cmultiplexersharedbus

I'd like to interface a lot of identical I²C sensors, let's say 32, with a MCU that has only 2 I²C busses.

I can configure each sensor to have up to 8 different addresses. Hence I can have 8 sensors per bus or 16 sensors in total which is not enough for my application.

I plan to use a multiplexer or some sort of I²C buffer (described in this document, page 8) in order to increase the number of sensor I can interface.

However, I have now to choose in between several options :

  • Having 4 different sensor busses with 8 sensors each and using two 2-channel multiplexers (or buffers) on each MCU bus to switch between those 4 sensor busses.
  • Having 8 different sensor busses with 4 sensors each and using two 4-channel multiplexers on each MCU bus to switch between those 8 sensor busses.

Those are just examples, there is plenty of other configurations but the question is the same :

Is there a reason to prefer having more channels with fewer sensors on each over having fewer channels with more sensors on each ?

I tried to figure out if there would be a change in the max. update rate of my sensors in each configuration but I can't see any difference.

If some of you already faced this dilemna and/or has any element of answer, I'd be glad to hear it !

EDIT : the sensor in question is the TLV493D, a 3-axis magnetometer. A descritpion of the bus with up to 8 sensors is available at page 24 of the User Manual linked previously.

I have no precise idea of multiplexers yet but it will probably be something similar to the PCA954* family.

Best Answer

On further inspection of the devices you are using, it seems that in order to configure their address, you need to be able to power up each device individually, which means that you will need one I/O pin per device to be able to set the address.

Additionally to be able to configure 8 addresses, you need to be able to set the voltage on the SDA pin when the device is powered on. This condition will be difficult to satisfy using I2C multiplexers. In order to achieve it, you would have to send a packet over the I2C bus, making sure to hold the SDA line either high or low for 200us. During these 200us, you need to power on a device.

Because of this, you may be better off choosing a different set of options from my original suggestion:

Option 1

The simplest method would be to use a pair of I2C multiplexers, one connected to each I2C master. Each I/O expander would have 4 downstream buses of 4 devices.

Because there are only 4 devices on each bus, this means that the LSB of the address (set by the SDA/ADDR pin voltage at power on) can always be set to 1 (the idle value of the I2C bus). This removes the difficulty of setting the SDA voltage to the correct level when powering on the devices.

Secondly, you can limit yourself to only needing 3 I/O pins to power up the devices. The power on sequence can become:

  1. The first device on each bus powers on with VCC. Once powered on, you write to each bus to change the MOD1 register to b11.

  2. You use an I/O line to power up the second device on each bus. Again you can now write to each bus and change the MOD1 register to b10.

  3. You use a second I/O line to power up the third device on each bus. Write to each bus to change MOD1 to b01.

  4. You use your third I/O line to power up the forth and final device on each bus.

This now gives you 8 buses, each of which consists of 4 devices with a unique address. There is no need to mess around with setting the SDA/ADDR pin to a specific voltage.

Option 2

The second option is to use an I2C buffer/isolator (e.g. PCA9515a) for each device. You connect one group of 16 via isolators to one master, and the other group of 16 via isolators to the second master.

You would then need 16 I/O pins to control the enable pins of the isolators. Each I/O pin controls an isolator on each I2C master.

To read from a device, you simply enable the corresponding isolator, and read two devices simultaneously using your two masters. Enabling I/O pin 0 allows reading from device 0 on each master, I/O pin 1 enables reading from device 1 on each master, and so on.

To save I/O pins, you could used a 74HC154 or similar 4:16 line decoder, given that you will only ever have one isolator selected at any given time. This reduces your I/O pin requirement from 16 down to 4.



Old Answer (applicable to devices that set address using Axx pins):

When using an I2C multiplexer, you have to write a command to the multiplexer to change which downstream bus is currently active. This takes time to do.

If you have fewer downstream buses to switch between (i.e. maximise the number of devices on each bus), you reduce the number of commands required to read all devices - you can read all devices on a bus, then switch to the next bus.

The fastest way to read all devices is going for the option which has more devices per downstream bus and fewer downstream buses.

In your case you have two upstream buses. Connect each of these to an I2C multiplexer. To each I2C multiplexer make two downstream buses of 8 devices.

While you can choose to go with a 1:2 mux which gives you just enough address space, you could still go with a 1:4 mux leaving two downstream buses unused on each mux. This gives you the ability to add extra devices later on if needed.