Using multiple identical I2C devices

A video supporting this article is available here:

The Basics of I²C
I²C was created by Philips in the early 1980’s as a way of talking to relatively slow devices over a common bus. A bus is just a group of wire connections in which usually several devices can be connected to the same bus as the same time. It allows for less complex and cheaper circuit boards and quite commonly an easier programming interface due to consistent design implementations for devices that must connect to it.

The Basic I²C Protocol
Each device on the bus has an address (an ID number) in the range 0-127 (0 – 7F Hex). The controlling processor (these days usually an MCU of some sort for our purposes) sends out the address of the device they want to talk to first and at this point all devices on the bus are listening to see if they are going to be talked to by this “Master”. If they see their address on the bus they send an acknowledgement that they are there, all the other devices now stop listening and ignore what’s on the bus. The master then sends data to the device or requests data from it (depending on what the device is). If no acknowledgement is received the data or request will not be sent.

The problem with multiple identical devices on the same I²C bus
You may have worked out the problem, if the same identical devices (i.e. a displays or temperature loggers) are on the same bus then they will have an identical address. In fact as there are only 128 (0-127) address’s available then even some completely different devices may have the same address anyway. In this scenario it is impossible to talk to them separately. Let’s take two examples a display and temp sensor. We want to send data to draw a line on just one of the screens, but how? They both have address of say 0x3C, we send this out and then the data and as both are address 0x3C they will both read in the data on the bus at the same time and both display the line. For a temperature sensor it may be worse, both sensors will potentially put data on the bus at the same time and this will corrupt the bus data or perhaps one will put it’s data on and another time the other but you will have no way or working out which one of the two actually did put their data on the bus.

The solution
Some devices allow you to select (on the physical pcb) perhaps one different address and this would work for two identical devices but in reality very few do this and if you wanted more than two then it is still a problem. We need some way of routing the I²C signals to one of the devices only but not the others. This problem was seen some time ago and I²C support chips that support this exist – enter the TCA9548A. This is available for prototyping work as a breakout board from many suppliers, here’s the one I bought.

 

It has the obvious connections for power and ground and two connections for SDA (Data) and SCL (Clock). In addition it has multiple SDA and SCL connections that go to your devices, these are labelled SD0 to SD7 for data and SC0 to SC7 for clock. Each or your identical devices should connect to one set of these. We will talk about the other connections later.

 

How to use the TCA9548A
The basic operation of the TCA9548A  is that it will re-route the Data and clock going into its SDA and SCL connections to one of its various output pairings (SD0 to SD7, SC0 – SC7)  respectively. Therefore if we connect each of our identical devices to one of the available pairings then we can select which gets SDA and SCL and which don’t. The TCA9548A itself is a I²C device and to select which of it’s 8 outputs gets the I²C data and clock involves sending it a short command stating which connections will be active. The default I²C address of this device is 0x70. Here’s a routine to do this;

To use it you just call it with the number of the connection you wish to use. So for example if you had two screens, one connection to I²C 0 on the chip and the other to I²C connection 1 the following sequence would allow you to write to both screens.

SetI2CConnection(0)

Write whatever you need to the first screen

SetI2CConnection(1)

Write whatever you need to the second screen

 

At any one time only one screen will be getting the commands to their common I²C address.

 

The other connections on the TCA9548A  

In addition to the I²C connections there are four more, the first is the Reset line and when sent low will perform a reset of the device. The remaining 3 are A0 to A2 and are a way of altering the I²C address of the TCA9548A itself. By default (and if they are all held low) the address is the default of 0x70. If A0 is pulled high it would be 0x71, etc. etc. (counting up in normal binary) up to 0x77. This helps if you have a device on the bus that is itself 0x70 or it could also be used so that you could have multiple TCA9548A’s  on the same bus to allow even more identical devices than 8 on the bus – amazing!

An Example – Two Screens
As a working example I’m going to control to OLED 128×64 screens – see this article to install the relevant libraries and to take you through setting up one screen. To add two screens use the following circuit diagram and just underneath it I’ve added my actual circuit.

 

Click to Enlarge

The Code
The code below will draw one line vertical going from left to right and back again on one screen and draw one horizontal line going down and then back up repeating all the time.

 

Problems Problems
On power up sometimes the screens aren’t working, I’ve been investigating this and have tried hardware changes and software changes and both. I won’t go into the things I’ve tried but it’s still an on-going situation and the only work-around is to perform 2 or 3 soft resets using the Nano’s reset button. I do have a good suspicion of what I need to do but further work is required and I’ve spent too much time on the problem for now. I will update this article when I can get a fully working reliable solution. But for now I’ve worked on another solution that does work fine using a 74 series logic chip. These were designed back in the late 60’s and 70’s and were very popular inside of late 70’s early 80’s home computers before ULA (Un-comitted Logic Array) chips took over. They are still widely available to buy and very very cheap depending on what you need. See this article (not written yet!).

Another alternative is that some OLEDs of the type shown can change their I2C address by changing a simple link on the PCB. I found one like this in my collection of these screens but all the rest lacked anyway that I could see to change the address so I think for many people this would not be viable alternative if supplies of  the correct screen cannot be guaranteed.

It should be noted that this issue almost certainly will not occur with other I2C devices or perhaps even these screens with a different driver.