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

Enable both I2C Busses

Sat Feb 09, 2013 11:59 pm

Hi all,

I'm trying to connect a number of I2C devices to the RPi but some have the same (fixed) I2C address. My understanding is that the RPi has two I2C busses but only the second (for the latest RPi revision) is exposed via the GPIO pins. Is there any way to access both I2C busses (e.g. soldering some wires to the board to connect to the other bus)?

Cheers
Jens

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: Enable both I2C Busses

Sun Feb 10, 2013 1:18 am

I2C bus 0 is available as an alternate function of GPIO 28 and GPIO 29 pins available on the P5 connector for the Rev 2 Raspberry Pi boards. I2C bus 1 is available on the P1 connector for Rev 2 Raspberry Pi boards. By default no connector is installed for P5 -- you can install your own 8 pin header.

Enjoy!
Bill

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

Re: Enable both I2C Busses

Sun Feb 10, 2013 1:35 am

thanks a lot Bill,

looks I'm up to some delicate soldering on my RPi :-) I'll post results when I get it to work (or when I fried the PCB).

Cheers
Jens

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: Enable both I2C Busses

Sun Feb 10, 2013 1:44 am

Just be aware that it was intended the P5 connection would be on the bottom so as not to interfere with P1. Your soldering will be on the top in this case. With the 2.54 mm spacing for the header, this is "easy" soldering, so you should not be overly concerned if you have reasonable skill with a low wattage iron.

Enjoy!
Bill

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Tue Feb 12, 2013 10:50 pm

Hi

I've just confirmed that I too need to access both i2c busses.

I have sample code which will detect my device on i2c-1 on P1.

I've tried attaching my device to i2c-0 on P5.
I believe that the pins to use are GPIO28 (SDA) and GPIO29 (SCL).

I've modified my sample code to use i2c-0 but it doen't work.
Running i2cdetect -y 0 shows no devices.

I've tried all permutations of the GPIO pins on P5 just in case I had misunderstood, but no luck.

What am I missing here? is there somewhere where I need to do something specific for each i2c bus that I've forgotten that I did for i2c-1?

Hope someone can help me out

srod
Posts: 6
Joined: Wed Feb 13, 2013 12:15 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 12:50 pm

Ragu3l wrote:Hi

I've just confirmed that I too need to access both i2c busses.

I have sample code which will detect my device on i2c-1 on P1.

I've tried attaching my device to i2c-0 on P5.
I believe that the pins to use are GPIO28 (SDA) and GPIO29 (SCL).

I've modified my sample code to use i2c-0 but it doen't work.
Running i2cdetect -y 0 shows no devices.

I've tried all permutations of the GPIO pins on P5 just in case I had misunderstood, but no luck.

What am I missing here? is there somewhere where I need to do something specific for each i2c bus that I've forgotten that I did for i2c-1?

Hope someone can help me out
#

I'm having the same problem.

Device and code configured connected to SDA1/SCL1 on P1, works fine (and i2cdetect -y 1 shows device).

Same device and code, reconfigured and connected to SDA0/SCL0 on P5, doesn't work (as above post i2cdetect -y 0 shows nothing). I've also probed the pins with a 'scope, nothing happening.

Do I need to do anything to enable I2C-0? Have I missed anything?

I'm using Rev2 board.
also /dev shows i2c-0 and i2c-1

srod
Posts: 6
Joined: Wed Feb 13, 2013 12:15 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 2:16 pm

Hallelujah... I have been able to access I2C-0!

But not on P5... on S5.

From this page here:
http://www.raspberrypi.org/archives/1929

SCL0 [BCM2835/GPIO1] routed to S5 pin 13
SDA0 [BCM2835/GPIO0] routed to S5 pin 14
SCL1 [BCM2835/GPIO3] routed to P1 pin 5
SDA1 [BCM2835/GPIO2] routed to P1 pin 3

Confirmed by the schematic, centre of sheet 4:
http://www.raspberrypi.org/wp-content/u ... .2_027.pdf

