Enable both I2C Busses

56 posts   Page 3 of 3   1, 2, 3
by JulianBrooks » Wed May 01, 2013 8:04 am
Nice, but a bit scary.

I really need to get my soldering skills down (and probably some better/more equipment) to be feeling confident to try something like this.

Thanks for sharing though, good to know it's doable.

We've ended up going for the IC demultiplexer method. Will update with our progress when the various bits and pieces arrive and we put them together - hopefully Friday.

Posts: 35
Joined: Wed Mar 20, 2013 1:08 pm
by sukisan » Thu Sep 25, 2014 11:09 pm
I'm using bgreat's python solution to work with both I2C busses. He also mentions one needs to add your own resistors. This and that suggest that you can simply configure pull up resistors. Can anyone confirm this works? bgreat?

I dug around in the bcm2835 source and ported the methods along with the original source to Python 3. I'm in particular unsure about the byteorder in configure_pull_up..again, review and second opinion highly appreciated!

Code: Select all
#!/usr/bin/env python3
# W. Greathouse 13-Feb-2013
# S. Ludwig 26-Oct-2014
# Inspired by bcm2835 source - http://www.airspayce.com/mikem/bcm2835/
#   Enable I2C on P1 and P5 (Rev 2 boards only)

# #######
# For I2C configuration test
import os
import mmap
import time

BCM2708_PERI_BASE = 0x20000000 # Base address of peripheral registers
GPIO_BASE = (BCM2708_PERI_BASE + 0x00200000)  # Address of GPIO registers
GPFSEL0 = 0x0000 # Function select 0
GPFSEL2 = 0x0008 # Function select 2
GPPUD = 0x0094 # GPIO Pin Pull-up/down Enable
GPPUDCLK0 = 0x0098 # GPIO Pin Pull-up/down Enable Clock 0
GPIO_PUD_OFF = 0b00   # Off - disable pull-up/down
GPIO_PUD_UP = 0b10    # Enable Pull Up control

def get_revision():
    with open('/proc/cpuinfo') as lines:
        for line in lines:
            if line.startswith('Revision'):
                return int(line.strip()[-4:],16)
    raise RuntimeError('No revision found.')

def i2cConfig():
    if get_revision() <= 3:
        print("Rev 2 or greater Raspberry Pi required.")

    # Use /dev/mem to gain access to peripheral registers
    mf = os.open("/dev/mem", os.O_RDWR|os.O_SYNC)
    memory = mmap.mmap(mf, BLOCK_SIZE, mmap.MAP_SHARED,
                mmap.PROT_READ|mmap.PROT_WRITE, offset=GPIO_BASE)
    # can close the file after we have mmap

    # each 32 bit register controls the functions of 10 pins, each 3 bit, starting at the LSB
    # 000 = input
    # 100 = alt function 0

    # Read function select registers
    # GPFSEL0 -- GPIO 0,1 I2C0   GPIO 2,3 I2C1
    reg0 = int.from_bytes(memory.read(4), byteorder='little')

    # GPFSEL0 bits --> x[20] SCL1[3] SDA1[3]
    #                        GPIO3   GPIO2   GPIO1   GPIO0
    reg0_mask = 0b00000000000000000000111111111111
    reg0_conf = 0b00000000000000000000100100000000
    if reg0 & reg0_mask != reg0_conf:
        print("reg0 I2C configuration not correct. Updating.")
        reg0 = (reg0 & ~reg0_mask) | reg0_conf
        memory.write(reg0.to_bytes(4, byteorder='little'))

    # GPFSEL2 -- GPIO 28,29 I2C0
    reg2 = int.from_bytes(memory.read(4), byteorder='little')

    # GPFSEL2 bits --> x[2] SCL0[3] SDA0[3] x[24]
    #                       GPIO29  GPIO28
    reg2_mask = 0b00111111000000000000000000000000
    reg2_conf = 0b00100100000000000000000000000000
    if reg2 & reg2_mask != reg2_conf:
        print("reg2 I2C configuration not correct. Updating.")
        reg2 = (reg2 & ~reg2_mask) | reg2_conf
        memory.write(reg2.to_bytes(4, byteorder="little"))

    # Configure pull up resistors for GPIO28 and GPIO29
    def configure_pull_up(pin):
        memory.write(GPIO_PUD_UP.to_bytes(4, byteorder="little"))

        memory.write((1 << pin).to_bytes(4, byteorder="little"))

        memory.write(GPIO_PUD_OFF.to_bytes(4, byteorder="little"))

        memory.write((0 << pin).to_bytes(4, byteorder="little"))


    # No longer need the mmap

if __name__ == '__main__':
Posts: 10
Joined: Mon Jul 07, 2014 10:20 pm
by JensKrueger » Mon Dec 15, 2014 1:47 am
Hi group,

it seems there is a new issue with enabling both I2C busses. After a recent apt-get update / apt-get upgrade / reboot cycle I seem to have lost /dev/i2c-0 . I checked all my configuration an nothing I touched has changed. So I can only assume that /dev/i2c-0 has been disabled, any idea how to re-enable bus 0?

I reverted to an old SD-card image and everything works fine, as soon as I update/upgrade/reboot i2c-0 is gone again. I'm using the Raspberry Pi B Revision 2.0. Unfortunately, I'm not rebooting my raspi very often so the change that removes the bus 0 device may have been introduced a while ago.

Any help is very much appreciated

Posts: 16
Joined: Sat Feb 09, 2013 11:53 pm
by ShiftPlusOne » Mon Dec 15, 2014 2:23 am
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 4349
Joined: Fri Jul 29, 2011 5:36 pm
Location: The unfashionable end of the western spiral arm of the Galaxy
by JensKrueger » Mon Dec 15, 2014 2:36 am
excellent, thank you very much.

Posts: 16
Joined: Sat Feb 09, 2013 11:53 pm
by robotrovsky » Wed Jun 03, 2015 12:14 pm
I made a class in C++ that makes out of any 2 GPIO Pins an I2C Bus via bit-banging. So you can create as many I2C busses as you have PINs. It uses wiringPi for access to the PINs. Maybe this helps someone.

Posts: 1
Joined: Wed Jun 03, 2015 12:06 pm