Introduction

The Raspberry Pi is an amazing piece of hardware. It’s an incredibly inexpensive platform for running software, and its expansion header is designed to help you link up your Pi to the real world.

In this series of tutorials we’ll explore techniques for doing just that. People often describe this as Physical Computing. Since we’ll be developing in Python, we’ve called the series Physical Python.

The Pi’s expansion header lets you connect your Pi to other devices in several different ways, all of which are supported by our Python API. This first tutorial covers an approach known as I2C, pronounced I squared C. We love I2C because it uses just two signal wires to connect lots of useful things to a Pi at the same time.

We’ll cover I2C before looking at the Pi’s GPIO pins or its SPI interface. There’s a lot of interest in I2C on the Pi at the moment, but it’s hard to find easily accessible introductory information. GPIO access is more widely covered, and SPI is not yet supported by the official Raspbian image.

Overview

There’s quite a bit you need to cover before you can write, run, and test your first Physical Python program using I2C.

  1. You’ll need to prepare your Pi and get familiar with the useful i2cdetect utility. That’s the focus of this tutorial.
  2. You’ll need to make sure you have the necessary hardware. Part 2 in this series introduces the hardware that you need, and explains where you can get it.
  3. Part 3 in the series shows you how to connect up the Pi’s expansion header to an MCP23008 port expander, ready for you to test your software.
  4. You’ll need to install our I2C library, and run (and maybe modify) a simple example. That’s the subject of part 4.
  5. Part 5 looks at a simple, practical application; you’ll connect a numeric keypad to the Pi and write some code to respond to pressing its keys.

The Software Environment

The Pi is still a new device, and its ecosystem is evolving rapidly. We’ll be using the Raspbian “Wheezy” distribution which you can get from the official Raspberry Pi downloads page.

The code we’ll be writing relies on the Quick2Wire Python API library. We’ll show you how to set that up in the third tutorial.

Before you install our library, you’ll need to make a couple of simple configuration changes and install some extra software. That’s what this tutorial covers.

Configuring your environment.

Once you’ve installed the Raspbian “Wheezy” distribution and booted your Pi, you’ll need to edit a couple of configuration files.

Both of them are system files which you will have to edit as the super-user by using the sudo command.

The first file normally tells Linux not to load a couple of drivers. Most users don’t need them, but we do, so we’ll edit the file.

In a terminal window, type

sudo nano /etc/modprobe.d/raspi-blacklist.conf

This will start nano, a simple text editor, and use it to edit the first configuration file. You should see an editing window like this:

Editing the blacklist
Editing raspi-blacklist.conf

Move the cursor onto each line that starts ‘blacklist’  and enter a # at the start of each line.

You might also want to change the top line to explain what you’ve done. The window should now look like this:

Contents of edited raspi-blacklist.conf
Edited blacklist

Now

  1. Type Control-O to save (output) the file,
  2. press Enter to confirm the name of the file to save, and
  3. type Control-X to exit nano.

Next, you need to create a configuration file that will tell Linux about another driver module which you need in order to use I2C.

Once again, since it’s a system file, you will need to edit it using the sudo command.

In your command window, type

sudo nano /etc/modules

You should see an edit screen like this:

content of /etc/modules
/etc/modules before you edit it

Move the cursor to the bottom of the file and add a line that reads i2c-dev. The window should now look like this:

/etc/modules file after editing
The contents of the /etc/modules file after i2c-dev has been added.

Once again,

  1. Type Control-O to save (output) the file,
  2. press Enter to confirm the name of the file to save, and
  3. type Control-X to exit nano.

Checking the configuration

Since you haven’t rebooted yet, the files you changed will not yet had any effect.

To see what will change when you do reboot, type the following in the command window:

ls -la /dev/i2c-0

You should see an error message:

ls: cannot access /dev/i2c-0: No such file or directory

You’ve asked Linux to look for the i2c-0 device. Since your changes haven’t taken effect yet, Linux won’t find it, and the ls command will display an error message.

Now reboot the Pi by typing

sudo reboot

in the command window.

Once the Pi has rebooted, log in, open a command window if necessary, and type

ls -la /dev/i2c-0

This time you should see a line that reads

crw------T 1 root root 89, 0 Aug 7 14:09 /dev/i2c-0

Congratulations! You now have an i2c device driver installed on your Pi.

There’s one more job to do before we’re finished with this stage: you’ll install a really useful piece of software called i2c-tools. This will allow you to list all the I2C devices that are attached to our Pi. Of course, right now there aren’t any, but just getting this software to run will provide further confirmation that you’ve got everything set up correctly.

I2C tools

The open-source i2c-tools package will help you check that you’ve correctly connected an i2c chip to your Pi.

You’ll need to install the package using the sudo command. Before you install the package, make sure your list of available software is up-to-date by running