I soldered 2 small flying leads onto pins 13/14 of S5, connected to my device and i2cdetect -y 0 works first time.

It would be much better to be able to use them on connector P5 though, so any information on how to set this up would still be great! Something to do with setting up pins with alternate functions...??

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 3:04 pm

I arrived at the same point late last night. Probing S5 with a scope.

I agree that it must be related to setting the alternate function for GPIO28 and 29 to get i2c on P5.
It might be necessary to disable the alternate function for GPIO0 and 1, making it impossible to use whatever connects to S5, think it's the camera. For me this is not a problem since I don't need it.

So, how do we control alternste functions for GPIO pins?
Preferably using Python.

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 5:19 pm

You can look at my Python SPI reset code for the method. It is posted in the Nokia SPI display thread. If no one steps up, I'll post the Python code for the I2C configuration this evening when I get home. It should be possible to maintain use of both I2C buses, but you will lose the I2C bus on the S5 connector.

Enjoy!
Bill

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 5:28 pm

Thanks Bill
I'll have a look and see what I can find out in your code.

If I accomplish anything I'll be posting it within the next 6 hours, if I can;t figure it out your assistance will be greatly appreciated

Ragu3l

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 7:58 pm

Here is my attempt to enable both I2C interfaces. It appears to work on my Raspberry Pi, but I do not have any I2C peripherals to test.

i2c_p5.py:

Code: Select all

#!/usr/bin/env python
#
# W. Greathouse 13-Feb-2013
# 
#   Enable I2C on P1 and P5 (Rev 2 boards only)
#

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

BCM2708_PERI_BASE=0x20000000
GPIO_BASE=(BCM2708_PERI_BASE + 0x00200000)
BLOCK_SIZE=4096

def _strto32bit_(str):
    return ((ord(str[3])<<24) + (ord(str[2])<<16) + (ord(str[1])<<8) + ord(str[0]))

def _32bittostr_(val):
    return chr(val&0xff) + chr((val>>8)&0xff) + chr((val>>16)&0xff) + chr((val>>24)&0xff)

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)
    m = 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)
    # Read function select registers
    # GPFSEL0 -- GPIO 0,1 I2C0   GPIO 2,3 I2C1
    m.seek(0)
    reg0=_strto32bit_(m.read(4))
    # GPFSEL2 -- GPIO 28,29 I2C0
    m.seek(8)
    reg2=_strto32bit_(m.read(4))
    # print bin(reg0)[2:].zfill(32)[2:]
    # print bin(reg2)[2:].zfill(32)[2:]

    # GPFSEL0 bits --> x[26] SCL0[3] SDA0[3]
    #                        GPIO    GPIO
    m0 = 0b00000000000000000000111111111111 
    s0 = 0b00000000000000000000100100000000
    b0 = reg0 & m0
    if b0 <> s0:
        print "reg0 I2C configuration not correct. Updating."
        reg0 = (reg0 & ~m0) | s0
        m.seek(0)
        m.write(_32bittostr_(reg0))

    # GPFSEL2 bits --> x[2] SCL0[3] SDA0[3] x[24]
    m2 = 0b00111111000000000000000000000000 
    s2 = 0b00100100000000000000000000000000
    b2 = reg2 & m2
    if b2 <> s2:
        print "reg2 I2C configuration not correct. Updating."
        reg2 = (reg2 & ~m2) | s2
        m.seek(8)
        m.write(_32bittostr_(reg2))

    # No longer need the mmap
    m.close()


if __name__ == '__main__':
    i2cConfig()
Enjoy!
Bill

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 11:01 pm

Hi Bill

Thank you.
I was slowly getting there but ran into some, I hope, unrelated problems with my wifi.
Which meant finding a keyboard and monitor out from storage and getting everything set up again.

I'm a linux noob so this took quite a while to get everything back in working order.

I've tried out your function and it seems to work, at least somewhat.

I often get errors like:

