Black Lives Matter - Action and Equality. ... Adafruit is open and shipping.

CircuitPython, BusIO and multiple I2C buses
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

CircuitPython, BusIO and multiple I2C buses

by Cruce on Thu Jan 09, 2020 2:30 pm

I have a setup where I am needing to use multiple I2C buses and I would rather not use a multiplexer. I have used the instructions on Instructables for enabling multiple I2C buses on my Raspberry Pi Zero W. I would rather use the existing Adafruit CircuitPython example and not have to write the code needed to use smbus. I have been following this post, ... i2c-busses

I have also looked at this site: ... c-Devices/

I have several I2C devices and yes they all have different addresses and all could be used on the same bus; however, the problem that I am running into is that some devices require a very slow clock and I ran into several issue with trying to change clock speeds on the fly. I was also running into conflicts with one particular device that seem to work better on the bus by itself. This being the a touch screen using the ft6206 chip. So I am trying to get it on a different i2c bus.

Any ways, to get back on topic. I also came across this topic, ... p?t=230828, which is very similar to my issue and some may think it is exactly the same issue.

As for my /boot/config.txt:
Code: Select all | TOGGLE FULL SIZE
I have seen both of these being used.

I am using:

The confusing part is shows 23 and 24 on pins 16 and 18. Yet, I have found several other sites showing images of them on pins 33 and 35. I do know that if I connect the i2c device to pins 16 and 18, the device shows up in i2cdetect. So I am confident that my wiring is correct.

the results of i2cdetect -l is:

i2c-3 i2c 3.i2c I2C adapter
i2c-1 i2c bcm2835 I2C adapter I2C adapter

i2cdetect -y 1
returns 04 and 40

ic2detect -y 3
returns 38

Adafruit even explains how to add additional I2C buses and uses the code below to find the different Board Pins for using with busio.i2c. ... python-i2c

Code: Select all | TOGGLE FULL SIZE
import board
import busio
from microcontroller import Pin

def is_hardware_I2C(scl, sda):
        p = busio.I2C(scl, sda)
        return True
    except ValueError:
        return False
    except RuntimeError:
        return True

def get_unique_pins():
    exclude = ['NEOPIXEL', 'APA102_MOSI', 'APA102_SCK']
    pins = [pin for pin in [
        getattr(board, p) for p in dir(board) if p not in exclude]
            if isinstance(pin, Pin)]
    unique = []
    for p in pins:
        if p not in unique:
    return unique

for scl_pin in get_unique_pins():
    for sda_pin in get_unique_pins():
        if scl_pin is sda_pin:
            if is_hardware_I2C(scl_pin, sda_pin):
                print("SCL pin:", scl_pin, "\t SDA pin:", sda_pin)

However the above code returns nothing. Not even the existing board.scl or board.sda. So my question is how to get busio.i2c to work with scl and sda on different pins. I am using GPIO 23 and 24 on pins 16 and 18. No matter what I try I get the following error:

ValueError: No Hardware I2C on (scl,sda)=(18, 16)
Valid I2C ports: ((3, 3, 2), (1, 3, 2), (0, 1, 0))

I have also tried using (24, 23) and (board.24, board.23) and all return the same ValueError message with different numbers.

Any ideas on how to pass the correct scl,sda info would be great. Ia m starting to think I might have to modify the BusIO.I2C class.

Posts: 2
Joined: Thu Jan 09, 2020 2:25 pm

Re: CircuitPython, BusIO and multiple I2C buses

by adafruit_support_carter on Thu Jan 09, 2020 6:55 pm

When you use CircuitPython on a Raspberry Pi, you are using the CircuitPython libraries, not the actual CircuitPython firmware - which is what runs on smaller MCU's like the Feathers, etc. You are actually running full Python. To allow using CircuitPython libraries with Python on Raspberry Pi, you use the Blinka "shim" - which emulates the same hardware interface that a native CircuitPython board provides.

The i2c-gpio overlay is a software I2C implementation which you can use on any GPIO pins. This is in contrast to hardware I2C ports, which are only available on specifics pins. Those overlays are named like i2c-1, i2c-3.

However, secondary I2C port usage is currently not supported by Blinka. Here are some relevant open issues related to this: (for additional hardware i2c ports) (for software i2c ports)

Posts: 16268
Joined: Tue Nov 29, 2016 2:45 pm

Re: CircuitPython, BusIO and multiple I2C buses

by Cruce on Fri Jan 10, 2020 12:08 pm

