I2C is a handy protocol to control plenty of chips/sensors/actuators with only 2 pins. With 128 adresses available you would think you are not going to run into an address conflict, meaning you want to use 2 modules that have the same I2C address, but you’d be surprised. Many I2C modules can in fact be set for another address, usually through some address jumpers, but that is not always possible. Even when the chip itself has a possibility to select more than one I2C address, the module does not always implement that (Various PCF8591 modules for instance)
The Adafruit I2C address list shows the I2C addresses of many modules.
The Arduino does have one hardware I2C port, except for the Arduino Due, that has 2.
So what can we do to use 2 or more I2C modules that share 0ne address?
The only solution is to create multiple I2C busses.
This can be done in 2 ways:
Software
The Wire Library that comes with the Arduino IDE only allows you to use the pins on the Arduino that are meant for I2C:
Board | I2C / TWI pins |
Uno, Ethernet | A4 (SDA), A5 (SCL) |
Mega2560 | 20 (SDA), 21 (SCL) |
Leonardo | 2 (SDA), 3 (SCL) |
Due | 20 (SDA), 21 (SCL), SDA1, SCL1 |
The Wire library doesn’t cater for multiple I2C busses, you can only call one instance of it.
So you will need a library that does allow multiple I2C objects. The following libraries do that.
SoftI2CMaster is a lean I2C implementation.
SoftWire allows any pins of the Arduino to be used. It needs another library called AsyncDelay.
Software_I2C on GitHub might be akin to this one from Seeedstudio, but I did not make a full comparison.
Some more multiple bus Software I2C libraries can be found here.
Using those software libraries is a quick and easy way to set up multiple I2C busses, but there is one major drawback. That is the fact that many existing libraries for I2C peripherals make direct calls to the “Wire” library. These would need some modification to make them work with another I2C library.
Hardware.
Instead of a software solution, it is also possible to use an I2C port expander. The TCA9548A is such an expander. It connects to the existing I2C port and then can be made to send commands to 1 of 8 different I2C ports.
The TCA9548A has its own I2C address of 0x70, which can be changed using three pins. This allows you to have up to eight of these modules in your design, adding a total of 64 extra I2C buses that of course each can address some 128 device
The TCA9548A operates on a range of 3 to 5.5 volts, making it suitable for say ‘old’ Arduino 5 Volt logic as well as the new 3V3 logic.
Its use is quite simple: One only needs to write the required bus nr (0-7) to the Chips address (0x70 by default).
It is easiest do to this in a routine:
void TCA9548A(uint8_t bus) { Wire.beginTransmission(0x70); // default TCA9548A address Wire.write(1 << bus); // select bus Wire.endTransmission(); }
a program thus could look as follows:
void setup() { TCA9548A(0); setup your device connected to bus 0 TCA9548A(1); setup your device connected to bus 1 } void loop() { TCA9548A(0); write to (or read from) device connected to bus 0 TCA9548A(1); write to (or read from) device connected to bus 1 } void TCA9548A(uint8_t bus) { Wire.beginTransmission(0x70); Wire.write(1 << bus); Wire.endTransmission(); }
As said, the default address of the TCA9548A is 0x70, but can be changed over the range 0x70-0x77. Make sure that you have no other chip on the chosen address as commands to that chip could be seen as commands to the I2C expander.
Chips in that range are:
- HT16K33 LED Matrix Driver (0x70 – 0x77)
- PCT2075 Temperature Sensor (0x28-0x2E, 0x48-0x4F, 0x70-0x77)
So make sure you choose another address for them than the addresss you put the Expander (0x70-0x77) on.