0

I have a Raspberry Pi 4 and I need to setup a program that can address many more ports than the Pi has. So far, I have three MCP23017 ICs and they are connected to the standard i2c bus on pins 3 and 5. The code I have written works fine with these three ICs, identified as device1-0x20, device2=0x21, etc. But as there can only be eight of these ICs on that bus due to them having only a three bit address line, I setup a second i2c using pins 23-SDA and 24-SCL. This bus is bus3, and typing in i2cdetect 3 with the ICs connected to it shows they have the same address as on the standard bus. 0x20, 0x21, etc. What I don't know is how to reference these two buses in my code. I presume there is some sort of prefix to be applied to the ICs address. I can't seem to find the answer to this on this or other forums. It's probably simple, but as a newcomer to the whole R/Pi world, I'm still on that learning curve.

I'm using Python provided with Raspbian, importing smbus.

Thank you, Hargrovm. The answer is as simple as you say—just instantiate the relevant bus number.

In my code, I had the usual bus=smbus.SMBus (1). This, of course, relates to the provided i2c bus on pins 3 & 5, so I changed that to - busA=smbus.SMBus(1) and then added busB=smbus.SMBus(3). I have patched over 1 of my 3 (so far) MCP23017 ICs to that second i2c (on pins 23 & 24 with 2.2k pullup resisters) and altered the code that referenced that chip throughout, and it all worked. I will only need two i2c buses with eight MCP23017 ICs on each, but clearly this is the way to connect to multiple i2c ports.

2
  • 1
    You need to specify which language you are using to write your program, because the answer will depend on that.
    – PMF
    Mar 31, 2020 at 6:09
  • 1
    Also provide the code you are currently using as it may be library dependent.
    – joan
    Mar 31, 2020 at 8:34

2 Answers 2

1

If you're willing to add one extra piece of hardware (e.g. the PCA9548, an 8 channel I2C multiplexer) to your setup then you're comfortable to have 8 (!!!) extra I2C buses "for free" with the newer Raspberry Pi distros. That is a total of 9 I2C buses (including the original one) with one and the same set of standard I2C pins: pin 3 for SDA and pin 5 for SCL. No need to "steel" the other I2C pins.

That means, you will be able to connect 8 x 9 = 72 MCP23017 devices to the RPi. That is a whopping total of 72 x 16 = 1152 extra IO pins for the RPi!!! Don't tell me you need more... :-)

Since the Jessie distro, IIRC, the kernel now contains an extra module typically used for different types of I2C multiplexers. Two popular ones are the PCA9544 (which adds 4 extra I2C buses to the RPi) and the PCA9548 (which adds 8 extra I2C buses to the RPi). Or compatible types (e.g. TCA9548 from Texas Instruments).

You only have to add one line to the file /boot/config.txt. At the end of that file, add the following line (in case you're using a PCA9548):

dtoverlay=i2c-mux,pca9548,addr=0x70

The first I2C address of the PCA9548 is 0x70, so make sure you connect the 3 address lines to ground. But since you already have used other I2C devices, I'm sure you know what I mean.

Once you reboot, you should have something like this when running the command sudo i2cdetect -l:

pi@rpi3bplus:~ $ sudo i2cdetect -l
i2c-3   i2c             i2c-1-mux (chan_id 0)                   I2C adapter
i2c-1   i2c             bcm2835 I2C adapter                     I2C adapter
i2c-8   i2c             i2c-1-mux (chan_id 5)                   I2C adapter
i2c-6   i2c             i2c-1-mux (chan_id 3)                   I2C adapter
i2c-4   i2c             i2c-1-mux (chan_id 1)                   I2C adapter
i2c-9   i2c             i2c-1-mux (chan_id 6)                   I2C adapter
i2c-10  i2c             i2c-1-mux (chan_id 7)                   I2C adapter
i2c-7   i2c             i2c-1-mux (chan_id 4)                   I2C adapter
i2c-5   i2c             i2c-1-mux (chan_id 2)                   I2C adapter

To run i2cdetect, make sure you have installed i2ctools (sudo apt-get install i2c-tools).

Needless to say that this won't work if you don't connect the mux to the RPi prior to rebooting the device...

The only thing you have to do now, is to select the correct /dev/i2c-x as I2C bus for your different MCP's in your I2C command that you send out. No need to control the PCA itself to set the muxes in the right position since the kernel will do this "transparent" for you, based on the I2C dev you've given...

Depending on the language you're using, the name of the /dev file might be different. For instance, if you would use Pi4J (Java) and you want to access an IO expander connected to, say, bus 9 you would give something like this:

sGpio01 = new MCP23017GpioProvider(I2CBus.BUS_9, 0x20, mPollingTime);

The important part here is I2CBus.BUS_9, since that's a define for /dev/i2c-9. But I guess you get the picture, right?

Another very important advantage of using the PCA9548 mux is that you can drive the mux directly from the 3V3 lines of the RPi and you can attach 5V devices to the 8 I2C output buses!!! Just make sure you power the mux with the 3V3 coming from the RPi...

See the respective datasheets for more detailed information. There's a nice "Application design-in information" chapter in the NXP datasheet (PCA9548).

You get a level converter for free on top of all the extra IO pins you already have...

If that's not a nice nifty little extra thingie...

0

As @joan said in the comments without knowing which specific library you are using it's difficult to be certain. The snippet below uses smbus2 which is supposed to be a drop in/side-by-side replacement for smbus so solutions for either library should be similar, if not the same. It should be as simple as instantiating the bus instance with the required bus number in your case (3).

from smbus2 import SMBus

# Use a context manager to open I2C Bus 3, read 1 byte from address 80 offset 0.
with SMBus(3) as bus:
    b = bus.read_byte_data(80, 0)
    print(b)

Equally, this should work with the smbus library. I've used the the smbus2 library in my example because that is where the sample code comes from.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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