Just finished putting making a nice birthday card for my grandmother.
SparkFun’s Peter Dokter has an interesting video talking about SPI and i2c comms. i2c in particular is a great bus mechanism, due to the microprocessor only needing TWO wires to control (almost) any number of devices.
Each device on an i2c network has a 7-bit address, so a single network theoretically supports up to 128 slave devices.In practice though, the limit is much lower. i2c slave chips often support only 8 different bus addresses, no more than 8 of that chip can be attached to the same i2c network. Others like the MPL3115A2 aren’t configurable at all! Some people really do want more than one altimeter…
You could have more than one chip to an address, it just means that the chips change in lockstep with each other, and any returned values are likely to be garbage. (being ANDed together by the open-drain bus)
Enter the i2c PCA9547 multiplexer. It allows you to have multiple i2c ‘channels’, and decide which one is active at any one time. That way, you could for instance have one MPL3115A2 altimeter on each channel, for a total of 8 in your system instead of just one. Ironically, the multiplexer suffers from the same address issues as the other chips; You can fit only 8 multiplexers on an i2c bus.
Or you can be sneaky… What’s the maximum number of uniquely controllable 1-address i2c devices you can put on a multiplexed i2c network?
One bus, one device. Not much fun.
Let’s add a PCA9547 multiplexer! Now we have 8 switchable channels, and 8 individually controllable devices.
But we can do better.
8 multiplexers × 8 channels = 64 devices, that each get a whole bus channel to themselves!
We can do better.
Not only can we attach multiple multiplexers to one bus, we can attach a multiplexer to another multiplexer. In this simple tree configuration, the controller is connected to a multiplexer with address 000. Each of 000‘s 8 channels is connected to a multiplexer with address 001. (For the same reason that we can have multiple devices with the same address if they’re not simultaneously connected, we can put same-address multiplexers on different channels.)
So, going down the tree, there are:
1 of 000
8 of 001
64 of 010
… and so on, down to;
16,777,216 of 111
And each 111 multiplexer has 8 channels, so we have 134,217,728 individually selectable bus segments, and can support that many single-address devices. Should be enough?
At this scale, we’d need 19 MILLION multiplexers, which not counting the net routing, the pull-up resistors, the power requirements, or the devices we’re supporting, would require (according to the package size) a circuit board with an area of more than 300 square metres.
We can do better!
(It becomes unwieldy at this stage to try and draw even collapsed collections of multiplexers, so for the above, imagine that boxes with plural labels indicate multiple chips, and thick connections represent the 1:8 fan-out discussed previously.)
Reading the PCA9547 datasheet, it mentions that you can also disable the multiplexer entirely so that no channels are selected. This allows another fun technique. In the above diagram, the left-most column is the tree structure show in the previous step. The second column is a slightly smaller tree starting at 001, and so-on.
By disabling all top-level multiplexers, then only enabling the multiplexers needed, all of the devices in all the trees can be accessed. The diagram only shows the first generation of extra multiplexers, this process can be recursively applied to each sub-tree.
Eg to access a channel in multiplexer 101 → 3 → 1 → 7:
- Disable all multiplexers
- Enable 101, select channel 3
- Enable 110, select channel 1
- Enable 111, select channel 7
(At this stage, multiple 110 and 111 multiplexers are ‘on’. We need to switch them off)
- Disable 101
- Disable 111
- Disable 110
- Re-enable 101. Now only the correct path is open, and the device can be accessed.
This adds 19 million extra devices on top of the 134 million we get from the simpler tree in the previous step. Now, that’s enough?
A few more can be added through further recursion, but there are diminishing returns.
Left as an exercise for the reader. What if you have multiple i2c multiplexers with the same address in sequence? If initially active, sending ‘disable’ would probably switch all of them off. And then sending ‘enable’ would activate only the first one…