Raspberry Pi and Arduino Connected Using I2C

Raspberry-PI-I2c-Arduino

With Raspberry Pi and I2C communication, we can connect the Pi with single or multiple Arduino boards. The Raspberry Pi has only 8 GPIO’s, so it would be really useful to have additional Inputs and outputs by combining the Raspberry Pi and Arduino.

There are many ways of Linking them such as using USB cable and Serial Connection. Why do we choose to use I2C? One reason could be it does not use your serial, USB on the Pi. Given the fact that there are only 2 USB ports, this is definitely a big advantage. Secondly, flexibility. You can easily connect up to 128 slaves with the Pi. Also we can just link them directly without a Logic Level Converter.

In this article I will describe how to configure the devices and setup Raspberry Pi as master and Arduino as slave for I2C communication. Article1 and Article2 if you don’t know what is I2C.

In the next article I will be doing some Voice Recognition, if you are interested see here Raspberry Pi Voice Recognition Works Like Siri

How Does It Work? Is It Safe?

The Raspberry Pi is running at 3.3 Volts while the Arduino is running at 5 Volts. There are tutorials suggest using a level converter for the I2C communication. This is NOT needed if the Raspberry Pi is running as “master” and the Arduino is running as “slave”.

The reason it works is because the Arduino does not have any pull-ups resistors installed, but the P1 header on the Raspberry Pi has 1k8 ohms resistors to the 3.3 volts power rail. Data is transmitted by pulling the lines to 0v, for a “high” logic signal. For “low” logic signal, it’s pulled up to the supply rail voltage level. Because there is no pull-up resistors in the Arduino and because 3.3 volts is within the “low” logic level range for the Arduino everything works as it should.

Raspberry-PI-I2c-Arduino-connected

Remember though that if other I2C devices are added to the bus they must have their pull-up resistors removed. For more information, see here.

These are the images showing where the I2C pins are on the Raspberry Pi and Arduino.

