Вы находитесь на странице: 1из 13

Raspberry Pi and Arduino

Connected Using I2C


25th May 2013

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.

Buy the Arduino from: Banggood | Amazon


Buy the Raspberry Pi from: Banggood | Amazon

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.

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:
On the Arduino Uno, the I2C pins are pins A4 (SDA)
and A5 (SCL), On the Arduino Mega, they are 20 (SDA),
21 (SCL)

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
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:
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
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.

Вам также может понравиться