Traceback (most recent call last):
File "i2c_smartbattery_functions.py", line 115, in <module>
print 'Current: ', get_Current_mA(), ' mA'
File "i2c_smartbattery_functions.py", line 81, in get_Current_mA
return bus.read_word_data(address,SB_CURRENT)
IOError: [Errno 5] Input/output error

It also occurs in other places or sometimes not at all, so the above is just an example.

I never see this on i2c-1, but I have not yet looked further into it.
I'm thinking that other stuff might be happening on i2c-0 or it could be speed related...

I'll post any findings

Ragu3l

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 11:22 pm

The only thing that comes to mind is pull-up resistors on the SDA0/SCLK0 lines. Since the P5 lines are not designated as I2C by default, you need to add your own resistors.

Enjoy!
Bill

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Wed Feb 13, 2013 11:26 pm

Hi Bill

Of course. You're right.

I was looking at the schematic and concluded that there was pull-ups, but that was on the way to S5, which I don't need now. Thank you

Will try again once I get some pull-ups added.

Tremendous help

srod
Posts: 6
Joined: Wed Feb 13, 2013 12:15 pm

Re: Enable both I2C Busses

Thu Feb 14, 2013 2:56 pm

Bill - thanks very much for posting that code, it does exactly what I want it do and worked first time!

I can now move on to the next stage of my project... :D

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

Re: Enable both I2C Busses

Wed Feb 20, 2013 8:40 am

This is too cool. Just when I finally found the time to solder a connector to P5 and ran into problems with the secondary I2C Bus my question (code required to configure the second bus) was already answered here. Awesome forum, answering my questions before I even ask them :D.

