1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ "Fewer" not "less". What is the sensor - data sheet please. \$\endgroup\$ – Andy aka Jul 10 '18 at 13:24
  • 1
    \$\begingroup\$ You have 2 I2C busses in your micro, so you can perform 2 I2C operations at one time. It shouldn't matter if you split each one as 2x8 or 4x4, you can still only talk to one device per bus at a time. \$\endgroup\$ – brhans Jul 10 '18 at 13:32
  • \$\begingroup\$ @Andyaka, the post has been edited. \$\endgroup\$ – J. K. Jul 10 '18 at 13:34
  • \$\begingroup\$ @brhans, that is indeed the conclusion I came up with. I wanted to be sure I wasn't missing something. The only difference I see so far is the number of pull-up resistors I will have to use but it is not a big deal for me. \$\endgroup\$ – J. K. Jul 10 '18 at 13:36
  • 1
    \$\begingroup\$ @ChrisKnudsen Please write answers in the answer box so your answer can be vetted by voting, editing, accepting, etc. \$\endgroup\$ – pipe Jul 10 '18 at 13:55
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your answer. I had this in mind but I though the command to switch the multiplexer would be unsignificant compared to the time to read each sensor. Do you think those commands would increase the update rate considerably ? \$\endgroup\$ – J. K. Jul 10 '18 at 14:05
  • \$\begingroup\$ @J.K. depends. Takes two I2C bytes to change bus. So by having 8 per bus you save two bytes each time you read from all the sensors (that's 40us with a 400kHz bus). \$\endgroup\$ – Tom Carpenter Jul 10 '18 at 14:11
  • \$\begingroup\$ True. With this in mind, is it correct to say that it is better to use buffers as described in the TI Application Report (PCA9515 for example) over mux as their command requires just one extra pin (for a 2-channel switching) and not I²C commands ? \$\endgroup\$ – J. K. Jul 10 '18 at 14:19
  • \$\begingroup\$ @J.K. essentially an I2C mux is basically just an I2C I/O expander, and a series of buffers. The I/O expander simply selects which buffer is enabled. If you've got the spare I/O pins on your MCU, you can follow the TI app report and use buffers - essentially your MCU I/O pins replace the I2C I/O expander. \$\endgroup\$ – Tom Carpenter Jul 10 '18 at 14:22
  • \$\begingroup\$ Perfect, I'll go for this and let you know in case of any issue. \$\endgroup\$ – J. K. Jul 10 '18 at 14:26
1
\$\begingroup\$

From a programming viewpoint:

Most likely all your magnetometers are handled by one single thread. Favourably, reserve one I²C bus for this thread, so you can easily implement isochronous sampling. That will make it simpler to implement a time-discrete closed-loop control.

The other I²C can then be controlled by another thread and collects all the other sensors you might need.

\$\endgroup\$
0
\$\begingroup\$

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.

According to the data sheet, to set 8 slaves with different addresses requires 7 extra IO lines. To route (via a mutliplexer) the bus to 32 slaves requires 5 extra IO lines and no messing with setting up the slave addresses.

You can probably use a standard mutiplexer (1:16 or 2 x 1:8) to switch power to 1 out of 16 slave devices (or 2 slaves on different I2C busses) and hence the bus(ses) need not be multiplexed. I don't know what the startup time from a power off condition is for the slaves hence this might end up being a little slow.

I'm certainly not saying that this is the optimum solution for your specific application but it should be considered as an option if IO pins are in demand.

\$\endgroup\$
  • \$\begingroup\$ It is true, I'm considering (for now) that I will have enough IO pins in order for this not to be a problem. \$\endgroup\$ – J. K. Jul 10 '18 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.