sudo apt-get update

and then run

sudo apt-get install i2c-tools

You should see apt installing the package.

You will need to use the i2cdetect command as root, the super-user. You need to be super-user because by default only the super-user can access i2c devices. The -y  parameter after i2cdetect suppresses a warning that i2cdetect is about to mess with your bus. We know that, and are happy for it to do its work, so we can safely suppress the warning.

The 0 tells i2cdetect to test bus number 0. The Pi has two i2C buses, 0 and 1, but bus 1 is not connected to the Pi’s expansion header.

Now run

sudo i2cdetect -y 0
Output from i2cdetect with nothing on the I2C bus

Output from i2cdetect with nothing on the I2C bus

You should see a table displayed, which shows all the devices connected to the Pi’s i2c0 bus. Since there aren’t any yet, the entries in the table will all be empty, displayed as double dashes.

At this point, it’s a good idea to restart your Pi to make sure that the i2c ports have the correct permissions.

sudo reboot

When you run this command again at the end of the third part of this series, you’ll see the MCP23008 showing up on the bus at address 20.

Coming next – the hardware you’ll need

In the next part of the tutorial series we’ll introduce the hardware that you’ll need and give you some suggestions about where to get it.

21 Comments

  1. Great entry level article thank you

    Reply

    • Great entry level article thank you: Where’s the next instalments?

      Reply

      • Coming soon, I hope.

        When we planned the series, several vendors offered all the parts needed for our example, including the MCP23008 chip. Before we published the second part pretty well everyone (including the vendors) shifted their focus to the more powerful MCP23017.

        This change meant that we’d have had to re-shoot all the photos, redo all the diagrams and rewrite the later instalments, and we couldn’t find time to do that. Meanwhile our own MCP23017-based Port Expander board moved closer to production.

        Once the board is available for purchase later this month we will publish the remaining articles using the board as a target.

        Reply

  2. Thanks for the great work. I have the GPIO module working well.

    I am trying to interface with a DS1631 I2C temperature sensor and am having problems. When I run i2cdetect 0 I can see my device connected. Then when I run my program I get the following error:

    Traceback (most recent call last):
      File "DS1631_2.py", line 8, in 
        bus.transaction(i2c.writing_bytes(0x48, 0x00, 0x51))
      File "/usr/local/lib/python3.2/dist-packages/quick2wire/i2c.py", line 72, in transaction
        ioctl(self.fd, I2C_RDWR, addressof(ioctl_arg))
    IOError: [Errno 5] Input/output error

    This is what my program looks like that interfaces to a DS1631 temperature sensor.

    #!/usr/bin/env python3
    import quick2wire.i2c as i2c
    import time
    address = 0x48
    with i2c.I2CMaster() as bus:
            bus.transaction(i2c.writing_bytes(0x48, 0x00, 0x51))
            bus.transaction(i2c.writing_bytes(0x48, 0x00, 0xAA))
            while True:
                    high, low = bus.transaction(i2c.writing_bytes(address, 0x01),
                    i2c.reading(address, 2))[0]
                    print ('High %r. Low %r') % (high, low)
                    time.sleep(1)

    Is there something that I am not doing correctly?

    Any help would be greatly appreciated.

    Thanks.

    Reply

    • Greg,

      Glad to hear you have GPIO working.

      Looking at your i2c sample, it looks like you are explicitly sending the RW bit of the control byte. Have you tried removing that, so

      i2c.writing_bytes(0x48, 0x00, 0x51)
      

      would become

      i2c.writing_bytes(0x48,0x51)
      

      Sorry for the delayed reply – please let us know how your project is coming along!

      Reply

  3. Milan Reiniger

    Hello,

    I connected camera module OV7670 to I2C interface. But when I try i2cdetect show me this table:

    root@raspberrypi:~# i2cdetect -y 0
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
    10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
    20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
    30: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
    40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
    50: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
    60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
    70: 70 71 72 73 74 75 76 77
    root@raspberrypi:~#

    Please – where is problem?

    Reply

    • It looks as if something (maybe the camera) is responding to every i2c address. I don’t know anything about the camera, so there is not much I can do to help. Perhaps someone who knows the camera can help

      Reply

    • [offtopic] Sorry for the offtopic question, but Milan Reiniger, did you solve this problem? I’m with the same problem here. My camera is responding to every i2c address too.

      Reply

    • I have this now too, but permanently. In attempting to connect an ATtiny85 to my over i2C RasPi I think I broke something. It worked great at 3v3 but when I moved to 5v with SDA and SCL pulled up to ~3v3 by voltage dividing the 5v source (not 100% sure if this is the right way to go about avoiding level shifting) I saw noise in the output of “watch -n 1 i2cdetect -y 0″ which finally settled on:

      0 1 2 3 4 5 6 7 8 9 a b c d e f
      00: 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
      10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
      20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
      30: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
      40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
      50: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
      60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
      70: 70 71 72 73 74 75 76 77

      which persists even after reboots. Now my RasPi I2C no longer functions.

      So, let this be a warning. It’s probably very wise to do proper level shifting if you are using 5v slaves with the RasPi. Is that camera module 5v? Does i2cdetect show all addresses even when you’ve disconnected it?

      Reply

      • If you are attaching a Pi to an I2C device that really needs 5v pull-ups to make it function, you’d have to use a level shifter. I’d recommend something like the Sparkfun logic level converter https://www.sparkfun.com/products/8745

        This should not be the case with an ATTiny. I’d expect that to work fine without external pull-ups if you are connecting its I2C connections directly to a Pi, for the reasons I gave here http://quick2wire.com/2013/03/pi-and-arduino-linked-via-i2c/

        It sounds as if you may have raised the voltage on the I2C lines too high with the voltage divided, which is not a good way to do the level shift.

        Reply

        • Andrew Scheller

          Hmmm? Does that mean there *is* a possibility he’s damaged his Pi’s I2C port? I thought one of the advantages of the Quick2Wire boards was that they’re supposed to protect your Pi from unsafe voltages?

          Reply

          • The interface board provides some protection to the 8 GPIO pins and the serial communications pins, but not the I2C or SPI pins, which are only accessible through our 6 and 8 way connectors.

            We don’t expect people to connect 5v devices to the I2C or SPI connectors, which are intended to link the Pi to the boards we make. We’ve assumed that anyone who makes their own connections to our I2C and SPI connectors knows what they are doing.

            It’s not clear to me that the camera users are using our boards at all.

          • Andrew Scheller

            Thanks for the reply Romilly (I’ve also sent you an email regarding the analogue board, if you’ve not already seen it).

            In that case would it be worth you producing simple “5V breakout boards” that connected to your I2C and SPI connectors, and included the necessary voltage-level conversion circuitry?

            Unfortunately the pinout of your I2C and SPI connectors can still only be found by searching through the archives of the blog.

          • I did damage my Pi’s I2C port but I’m not using the Quick2Wire board. I just jumped in here because this popped up while searching.

            Does anyone know whether it is possible to reassign the I2C bus (SDA/SCL) to other GPIO pins on the RasPi?

          • Andrew Scheller

            “Does anyone know whether it is possible to reassign the I2C bus (SDA/SCL) to other GPIO pins on the RasPi?”

            I haven’t needed to do so myself, but the info you need can be found at:
            http://elinux.org/RPi_Low-level_peripherals
            http://elinux.org/RPi_BCM2835_GPIOs

            If you’ve got a Rev.2 Pi board (with the mounting holes) you could just use the I2C interface on P5
            http://elinux.org/Rpi_Low-level_peripherals#P5_header

  4. Charlie Wakely

    Great article!

    I love the IDEA of the Quick2Wire boards, but I am a TOTAL noob – never programmed before, never run Linux before, I have no idea what an API is etc. etc.,

    So this tutorial looks as if it is going to be brilliant…… except…..

    you’ve been promising part 2 for ages! And I can’t make head or tail of the rest of the site – a flow chart of what libraries control what from GPIO pin to the end of the expansion board would help – but I really, really need these tutorials – I have an assembled beta board and no way to play with it! Please help!

    Reply

  5. Hai

    I have a PI and the board, the GPIO is workin, I can control the led and read the button

    I have installed Python 3 and followd Physical Python Part 1

    When I start run a python program

    From quick2wire.gpio import pins, In, Out

    I recieve the message No module named quick2wire.gpio

    I think I mised a document in the installation process, but I can not find the documend

    Pleas help

    John

    Reply

  6. I have this problem….

    /home/pi/Air-Predictor/interfaces/MCP3204/MCP3204.py:18: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
    GPIO.setup(self.SPIMOSI, GPIO.OUT)
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address
    Error accessing 0×77: Check your I2C address

    Please Help me….. :(

    Reply

  7. Matthias Szusdziara

    After reading about those dead i2c interfaces, i’d like to recommend a great read on cheap and powerful level shifting:
    http://ics.nxp.com/support/documents/interface/pdf/an97055.pdf

    The circuits described can also be used to protect a bus member (without any level shifting) and they come at the cost of only two to four cheapo FETs (depending on the level of protection you want) and some additional pullup resistors.

    Note that the pi (at least Pi B rev. 2) already comes with pullup resistors installed. (Paralleling them in general isn’t a good idea since it increases the current. It might be an option if high bus speeds are desired and the pullups are selected to be safe, but that’s a different story.)

    Btw: Bread board users may solder the SMD FETs (if the TO-92 types are not accessable) to a 3-pin jumper header for prototyping.

    Cheers,
    Matthias

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>