Maybe I can also add some knowledge to the community: I did not like the idea of having the P5 connector on the bottom of the board so I went ahead an soldered a 4x2 2,54 mm pin connector to the PCB on the top side, and I do not have any problems. It fits in just fine and I connected female connectors (such as this http://cdn.pollin.de/article/small/K451351.JPG) to the primary and the secondary I2C bus without any trouble. Here are a few images of the assembled RPi (http://www.fotocommunity.de/pc/pc/mypic ... y/30283820, http://www.fotocommunity.de/pc/pc/cat/1 ... y/30283836)

Cheers
Jens

P.S.: My Project is all C++ and I preferred having the code to enable the second bus in C as well so I ported it. In essence I could copy the python script into a CPP file and change the syntax only very slightly. But here it is for reference:

Code: Select all

#include <unistd.h>     // open, close
#include <fcntl.h>      // O_RDWR, O_SYNC
#include <sys/mman.h>   // mmap

void I2CBus::initSecondaryI2CBus() const {
  int fileHandle = 0;

  if ((fileHandle = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
    throw EAccessDenied("Failed to open /dev/mem, try checking permissions.");
  }

  void* map = mmap(
    0,
    BLOCK_SIZE,
    PROT_READ|PROT_WRITE,
    MAP_SHARED,
    fileHandle,
    GPIO_BASE
  );

  if (map == MAP_FAILED) {
    throw EAccessDenied("Failed to mem-map /dev/mem.");
  }

  volatile unsigned int *addr = (volatile unsigned int *)map;

  int reg0 = addr[0];
  int m0 = 0b00000000000000000000111111111111;
  int s0 = 0b00000000000000000000100100000000;
  int b0 = reg0 & m0;
  if (b0 != s0) {
     //  need to change register 0
     addr[0] = (reg0 & ~m0) | s0;
   } else {
     // register 0 is ok
   }

   int reg2 = addr[2];
   int m2 = 0b00111111000000000000000000000000;
   int s2 = 0b00100100000000000000000000000000;
   int b2 = reg2 & m2;
   if (b2 != s2) {
     // need to change register 2
     addr[2] = (reg2 & ~m2) | s2;
   } else {
     // register 2 is ok
   }

   munmap(map, BLOCK_SIZE);
   close(fileHandle);
}

User avatar
rew
Posts: 408
Joined: Fri Aug 26, 2011 3:25 pm

Re: Enable both I2C Busses

Sat Feb 23, 2013 9:21 am

You can grab my "bw_rpi_tools" programs from github.

There is a gpio_set program in there that will allow you to select alternate functions for the gpio pins.
Check out our raspberry pi addons: http://www.bitwizard.nl/shop/

StaticDet5
Posts: 21
Joined: Sun Nov 25, 2012 5:11 am

Re: Enable both I2C Busses

Sat Feb 23, 2013 2:22 pm

I'm trying to get both I2C busses to work. I've soldered on a header onto P5. I need to photograph the board, as my technique leaves the original GPIO header relatively unobscured.

Has anyone had any luck getting the second I2C bus to work?

I'm using a Raspberry Pi Version B, Rev 2. The i2cdetect -y 1 is showing me the devices on the "1" bus. The i2cdetect -y 0 is not showing any devices on the "0" bus.

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Sat Feb 23, 2013 2:35 pm

I've not tried the C code above so I have no personal experience with thst' but bgreat's python code above works. So if you're working with python it should be straight forward.
If you're working with C then I suggest giving the C code a try.
Remember to add your own pull up resistors to i2c0 on p5.

Raguel

StaticDet5
Posts: 21
Joined: Sun Nov 25, 2012 5:11 am

Re: Enable both I2C Busses

Sat Feb 23, 2013 3:40 pm

I'm not completely sure why this works, or how it works, but it definitely works. I've got my second I2C bus plugged in to P5, and the Python code works. I just had to run it once for the i2cdetect function to work correctly.


I'm going to post links to this thread from the pages where I'm hosting my project. Hopefully you'll get the word out. I got an email last night that the second I2C bus was inaccessible without wiring directly to the S5 connector.

Thanks tons!

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Sat Feb 23, 2013 4:13 pm

The code changes the function of gpio pins. In this case reroutes i2c0 from pins connected to s5 to pins connected to p5.
This only works for boards with p5, obviously.

It also means that this prevents s5 from working as designed.

If the devices you wish to connect have different addresses or if the adresses can be changed so all devices have unique addresses then I'd recommend connecting them all to i2c1 on p5 and preserve s5's functionality.

The data sheet section about gpio pins and alternate functions is key in understanding why this works

StaticDet5
Posts: 21
Joined: Sun Nov 25, 2012 5:11 am

Re: Enable both I2C Busses

Sat Feb 23, 2013 4:29 pm

Does this change need to be run every time at startup?
Can the change be undone?
Can it be undone without a reboot? Could you utilize the I2C bus, and then use code to switch back to the camera module?

I'm interested in the camera module, but really interested in running identical sensor systems off of the same board.

Again, thanks a bunch.

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Enable both I2C Busses

Sat Feb 23, 2013 4:49 pm

I believe the code needs to be run after a reboot to change the pin finctions.

This of course means that it can be undone by a reboot.

The code can be modified to include a function that'll revert the change back so camera can be used. At least I can't think of a reason why this should not work. But I know nothing about how the camera, drivers etc work fir that side if things.

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

Re: Enable both I2C Busses

Sat Feb 23, 2013 9:08 pm

yes, you are correct. The code needs to be re-run after a reboot. That's why I ported it to C so I can run it inside my program. If you want to undo the change without rebooting the RPi just flip the bits back that the code changes, for instance by storing the values of the registers 0 and 2 before changing them.

Cheers
Jens

StaticDet5
Posts: 21
Joined: Sun Nov 25, 2012 5:11 am

Re: Enable both I2C Busses

Fri Mar 01, 2013 12:12 pm

I just got a bizarre result.
I'm working on running a second TSL2561 Luminosity sensor off of my Pi. The first one is on bus 1 (RasbPi Model B, Rev 2). It seems to work, but erratically. The person I'm working with over on Adafruit is helping me run down the problem.

I just wired up the second sensor, on bus 0. It's the only thing that I have wired on bus 0. I ran the i2cdetect code and got an I2C table that is completely filled except for 11 addresses. A similar check on bus 1 yields the expected results (I have half a dozen devices on that bus).

What gives? Anyone have similar experiences?

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

Who is online

Users browsing this forum: No registered users and 26 guests