Note that the built-in pull-up resistors are only available on the Pi’s I2C pins (Pins 3 (SDA) and 5 (SCL), i.e. the GPIO0 and GPIO1 on a Rev. 1 board, GPIO2 and GPIOP3 on a Rev. 2 board:

I2C Raspberry Pi and Arduino Connect Link

On the Arduino Uno, the I2C pins are pins A4 (SDA) and A5 (SCL), On the Arduino Mega, they are 20 (SDA), 21 (SCL)

I2C Raspberry Pi and Arduino Connect Link

For information about the Arduino I2C Configuration and for other models of Arduino, check out this documentation Wire library.

Setup Environment on Raspberry Pi for I2C Communication

I will describe the process briefly here, if you are in doubt please refer to a more detailed process here and here.

Remove I2C from Blacklist:

$ cat /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default (many users don't need them)
blacklist spi-bcm2708
#blacklist i2c-bcm2708

Load i2c.dev in Module File

Add this to the end of /etc/modules

i2c-dev

Install I2C Tools

$ sudo apt-get install i2c-tools

Allow Pi User to Access I2C Devices

$ sudo adduser pi i2c

Now reboot the RPI. After that you should see the i2c devices:

pi@raspberrypi ~ $ ll /dev/i2c*
crw-rw---T 1 root i2c 89, 0 May 25 11:56 /dev/i2c-0
crw-rw---T 1 root i2c 89, 1 May 25 11:56 /dev/i2c-1

Now we run a simple test, scan the i2c bus:

pi@raspberrypi ~ $ i2cdetect -y 1 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Hint: if you’re using the first revision of the RPI board, use “-y 0″ as parameter. The I2C bus address changed between those two revisions.

Install Python-SMBus

This provides I2C support for Python, documentation can be found here. Alternatively, Quck2Wire is also available.

sudo apt-get install python-smbus

Configure Arduino As Slave Device For I2C

Load this sketch on the Arduino. We basically define an address for the slave (in this case, 4) and callback functions for sending data, and receiving data. When we receive a digit, we acknowledge by sending it back. If the digit happens to be ‘1’, we switch on the LED.

This program has only been tested with Arduino IDE 1.0.


#include <Wire.h>

#define SLAVE_ADDRESS 0x04
int number = 0;
int state = 0;

void setup() {
    pinMode(13, OUTPUT);
    Serial.begin(9600);         // start serial for output
    // initialize i2c as slave
    Wire.begin(SLAVE_ADDRESS);

    // define callbacks for i2c communication
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);

    Serial.println("Ready!");
}

void loop() {
    delay(100);
}

// callback for received data
void receiveData(int byteCount){

    while(Wire.available()) {
        number = Wire.read();
        Serial.print("data received: ");
        Serial.println(number);

        if (number == 1){

            if (state == 0){
                digitalWrite(13, HIGH); // set the LED on
                state = 1;
            }
            else{
                digitalWrite(13, LOW); // set the LED off
                state = 0;
            }
         }
     }
}

// callback for sending data
void sendData(){
    Wire.write(number);
}

Configure Raspberry Pi As Master Device

Since we have a listening Arduino slave, we now need a I2C master.

I have written this testing program in Python. This is what it does: the Raspberry Pi asks you to enter a digit and sends it to the Arduino, the Arduino acknowledges the received data by send the exact same number back.

In the video, I used a built-in programming tool called “IDLE” in Raspberry Pi for compiling.


import smbus
import time
# for RPI version 1, use "bus = smbus.SMBus(0)"
bus = smbus.SMBus(1)

# This is the address we setup in the Arduino Program
address = 0x04

def writeNumber(value):
    bus.write_byte(address, value)
    # bus.write_byte_data(address, 0, value)
    return -1

def readNumber():
    number = bus.read_byte(address)
    # number = bus.read_byte_data(address, 1)
    return number

while True:
    var = input("Enter 1 - 9: ")
    if not var:
        continue

    writeNumber(var)
    print "RPI: Hi Arduino, I sent you ", var
    # sleep one second
    time.sleep(1)

    number = readNumber()
    print "Arduino: Hey RPI, I received a digit ", number
    print

For more read/write functions, check out this useful look up table for the functions.

Connect Your Arduino With Raspberry Pi

Finally, we need to connect the Raspberry Pi and Arduino on the I2C bus. Connection is easy:

RaspberryPI-I2c-Arduino

RPI               Arduino (Uno/Duemillanove)
--------------------------------------------
GPIO 0 (SDA) <--> Pin 4 (SDA)
GPIO 1 (SCL) <--> Pin 5 (SCL)
Ground       <--> Ground

To make sure this is working, run i2cdetect -y 1 again in the terminal, you should get something like this. 04 is the address we defined in the Arduino sketch.

pi@raspberrypi ~ $ i2cdetect -y 1 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- 04 -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

That’s the end of this article, for results, please see video on top. From here, you can add sensors to the Arduino, to send data back to the Raspberry. Or have servos and motors on the Arduino that can be controlled from the Raspberry Pi. It’s just Fun.

Updates: 07/07/2013

Someone messaged me asking how to use logic level converter for i2c connection between Raspberry Pi an d Arduino. I happen to have a spare Logic Level converter, so I gave it a go.

This is how I connect them.

GPIO0 (SDA) -- | TX1  -- TX0 | -- A4 (SDA)
GPIO1 (SCL) -- | RX0  -- RX1 | -- A5 (SCL)
3.3V        -- | LV   -- HV  | -- 5V
GND         -- | GND  -- GND | -- GND

08745-04-L

But the result was a little weird. The data successfully sent to the Arduino, and the data was also received successfully from the Arduino on the Pi, but the data was wrong at the raspberry pi side.

  • When I sent number 1 to the Arduino, I got 0 back.
  • When I sent 2, I got 1 back.
  • sent 3 and got 1 back
  • sent 4 and got 2 back… etc…

I don’t know why this is happening, something to do with the converter? or maybe the connection is wrong? I don’t have time to figure this out. Since I can get it working without a logic level converter, i will leave it for now, if you do know why, please let me know.

Subscribe to our Youtube Channel for more videos :D
Don't have much on Google Plus, but follow me anyway :)
Donate any amount, to help us maintain this website.
Love Multicopters? Join our discussion Group on Facebook!

80 thoughts on “Raspberry Pi and Arduino Connected Using I2C

  1. Your post has been very helpful for newcomers like myself.
    I’ve been trying to control an led on arduino using a push button… And it worked. Then I attached a Raspberry pi and controlled the led on the arduino via i2c… It was fun!!!

    But when I try to connect them both together( to be able to control via i2c and also using a push button on the arduino to on and off the same led) I run in to many troubles.
    I would really appreciate it if you could show me a way to make it work!

Leave a Reply

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


five + = 7

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>