Introduction: Raspberry Pi I2C (Python)

In this instructable, I will explain how to use I2C on the Pi, with the examples of the CMPS03 compass module and SRF08 Ultrasonic range, using python. I will explain right through installing the OS, to ensure that the dependencies and everything is installed.

I2C is a communication bus designed by Philips, for chips to communicate with each other on a PCB. It is commonly used, however, for connecting sensors, such as the two examples later in this instructable and port expanders, because you can have multiple devices on the same two pins. 

Step 1: Install R-Pi Image

Go to the Raspberry Pi website, and download the latest Raspbian image and follow the instructions burn it to the SD card.

http://www.raspberrypi.org/downloads

There is an easy setup guide on the wiki, just follow it through.

When you have got it installed, run the config tool, and get everything going nicely. In my case, I am running it headless via SSH, which is enabled as default, at pi@192.168.0.X (check on your router to find the IP).

Step 2: Enable I2C

On the Pi, I2C is disabled by default. The first thing to do, is run the command sudo nano /etc/modprobe.d/raspi-blacklist.conf . In this file, there is a comment, and two lines. Add a hash before the I2C line, to comment it out.

Original:

# blacklist spi and i2c by default (many users don't need them)

blacklist spi-bcm2708
blacklist i2c-bcm2708


Convert to this:

# blacklist spi and i2c by default (many users don't need them)

blacklist spi-bcm2708
#blacklist i2c-bcm2708

Step 3: Enable Kernel I2C Module

The next thing to do is add the I2C module to the kernel. Run the command sudo nano /etc/modules .You should see the following file:

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

snd-bcm2835


This should have the line i2c-devadded to the end.

Final file:

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

snd-bcm2835
i2c-dev

Step 4: Install Necessary Packages

There are a few packages that will need installing to use I2C. The first command to run is sudo apt-get install i2c-tools. If this fails, try running sudo apt-get update and try again, else run crying to your nearest nerd. The other package needed can be installed by running sudo apt-get install python-smbus.

To configure the software, we will add the Pi user to the I2C access group, by running the command sudo adduser pi i2c.
Now run sudo reboot to reboot, and test the new software.

To test the software, run the command i2cdetect -y 0 to see if there is anything connected. On my setup, it returned this output, because there was nothing connected:

0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Step 5: Example 1: CMPS03 Compass Module

We now have everything ready to start using I2C! 

To use the CMPS03 compass module, connect the power to V+ and 0V, from the Pi. I used the 5V line, which they recommend not doing because it might damage your pi, It worked for me, and has caused now damage, but I am not responsible if your's fries. 

Then, connect the SDA and SCL lines to the Pi SDA and SCL, and you are ready to roll. The wiring diagram is shown at http://www.robot-electronics.co.uk/htm/cmps3tech.htm. 

When you have connected it, run the command "i2cdetect -y 0". In my case, this returned: 

       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --


This shows that the module is on address 0x60.  You then need the following python file:

import smbus
import time
bus = smbus.SMBus(0)
address = 0x60

def bearing255():
        bear = bus.read_byte_data(address, 1)
        return bear

def bearing3599():
        bear1 = bus.read_byte_data(address, 2)
        bear2 = bus.read_byte_data(address, 3)
        bear = (bear1 << 8) + bear2
        bear = bear/10.0
        return bear

while True:
        bearing = bearing3599()     #this returns the value to 1 decimal place in degrees. 
        bear255 = bearing255()      #this returns the value as a byte between 0 and 255. 
        print bearing
        print bear255

        time.sleep(1)

This program should be saved as anything, but add ".py" on the end. Then, run the command with sudo python whateveryoucalledit.p and you should get values written to your screen in a long list. 

Step 6: SRF08 Range Sensor

The second example is the SRF08 range sensor, with built in light sensor. 

Wire it in in exactly the same way as before, with power, SDA and SCL connected to the Pi. I found that this sensor would not work off 3.3V, but again, I bear no responsibility for you putting 5V through your Pi pins. You can even leave the compass module in as well, because I2C can handle multiple devices on one line. The wiring diagram can be seen here: http://www.robot-electronics.co.uk/htm/srf08tech.shtml . 

Run i2cdetect -y 0  

0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --


Note that I have left the compass module connected. 

You will then need the following python file. It is more complex, becuase you have to write a command to the sensor to get it to begin reading. 

import smbus
import time
bus = smbus.SMBus(0)
address = 0x70

#SRF08 REQUIRES 5V

def write(value):
        bus.write_byte_data(address, 0, value)
        return -1

def lightlevel():
        light = bus.read_byte_data(address, 1)
        return light