Thanks for the information Carter. I have changed my architecture. I have further questions but will start new topics for them.
Just in case anyone is thinking of a similar setup and are having issues or suggestions, here are my multiple setup attempts and what I am going with currently.

First attempt:
Raspberry Pi Zero W with Adafruit 2.8" TFT for Pi w/Capacitive touch and sensors.
I had to drop this idea as it took way too long for the display to show anything until the drivers were loaded and I could run code.
It would be great if the display had a feature where it could automatically load an image from eeprom until it started receiving data from the Raspberry Pi. This way the person using the device didn't have to sit around and wonder if the device was broken or not while waiting for it to display something.

Second Attempt:
Arduino MKR1000 with Adafruit 2.8" TFT for Arduino w/Capacitive touch and sensors.
This worked great. However, I ran into issues where I needed to add additional capabilities, like otg, which are handled better by the Raspberry Pi Zero.

Third Attempt:
Arduino MKR1000 with Adafruit 2.8" TFT for Arduino w/capacitive touch for display and touch only.
Raspberry Pi Zero W with sensors.
The Raspberry Pi Zero W communicated with the MKR1000 via WiFi ad-hoc connection. However, I ran into issues where the WiFi connection wasn't stable or didn't establish connection on power up.

Fourth Attempt:
Same setup as the Third Attempt, but using i2c. I was originally going to try and have both the Raspberry Pi and the MKR1000 setup as masters on a single i2c bus. I have read that it is possible, but I was running into issues. It was easier to let the main i2c bus on the MKR1000 to communicate with the touch screen and setup a second i2c as slave to communicate with the Raspberry Pi.

To further expand on this setup, I thought it might be best if the touch screen was connected directly to i2c bus on the Raspberry Pi instead of the MKR1000. This way I didn't have to pass touch events to the Raspberry Pi from the MKR1000. However, this setup caused the screen to flicker. I found that if the touch screen was the only device on the i2c bus, the flickering went away. Hence, the need to setup a second i2c bus on the Raspberry Pi. Just to be clear, everything is 3.3v. I was concern that the flickering was caused by 5v/3.3v incompatibilities. The display is suppose to be both 5v and 3.3v compatible.

So my final setup is with the touch screen connected back up to the MKR1000. I have the Raspberry Pi sending data that the MKR1000 processes and places on the display. The Raspberry Pi also sends a request to the MKR1000, which returns if the touch event has selected a button on the display and which button it was.

I still think the best setup would have been my first attempt, but even if I could get a Raspberry Pi bare metal setup, 4-10 seconds is still too long to wait for anything to appear on the display.

I'm open to any suggestion.

Posts: 2
Joined: Thu Jan 09, 2020 2:25 pm

Re: CircuitPython, BusIO and multiple I2C buses

by kizniche on Sat Jul 18, 2020 8:12 pm

I found this thread because I was having the same issue, but I noticed this thread went dead in January. However, in April a new Python library, Adafruit_Python_Extended_Bus, was released to address this very issue. I just wanted to leave a reply with this information in case anyone else finds this thread.

Posts: 3
Joined: Sat Nov 14, 2015 1:47 pm

Re: CircuitPython, BusIO and multiple I2C buses

by juan_anciano on Mon Jul 20, 2020 1:50 pm

This thread is also applicable to multiple I2C busses on Raspberry Pi 3: There were problems with OS "i2c-gpio.dtbo" which created issues with default and additional I2C busses. OS has been updated. No further issues noted.

Currently running latest RaspiOS on RasPi 3B+. Configured with two (2) additional I2C busses (used Instructables guide: ... c-Devices/ ). Edited "/boot/config.txt". Respective lines follow:


Installed sensors/peripherals: I2C-1 (default): RGB LCD PiPlate with RGB Negative 20x4 LCD display (addr 20); RGB LCD PiPlate with RGB Negative 20x4 LCD display (addr 21); SHT-31D (addr 44); DS3231 (addr UU/68); BMP388 (addr 77). I2C-3, I2C-4: Each host a single SHT-30 Mesh-protected T/RH sensor (addr 44).

Latest Adafruit Blinka with respective sensor libraries installed. Required modification to "/usr/local/lib/python3.7/dist-packages/adafruit_blinka/microcontroller/bcm283x/" to specifically add respective pins for the additional I2C busses:

i2cPorts = (
# Modified system I2C config per /boot/config.txt
(4, 27, 17),
(3, 24, 23),
(1, SCL, SDA),
(0, D1, D0),

Posts: 8
Joined: Tue Sep 18, 2018 11:36 pm

Please be positive and constructive with your questions and comments.