JulianBrooks
Posts: 35
Joined: Wed Mar 20, 2013 1:08 pm

Re: Enable both I2C Busses

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.

Julian

sukisan
Posts: 10
Joined: Mon Jul 07, 2014 10:20 pm

Re: Enable both I2C Busses

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

BLOCK_SIZE = 4096
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.")
        return

    # 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
    os.close(mf)

    # 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
    memory.seek(GPFSEL0)
    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.seek(GPFSEL0)
        memory.write(reg0.to_bytes(4, byteorder='little'))


    # GPFSEL2 -- GPIO 28,29 I2C0
    memory.seek(GPFSEL2)
    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.seek(GPFSEL2)
        memory.write(reg2.to_bytes(4, byteorder="little"))

    # Configure pull up resistors for GPIO28 and GPIO29
    def configure_pull_up(pin):
        memory.seek(GPPUD)
        memory.write(GPIO_PUD_UP.to_bytes(4, byteorder="little"))
        time.sleep(10e-6)

        memory.seek(GPPUDCLK0)
        memory.write((1 << pin).to_bytes(4, byteorder="little"))
        time.sleep(10e-6)

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

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

    configure_pull_up(28)
    configure_pull_up(29)

    # No longer need the mmap
    memory.close()


if __name__ == '__main__':
    i2cConfig()

JensKrueger
Posts: 16
Joined: Sat Feb 09, 2013 11:53 pm

Re: Enable both I2C Busses

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

Cheers
Jens

ShiftPlusOne
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 4621
Joined: Fri Jul 29, 2011 5:36 pm
Location: The unfashionable end of the western spiral arm of the Galaxy

Re: Enable both I2C Busses

Mon Dec 15, 2014 2:23 am


JensKrueger
Posts: 16
Joined: Sat Feb 09, 2013 11:53 pm

Re: Enable both I2C Busses

Mon Dec 15, 2014 2:36 am

excellent, thank you very much.

Cheers
Jens

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

Re: Enable both I2C Busses

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.

https://github.com/robotrovsky/rpi_i2c_bit_banging

Return to “Interfacing (DSI, CSI, I2C, etc.)”

Who is online

Users browsing this forum: No registered users and 8 guests