Connecting an Arduino to a Raspberry PI using I2C

Raspberry Pi connected to Arduino via I2C
PDF24    Send article as PDF   
I’m intending to use several Arduino Boards as a cheap means of controlling a number of RFID Readers which will be used to detect the position of Locomotive Engines on my LEGO Train Layout. That said I need a way of connecting these Arduinos to the Raspberry Pi which is the Master Controller for the layout.
The easiest way of Connecting an Arduino to a Raspberry PI is using USB, however the PI’s USB ports are need for WiFi Keyboard, Mouse, etc. So in many cases USB is out, especially if you are using a Raspberry Pi Model ‘A’.

Then there is RS232 which both support, however the PI runs on 3v3 whilst most of the Arduinos (UNO & Mega) use 5v, so one needs to add a ‘Level Converter’ between the two devices. It also limits you to just one Arduino and if you need to use more than one, another solution is needed.

Enter I2C

Both the PI and Arduino support two additional types of communication for talking to peripheral devices. First there is SPI which is a high speed serial protocol, and I2C. Like RS232, SPI needs level shifters, but this is not exactly the case for I2C.

I2C is a 2 wire protocol, allowing for 127 devices to be connected to a single bus. One device is configured as the master (The PI in our case) and then the peripherals as slaves.

An example I2C network (From Wikipedia)
An example I2C network (Wikipedia)

In the above diagram you can see that there’s two connections between devices (other than ground), SDA (Serial Data Line) which is where the data is carried, and SCL (Serial Clock Line). There’s also a pair of resistors which pull up the signals to the positive supply, Vdd.

Vdd is only there to pull the signals high, and with I2C a ‘1’ is when the signal is pulled down to 0V. It’s not there to power the devices. Therefore as long as we keep Vdd at 3v3 and no device has a pull up resistor on them (i.e. to 5V), then it will be safe to connect it to the PI. An issues only arises if any slave device on the I2C bus, also has a pull up resistor.

Arduino’s don’t have pull-up resistors, as the I2C interface is shared by two of the analogue inputs (4 & 5 to be precise). As a result there cannot be a resistor connected as would affect the reading on those pins when they are used in Analogue Mode.

Raspberry Pi & Arduino connected to I2C

So, as long as the Raspberry PI is the I2C Master, which is the case that we want in this example. Also, of the available GPIO pins, only SDA and SCL have pull up resistors. Exactly what we need.


If you are uncertain of anything, including blowing up your PI, then don’t follow this any further. You do this at your own risk. But it’s hard to gain knowledge in the field of electronics without the minor fire to impregnate information into your grey-matter.

Configuring Your Pi for I2C:

I2C is a very commonly used standard designed to allow one chip to talk to another. So, since the Raspberry Pi can talk I2C we can connect it to a variety of I2C capable chips and modules.

To make sure your Pi is ready to go with I2C we need to start by enabling the hardware. If you are using Raspbian, you will need to open LXTerminal and enter the following command:

sudo nano /etc/modules

and add these two lines to the end of the file:

i2c-bcm2708<br /> i2c-dev

After editing the file, you will need to reboot for the changes to take effect.

The I2C bus allows connection of multiple devices to your Raspberry Pi, each with a unique address, that can often be set by changing jumper settings on the module. It is very useful to be able to see which devices are connected to your Pi as a way of making sure everything is working.

To do this, it is worth running the following commands in the Terminal to install the i2c-tools utility.

sudo apt-get install python-smbus<br /> sudo apt-get install i2c-tools

Depending on your distribution, you may also have a file calle draspi-blacklist.conf:

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

If you do not have this file then there is nothing to do, however, if you do have this file, you need to edit it and comment out the lines below by putting a # in front of them.

blacklist spi-bcm2708<br /> blacklist i2c-bcm2708

.. then edit the file so that it appears as below, and then save and exit the file using CTRL-x and Y.

Raspberry Pi Blacklist

When you are ready to continue, enter the following commands to add SMBus support (which includes I2C) to Python:

sudo apt-get install python-smbus<br /> sudo apt-get install i2c-tools

i2c-tools isn’t strictly required, but it’s a useful package since you can use it to scan for any I2C or SMBus devices connected to your board. If you know something is connected, but you don’t know it’s 7-bit I2C address, this library has a great little tool to help you find it. python-smbus is required, it adds the I2C support for python!

Once this is all done, reboot!

sudo reboot

Configuring the Arduino

The following sketch implements a simple I2C slave with two commands:

  • Command 1 will toggle the onboard led on the Arduino.
  • Command 2 will return the Arduino’s temperature in Celsius.

Arduino Sketch Source Code:


The Raspberry PI client

Here’s a simple C application which will now talk to the Arduino over I2C:

C Source Code:


Save that as main.c and compile it:

$ gcc main.c -o main

Now you’ll notice there’s a couple of usleep() waits in this code, once between sending the command and again after reading the response. I’ve found that this is necessary for two reasons.

  1. The Arduino is emulating an I2C device, so it won’t respond immediately unlike a dedicated device so you need to wait a short while before reading it otherwise you won’t get a response.
  2. Without the second delay you can confuse the Arduino by requesting another command too quickly, necessitating the Arduino to be reset before it can be used again.

I found that 10000 (10ms) is enough here.

Wiring the two together

Now this is simple: First power down both the Arduino and the Raspberry PI – never connect things whilst they are powered up!

Wiring Raspberry Pi to Arduino with I2C

Next simply connect the two with 3 wires using the image above and the following table:


Raspberry PI   Arduino
GPIO 0 (SDA) < –> Pin 4 (SDA)
GPIO 1 (SCL) < –> Pin 5 (SCL)
Ground < –> Ground


Power up both the Arduino and Raspberry PI. Once it’s up and running log in to the Raspberry Pi and run i2cdetect:

$ i2cdetect -y 1

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

What you are now seeing is a list of all I2C devices connected to the Raspberry Pi. The one you are interested in is 04 (0x4) which is the Address of the Arduino.

Lets toggle the Arduino’s LED:

$ ./main 1

I2C: Connecting
I2C: acquiring bus to 0x4
Sending 1
Received 1

You should now see the Arduino’s onboard LED turn on. Run it again and the led goes out.

Check the Arduino’s Temperature?

$ ./main 2

I2C: Connecting
I2C: acquiring bus to 0x4
Sending 2
Received 37

The returned value in this case of ’37’ is the Arduino’s internal temperature measured in degrees Celsius (in this example we’ve just returned the integer temperature).

That’s about it. The next thing I now need to do is to get those additional sensors working with the Arduino and wrap them into a number of separately addressed I2C slaves.

As mentioned earlier and in that diagram, you can have many devices on the one I2C bus, so to add another Arduino all you need to do is to connect the three wires to that Arduino as well and make certain it is using a different address. Noting it does not conflict with any other I2C devices you have attached to your Raspberry Pi.

Previous Post
Pridopia Pi-9685-23017

Raspberry Pi 'Plate' or Add-on with 16 Ch. Servo & 16 Ch. GPIO

Over 12 months ago I came across a "I2C: 16 Channel, 12 bit PMW Servo & I2C 23017, 16 GPIO" add-on board for the Raspberry Pi made by a U.K. ... Read more

Next Post
Supstronics X300

Give the Raspberry Pi B+ SATA, Wi-Fi, Bluetooth & More..

I have been patiently waiting the release of the new Raspberry Pi B+ Expansion Board from Suptronics, the X300 for the last couple of months.The X300 is Raspberry Pi B+ Expansion ... Read more

Short URL:

Leave a Reply

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

Do NOT follow this link or you will be banned from the site!
error: Content is protected !!