def range():
        range1 = bus.read_byte_data(address, 2)
        range2 = bus.read_byte_data(address, 3)
        range3 = (range1 << 8) + range2

        return range3

while True:
        write(0x51)
        time.sleep(0.7)
        lightlvl = lightlevel()
        rng = range()
        print lightlvl
        print rng



This will print the light level on the built in light sensor and the current range, in cm. 

Step 7: Conclusion

I hope you have found this instructable useful, as it should provide you with the code you need to get I2C working nicely. I spent a long time trying to fathom the Adafruit I2C Library out, before realising that these simple commands are all that I need. The basic read and write commands are functions in my provided code, so that should see you through. 

Comments

author
LorenzoL25 made it! (author)2016-08-17

smbus is not available in Python 3. Does anybody know an alternative?

author
Tallis1 made it! (author)Tallis12016-12-01

Hi Lorenzo, this may be far too late, but it may still be helpful for persons having the same issue as you. I followed the instructions on this link and got smbus working on python 3. http://jtecheng.com/?p=959#comment-925

author
LorenzoL25 made it! (author)LorenzoL252016-12-02

Hi Tallis,

I appreciate your help, but I am not working at the moment with RPi.

Thank you

author
LuisanaP made it! (author)2016-06-23

Hii your post was very helpfull but i have a big question how can i do if i have a pic? im starting from 0 how to work with the raspberry and i want to conect with a pic 16f886 slave.. and the rp as a master but when i do the conection dosent read the pic :( please help!

author
CharlieF31 made it! (author)CharlieF312016-07-05

Do you have access to an oscilloscope? I've always had a lot more luck understanding what's going on when I can see what they're sending back and fourth. I have some experience with both PICs and the Raspberry Pi, but I've noticed that the PIC freaks out a bit more readily than a Raspberry Pi with i2c. Make sure that the speeds are set up accordingly (although this shouldn't be a problem with i2c). Another thing is, you could just transmit things over GPIO pins on your own. What are you trying to do? i2c may not be the only thing that can accomplish the goal you want.

author
LuisanaP made it! (author)2016-06-23

Hii your post was very helpfull but i have a big question how can i do if i have a pic? im starting from 0 how to work with the raspberry and i want to conect with a pic 16f886 slave.. and the rp as a master but when i do the conection dosent read the pic :( please help!

author
ricoow6 made it! (author)2016-05-23

Now here is a question from a newb who wants to get into I2C on the Pi.

The provided page (http://www.robot-electronics.co.uk/htm/srf08tech.html) says that this comes with default address 0xE0 and it is modifiable to 0xFE with increments of 0x02. But the pi only supports up to 0x78. How does that work?

author
ricoow6 made it! (author)ricoow62016-05-23

(Step 6 sensor)

author
M0J01 made it! (author)2016-04-11

Oh man, Thank you so much for this instructable! Your tutorial was short and to the point, while remaining sufficient for my applications.

Thank you so much!

author
paulbrandt made it! (author)2016-02-08

I am just learning i2c, thanks a lot for your info, but for the price of the i2c rangefinders I think I will stick with HC-SR04 Ultrasound Wave Detector Range Ultrasonic Sensor Distance Module for just over $1 each and use i2c for the i2c sensors.

author
adolinus made it! (author)2015-10-07

thanks, very usefull. just wonder if i'm able to communicate with a pcf8574 or mcp23017 i/o expander now.

author
edrandall made it! (author)2014-12-16

Where do I find the SDA and SCL lines on my Pi

author
seempie made it! (author)seempie2015-07-15

you can find them on pin 3 and 5, 3 is the SDA and the SCL is the 5th pin

author
bohdan-anderson made it! (author)2014-01-15

For the 512mb of ram USE

i2cdetect -y 1

instead of the other.

author
djuricic made it! (author)djuricic2014-03-20

Thank you! I've been trouble shooting for almost an hour and was about to give up when i saw your post. I thought I had killed my BMP180 while soldering it or that it was broke for some other reason. =)

author
bohdan-anderson made it! (author)bohdan-anderson2015-03-03

Awesome!

author
Technoshaman made it! (author)Technoshaman2015-03-03

Same goes for the Pi 2, which is also a B+.

author
ElegantAndrogyne made it! (author)2015-01-28

A good ible - another great example would be connecting MCP23008 or MCP23017 chips and controlling them either via python-smbus (by sending bytes to registers) or via wiringpi2 (high level driver providing setup routines and an abstraction layer).

author
bacoms made it! (author)2015-01-15

Please forgive a complete noob commenting here but, as I read more and more
on I2C, the noobier I'm getting.

What's got me confused is how to connect, for example, several SRF08 Range Sensors.
Presumably they all have the same address (0x70) so confusion reigns, right? I
suspect you can only connect devices that have different addresses which, if
I'm right, severely limits the usefulness of I2C.

Am I right and is there a cost-effective way around this limitation?

P.S. I'm relatively new to all this hardware stuff. I'm retired now but was a mainframe programmer who has since discovered Python and loves it.

author
paulhill13 made it! (author)paulhill132015-01-18

You can configure the address that the SRF08 uses, there a 16 possibles,
meaning you could use up to 16 SRF08's on one bus. Scroll down on this
page to see how http://www.robot-electronics.co.uk/htm/srf08tech.shtml

author
laffoleyb made it! (author)2014-12-04

There is a very simplai I2C level shifter that will save your port.

see for example http://playground.arduino.cc/Main/I2CBi-directionalLevelShifter, you will probably have the pull up resistors on the boards anyway so you probaly just need the two FETs.

author
pdfsman made it! (author)2014-10-26

If I use another sensor for example IMU breakout-LSM9DSO, What is the change in the python file?

author
Gorgoth made it! (author)2014-09-29

Great bit of info got my almost totally unrelated project working as you had all the important stuff

author
rkhedkar made it! (author)2014-06-09

very easy explanation... I easily get confused with Rpi tutorials on web but this one is an exception....

thank you sir... @

AntMan232

author
sakko303 made it! (author)2014-05-23

as a lurker who is considering a pi for all sorts of nefarious purposes, I find this very helpful!

author
kkjensen made it! (author)2013-05-12

What purpose does the write(0x51) provide? Is it just activating the module on the i2c bus so values can be read from it?

author
Nargun made it! (author)Nargun2014-04-26

0x51 is the write register to command data returned in centimeter vales. 0x50 commands values in inches and 0x52 commands values in microseconds (flight time.

See http://spaces.atmel.com/gf/download/frsrelease/228/1344/SRF08%20Ultra%20sonic%20range%20finder.pdf

author
moshtaghioun made it! (author)2014-02-11

TNX for the great instruction but 1 question

i didn't understand if the 5V i2c device has damaged your device or not ,

author
trollies made it! (author)2013-03-31

When you do:

bear2 = bus.read_byte_data(address, 3)
bear = (bear1 << 8) + bear2
bear = bear/10.0
return bear....
why do you divide by 10? I am assuming you have a signed 15 bit number and you are getting rid of the last 0? Why not use >> 1?

author
utest_megha500 made it! (author)2013-02-17


author
john1221 made it! (author)2012-11-23

I could only run i2cdetect with the command "sudo i2cdetect -y 0"
Otherwise it would not run..

author
dgateley made it! (author)2012-10-26

Hey, AntMan. Should you be so inclined, a similar article on how to get i2s (much different than i2c functionally) working on Raspberry Pi would be enormously appreciated. I'd like to attach a Wolfson audio codec but getting up to the configuration point where I could basically do that and begin talking to it is daunting to say the least.

author
vynylpooh made it! (author)2012-10-26

Thank You!

author
dcastor made it! (author)2012-10-25

To make this 'bile better, you might explain in step 1 what I2C is for.

author
AntMan232 made it! (author)AntMan2322012-10-26

Ah, whoops, thanks!

author
chrimel made it! (author)2012-10-25

Would the external GPS cable for a generic Android tablet or an old XM radio possibly work? I have a couple of those that I might be able to part with if they could be made to work.

author
DatasheetDungarees made it! (author)2012-10-25

As a supplement, I have a similar write-up that I buried perhaps a little too deep on the eLinux wiki:

http://elinux.org/RPi_Tutorial_EGHS:Communicating_With_Other_Micro-controllers

Includes: the official (probably overkill) way of interfacing 3.3V and 5V I2C applications, software for a few languages, and kernel considerations.

Range sensor sounds fun, I'll give that a try!

author
1-big-dog made it! (author)2012-10-25

Thanks for a very straight forward step by step explanation!

author
sparten11 made it! (author)2012-10-25

all we need now is gps and radar. and viola we are ai nav.. kewl. let me know when you get GPS up and running..

author
AntMan232 made it! (author)AntMan2322012-10-25

If you give me a GPS module, I will gladly oblige. :D If only I had the money...

author
syseng made it! (author)2012-10-25

Thanks for sharing this,it means i could use my temperature sensors

author
AntMan232 made it! (author)2012-10-24

Thanks guys, it's nice to be able to help! It geniunely took me about a week to realise that the Adafruit code was overkill, and that it only took one line to read over i2c...

author
antares72 made it! (author)2012-10-24

Nice and clean examples! You have a new follower.

author
randofo made it! (author)2012-10-23

Thanks for sharing this. This will surely come in handy.