Raspberry Pi and Arduino Connected Using I2C

arduino-raspberry-pi-serial-connect

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.

[sourcecode language=”cpp”]

#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);
}

[/sourcecode]

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.

[sourcecode language=”python”]

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
[/sourcecode]

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.

82 thoughts on “Raspberry Pi and Arduino Connected Using I2C

  1. Georg

    re logic level converter:
    I found a comment on watterott.com/en/4-channel-I2C-safe-Bi-directional-Logic-Level-Converter-BSS138
    that hints that the problem with your trial might have been due to ‘I2C, which uses a funky pull-up system to transfer data back and forth’ and this particular converter (as shown in picture).
    I am thinking about ordering the converter linked above and will report back if I succeed ;)

    Reply
  2. Drac

    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!

    Reply
  3. nvw

    I’ve been digging a bit on this statement: “The reason it works is because the Arduino does not have any pull-ups resistors installed”

    The ATmega328P chip datasheet shows SDA and SCL are bits of Port C, described as follows:
    “Port C is a 7-bit bi-directional I/O port with internal pull-up resistors (selected for each bit)”

    And the section specifically describing SDA/SCL says:
    “Note that the internal pull-ups in the AVR pads can be enabled by setting the PORT bits corresponding to the SCL and SDA pins, as explained in the I/O Port section.”

    Looking up the Arduino Wire library code I see the following:

    The Wire.begin() & Wire.begin(int address) functions both call twi_init() which contains the following code:

    // activate internal pullups for twi.
    digitalWrite(SDA, 1);
    digitalWrite(SCL, 1);

    I understand from the above that ATmega328P based Arduinos do have pull-up resistors enabled when using the Arduino Wire library for the SDA/SCL pins and thus should not be used on a 3.3V i2c bus without a logical level converter.

    What am I missing?

    Reply
  4. sandeep

    hi oscar,
    i did all you posted and everything is ok, but whenever i run python code it gives error like these
    ——————————————————————————————————
    root@raspberrypi:/home/pi# python test19.py
    enter 1-9: 1
    Traceback (most recent call last):
    File “test19.py”, line 21, in
    writeNumber(var)
    File “test19.py”, line 9, in writeNumber
    bus.write_byte(address, value)
    IOError: [Errno 5] Input/output error
    root@raspberrypi:/home/pi#
    ————————————————————

    Reply
    1. Oscar Post author

      because the device of that address you are sending the data to is not there. please google the error before asking.

      Reply
  5. Milliways2

    A c++ version of the test program

    // I2cTest
    //
    // Based on http://blog.oscarliang.net/raspberry-pi-arduino-connected-i2c/
    // Requires WiringPi http://wiringpi.com/

    #include
    #include “wiringPi.h”
    #include “wiringPiI2C.h”

    const int address = 0x04; // This is the address we setup in the Arduino Program
    int fd;

    int writeNumber(unsigned value) {
    return wiringPiI2CWrite(fd, value);
    }

    int readNumber(void) {
    return wiringPiI2CRead(fd);
    }

    int main(int argc, const char * argv[]) {
    unsigned int var;
    int number;

    fd = wiringPiI2CSetup(address); // Automatically selects i2c on GPIO

    std::cout <> var;
    while(var) {
    writeNumber(var);
    std::cout << "Arduino, I sent you " << var << std::endl;
    number = readNumber();
    std::cout << "Arduino, I received a digit " << number << std::endl;
    std::cout <> var;
    }
    return 0;
    }

    Reply
  6. Lin

    Hi, im new bie with raspberry.
    I want to connect it to my arduino uno using i2c.
    my question is:
    1. ” 04 is the address we defined in the Arduino sketch. ” —> so couldn’t we change the address to 01 or 02 or ?
    2. I send data from arduino to raspberry.
    So i make counter in arduino then i send that counter to raspberry.
    So far is it running well, my counter is 1,2,3,50,90,110,255 is it fine and raspberry can show data correctly.
    But when it takes 256, raspberry turn into 0.
    What happen with that? is it raspberry just can show my counter till 255? what causes it?
    Thanks

    Reply
    1. Oscar Post author

      1. yes you can, from 0x00 to 0xFF I believe
      2. because you are sending a byte (8 bits), which can only be 0 to 255, when you send 256, it overflows, and it will go back to 0.

      Reply
      1. chichara

        Hi, so where i can connect pin SDA SCL? coz in raspberry just have one SDA and SCL.
        Or GPIO can set as SDA SCL?
        *sorry im beginner with this.

  7. Brian92127

    Excellent tutorial!
    As a tip for anyone else trying this one: if you “copy/paste” the python code make sure you delete all of the “spaces” and replace them with “tabs”. For every 4 spaces I deleted I replaced them with 1 tab. Eight spaces deleted equals two tabs, and so on. Also, there are a couple of blank lines that are not actually blank. Python recognizes a “space” and will choke on it so make sure to delete/remove the “spaces” from the blank lines as well. Thanks again Oscar!

    Reply
    1. Oscar Post author

      yes, it is a problem with python source code on my blog, it somehow changes the indentation of the code… and python relies on it…
      Thank you for the tip!

      Reply
  8. eco_bach

    Hey Oscar. Great post!
    But 2 problems.

    1- Sending values larger than 255!

    2- Sending a continuous stream of data . My goal is to send MouseXY data in realtime.

    Since I am a novice arduino hacker, haven’t made much progress.

    Reply
    1. Oscar Post author

      Hi eco_bach,

      depends on what the possible maximum number you would send, then you should work out how many bytes of data needs to be sent, in order to represent that max number. For example if you send 2 bytes of data, it represents a number between 0-65536.
      And now, modify the receiving side code, as you will expect to receive 2 bytes of data every time.

      Reply
  9. Guillaume L.

    Thanks!

    Perfect tutorial!

    Two reamarks :
    “ll /dev/i2c*” required the uncommented alias ll in file “.bashrc” (or using ls -la)

    If you use a Arduino Leonardo pins are :
    Pin 2 (SDA)
    Pin 3 (SCL)

    Reply
  10. Daniel Eriksson

    Hi.

    I would like to share some important info regarding Wire library on Arduino. I spent many hours debugging communication on the Raspberry Pi when I randomly got “IOError: [Errno 5] Input/output error”.

    Don’t put heavy code in receiveData() function on you Arduino. This code is called from an interrupt and to execute code here will disrupt communication. I suggest you to put received data in your own buffer and close the function as soon as you can.

    Like this:

    unsigned char tmpBuffer[120];
    unsigned char currentPos = 0;

    void receiveData(int byteCount){
    unsigned int number = 0;
    currentPos = 0;
    while(Wire.available()) {
    number = Wire.read();
    tmpBuffer[currentPos] = number;
    currentPos++;
    }
    }

    Good luck!

    /Daniel

    Reply
  11. kay

    Not sure if anyone said this already but that particular logic level converter is not suitable for I2C, that is why you are getting errors. Try this one adafruit.com/product/757 from adafruit or look for I2C converters that are I2C compatible

    Reply
  12. Pingback: Controlling an Arduino through a Rapsberry Pi webserver | Bajdi.com

  13. Bobbie

    Magnificent web site. Plenty of helpful info here.
    I am sending it to a few pals ans additionally sharing in delicious.
    And naturally, thanks on your sweat!

    Reply
  14. Pingback: Connecting an Arduino with the Raspberry Pi via I2C | revect.de/

  15. Pingback: Rpi | Pearltrees

  16. laviritel

    Hello.
    Thanks for this great tutorial. Everething works fine.
    I have one question, maybe You can help me. For example, I’m going to send a byte array from arduino to RPi, my array looks like this:
    sysState[0]=00000001
    sysState[1]=11111111
    I send it this way:
    Wire.write(sysState,sizeof(sysState))
    And the question is, it is possible to read this two values in Python on RPi? At moment I receive only first value. Thank you again.

    Reply
    1. Oscar

      I actually tried to do that as well, but because I am not familiar with Python, and there isn’t much information about i2c communication with Python on the internet, I couldn’t find a way to do it. I would suggest reading it byte by byte if you are not getting the answer from anyway.

      Reply
  17. Avinash Babu

    hi
    can we connect multiple Arduino Uno boards to Rapberry pi ? can you provide any link or explain procedure for connecting multiple Arduino uno boards to Raspberry pi ?
    thanks for your help in advance………………………………..

    Reply
    1. Oscar

      yes, like I said in the post you can link up to 128 devices. You just need to assign each on with a different address. sorry i can’t give you more explanation right now, hope that helps.

      Reply
  18. panic

    Hi i have absolutely the same issue here i don’t get it. did you find a way to manage multibyte send from arduino ??
    thanks

    Reply
  19. Balazs

    Hi!
    I would like to transfer multiply bytes at once. With the python method “bus.write_block_data()” I was able to do this in direction to Arduino.
    But I cannot transfer more bytes from the Arduino. I guess I should use the Wire.write(resultBuffer, resultLen); on the Arduino side, but “bus.read_block_data()” does not make the Arduino to enter the sendData() callback.
    Anyone has a hint on this?
    Thx,
    Balazs

    Reply
  20. Pingback: Raspberry Pi – Arduino I2C 통신 (2013.10.26) | f*cking COREA

  21. boy

    I have a bit of a trouble here.

    I did all the instruction until i2cdetect -y 1 in the terminal
    and it shows the address 04.

    The problem is when I tried the program above no matter what I wrote the arduino would not response . I have no idea what is wrong. I tried update and upgrade the Rpi the result is still the same. Is it possible that the pi is broken?

    Thanks in advance for the answer

    Reply
    1. boy

      I managed to solve the problem, seems like the psition of variable print in the code needs to be parallel with number. Thanks a bunch for the code

      Reply
  22. Brian

    Absolutely AWESOME article. I was able to get my Rpi rev2 talking to my arduino micro in no time and your sample code and instructions were spot on!
    One problem I encountered was a sequence issue resulting in Rpi not booting up.
    When physically wired between Rpi GPIO and Arduino you MUST have Ardiuno code running and it be available for communication. If not, my Rpi would lock up in boot. Took me a little while to figure out and was a bit alarming at first but quickly figured it out.

    Thank you for this AWESOME tutorial on i2c with Rpi and Arduino!

    Reply
  23. Pingback: Connecting Raspberry Pi and Arduino using I2C | PotentialLabs - Driving Human Potential

  24. Frans Merrild

    Hi,

    I am doing a new project with the Raspberry PI, and we are doing a sensor board consisting of PIR, IR, temperature, humidity, air quality sensor, siren, andcamera.

    What do you think would be the best way to integrate these sensors to the Raspberry PI. Do we need to have an external processor board, or might we just as well connect all of these directly to the Raspberry PI?

    Reply
    1. Oscar

      is it like a weather station kind of thing? :-)
      I think you can get those sensors with I2C communications, and connect them directly to the raspberry pi!

      this sounds very interesting I might do a separate post for it!

      thanks for sharing the idea.

      Reply
  25. Marcelo

    Try to use only the TX of the Logic Level converter from Sparkfun.
    TX are bi-directional.
    RX are uni-directional.
    GPIO0 (SDA) — | TX1 — TX0 | — A4 (SDA)
    — | RX0 — RX1 | —
    3.3V — | LV — HV | — 5V
    GND — | GND — GND | — GND
    GPIO1 (SCL) — | TX1 — TX0 | — A5 (SCL)

    Reply
  26. Pingback: Raspberry Pi Home Server - Arduino - Lier les deux via le bus I2CRaspberry Pi Home Server

  27. Pingback: Communicating via i2c from Raspberry Pi to Arduino | Printing Robots

  28. Kostas Maragos

    Hey Oscar, thank you for this great post.

    I finally got to trying it out myself and I had trouble getting it to work on my Raspberry Pi running Arch Linux. The package python-smbus does not seem to be available for Arch Linux.

    After some research, I decided to give Quick2Wire a try. After modifying the code, it worked like a charm. I have created a repository on github (https://github.com/kmaragos/raspi2cino) hoping it might help others. FYI, I have tested this with an Arduino Pro Mini, Nano and Uno.

    I have included the URL to your post. I hope it is ok with you. Let me know if there is any other specific attribution method I should use. Thanks again for an amazing tutorial!

    Reply
  29. Pablo Torres

    Hi, sorry to disturb you, I have a very important question, I have a project in my house where I use an arduino board in each room to control everything that is on that room. I want to command this arduinos (8) from a tablet running android, how can i do it? Using wifi on each one? Using Bluetooth on each one? Using one as a master and connecting this one to the rest and to the tablet? Doing the same but using a raspberry pi? Can you help me? Just point me the direction you think it’s better. Thanks so much

    Reply
    1. Oscar

      You are limited to 2 choices by the Androoid Tablet, Bluetooth (BT) or Wifi.

      BT is quite easy to use on Arduino, but it’s very range limited. Not to mention you have 8! I am not sure if Bluetooth can support that many connections at the same time on the Arduino (i have not looked into this)

      Another option would be wifi. It’s not common to use wifi on Arduino (have not seen people implemented this) what are you controlling in each room?

      I personally would use Raspberry Pi to replace the Arduinos for what you described, because it supports wifi (which has longer range than BT), and all clients can connect to the network at the same time. If you are short of GPIO or need Analogue I/O, you can always extend it by adding new components.

      Reply
  30. tweety

    Hello Oscar,

    Very good tuto. Tested and … working. But is it really safe AND reliable ? Reading on internet, some says yes some say no ! I’m quite lost.

    And what do you mean by “Remember though that if other I2C devices are added to the bus they must have their pull-up resistors removed”. I have a ds18b20+ sensor. You mean that I dont have to use the 4.7k resistor ?
    Do you have a sample schema for connecting those other i2c devices.

    @Dantheman2865 : you mean the spakfun module is not working for linking raspberry and arduino ?

    Reply
    1. Oscar

      hey~ thanks for the comment.
      It is very controversial whether we should connect both devices directly.

      Like I explained there are pullup resistors on the Pi, so in theory it should be okay (I have been using this configuration since I wrote this tutorial, I have not had any problem with it yet.)
      But if you are not confident and doesn’t want to take the risk, USE a level converter. They are so cheap (~$1) so there is no reason why you shouldn’t do more to protect your pi.

      Reply
  31. Dantheman2865

    I think the reason your Level Shifter doesn’t work is because it’s uni-directional. If that’s the Sparkfun Level Shifter, you need to use Transmit and Receive properly based on the circuitry involved. I2C has one uni-directional signal (Clock) and one *Bi*-directional signal (Data). There is some circuit theory behind this, but here is a product that will work for you: https://www.adafruit.com/products/757

    Reply
    1. Oscar

      that could be the reason, I didn’t really look at the specification when I was using it, so you might be right!
      Thanks for the pointing that out! :-)

      Reply
    2. merill

      For me, the line with resistor is uni-directional but the line with the transistor is bi-directional.
      When i’m using it, i let the two resistor-line alone and i use the two other (extreme Right, extreme left).
      Less hassle.

      Reply
  32. Jason

    Hello!
    I really appreciate your entry and the help it provides!

    One note, though – in Python, the Print command requires a value set by print(value).

    You leave out these parentheses, which will trigger syntax errors if left.

    Thanks again!

    Reply
    1. Jason

      Actually, it looks like I was wrong. In this case, it can work without the parentheses, although I do think it is more “hardy” if you leave them in. This will allow the code to function even if there is a mistype somewhere along the way.

      That said, the code printed above DOES WORK (woo!) and the only reason you would need the parentheses is if you did something differently.

      Reply
      1. Oscar

        thank you for the comment, I am not familiar with Python, so I don’t really know if leaving the parentheses would cause any problem potentially, but it did work like you said. Anyway, what I was trying to achieve with “print” without any argument is to create a newline, so if any problem occur because of this, we can just add “” to it as argument i guess…

  33. Piero

    Hello,
    thanks for this nice tutorial.

    I’m trying to make it work, with Rpi REV1 and Arduino 2009/Arduino UNO. Connections are ok (I think), because when I run i2detect -y 0 I see this (Ihave two MCP23017 also connected to i2c):

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

    but when I run the python script, I see:

    python i2c_arduino.py
    Enter 1 – 9: 1
    Traceback (most recent call last):
    File “i2c_arduino.py”, line 24, in
    writeNumber(var)
    File “i2c_arduino.py”, line 10, in writeNumber
    bus.write_byte(address, value)
    IOError: [Errno 5] Input/output error

    any suggestion? I missed something?
    Thank in advance for you help

    Reply
    1. Oscar

      sorry I don’t have a Rev1 Rpi, so I can’t replicate your problem. have you tried the commented out function:
      bus.write_byte_data(address, 0, value)

      Also, make sure the cabling is correct, because the pin arrangement has changed from Rev1 to Rev2.

      Reply
      1. Piero

        Hello,
        thanks for your answer and sorry for my late reply

        It was my NEWBIE and distraction error… I have REV 1 Pi, so
        bus = smbus.SMBus(0)
        and not
        bus = smbus.SMBus(1)

        :-)

        now all seems to be working fine, thanks again

  34. Pingback: Raspberry Pi+Arduino+I²C: I dalis | Darau, blė

  35. Clayton Lambert

    Hey, thanks for the great walkthrough! I got it working no problems with continuous servos and leds for a robot. I’m looking for another guide to help me make a web gui which can interface with this setup (and can also do video) any suggestions?

    Reply
    1. Oscar

      Hi, I think that’s a very interesting idea to create a web GUI to enhance this project! I might actually do some work and write a post on this (just a thought)

      If I was going to do it
      1. I will setup a web server on my laptop/PC, maybe using Apache.
      2. Build the web GUI in HTML/PHP/Javascript, you will be using this GUI on your client (laptop/PC)
      3. We can send data from the Pi to the web server using GET or POST in Python, which can be interpreted in PHP on the server.
      4. That data will be sent to the web GUI client from the web server.

      does that make sense? Any better idea?

      Reply
      1. Clayton Lambert

        That makes perfect sense. I’m just a bit of a novice when it comes to programming especially when it comes down to multiplatform interfacing. If you could create a guide I would greatly appreciate it. Using your modified code I was able to remotely drive a arduino-pi robot around my room over wifi from the inputs into python while my laptop was vnc’d into the raspberry pi. It works fine but a web based gui would be much slicker. Thanks in advance!

  36. Pingback: Raspberry Pi Color Tracking Using PID - OscarLiang.net

  37. Jon

    Thanks for the tutorial. I’m having a bit of trouble, though. My pi is recognizing my arduino when I type i2cdetect -y 1, but when I run the python script, nothing seems to be sent or returned. In order to get the py script to work properly, I had to tab over lines 25 – 33. I don’t know python, but I don’t see how that could have affected the I2C… the script ran and asked for a digit, but the Arduino doesn’t show anything. I’d appreciate any help. Thanks!

    Reply
    1. Oscar

      by “tab over” you mean create indentation? I don’t know Python very well either, but I do know that Python is very strict about line indentation. Because it doesn’t use the semi colon ; like C or C++, wrong indentation could make your code get executed completely differently.

      Reply
  38. Pingback: Conexiune I2C intre Raspberry si Arduino | Robofun Blog

  39. Pingback: Raspberry Pi Face Recognition Using OpenCV - OscarLiang.net

  40. fm3391

    I followed this tutorial but I have a problem where no matter what integer I put in, I get the integer 9 back.
    Example:
    RPI: Hi Arduino, I sent you 1
    Arduino: Hey RPI, I received a digit 9
    or
    RPI: Hi Arduino, I sent you 7
    Arduino: Hey RPI, I received a digit 9

    Reply
    1. Goe

      I have the same exact problem. No matter what integer I put in, I get integer 9 back. I’m on Rev. 1 of Rasperry Pi, and I’m using I2C Bus 0.

      Reply
      1. Goe

        On the Arduino Serial terminal, this is what I see if I send a ‘6’:
        Ready!
        data received: 0
        data received: 6
        data received: 1

        For some reason, 2 additional bytes are always sent… a ‘0’ in front, and a ‘1’ behind the byte that I select.

      2. Goe

        Figured it out… for some reason, the python code was not working properly.

        Had to replace the write_byte_data() with write_byte() and the read_byte_data() with a read_byte() for things to finally work. Not sure why… I’m new to i2c

      3. Oscar

        you are absolutely right, the write_byte_data() has a ‘cmd’ parameter, it’s part of the data transferred, that’s why you are getting the extra byte zero.

        This is entirely my fault, I made a change in the codes, updated this post a couple of days after it was posted. I think I must have forgotten to update the Python code. I will do so now. The reason for the change is that I am still not confident with the write_byte_data() function (couldn’t find any good documentation about it), that’s why I used write_byte() as well at the end.

        Thank you very much for pointing that out!

  41. Pingback: Raspberry Pi and Arduino Connected Using I2C | Syed Anwaarullah

  42. Pingback: Connect Raspberry Pi and Arduino with Serial USB Cable - OscarLiang.net

  43. Pingback: Raspberry Pi and Arduino Connected Over Serial GPIO - OscarLiang.net

Leave a Reply

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


nine + = 10

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=""> <s> <strike> <strong>