Oscarliang Com

November 15, 2017 | Author: Jess Candelearia | Category: Arduino, Digital Technology, Digital & Social Media, Computer Hardware, Technology
Share Embed Donate


Short Description

Raspberry Pi Arduino...

Description

Menu

Search

RASPBERRY PI AND ARDUINO CONNECTED USING I2C

Share this:

 Facebook

33

 Google

 Twitter

 Email

 Reddit

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.

converted by Web2PDFConvert.com

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.

converted by Web2PDFConvert.com

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 need them) blacklist spi-bcm2708 #blacklist i2c-bcm2708

converted by Web2PDFConvert.com

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 0123456789abcdef 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

converted by Web2PDFConvert.com

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 #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; converted by Web2PDFConvert.com

} 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

converted by Web2PDFConvert.com

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.

converted by Web2PDFConvert.com

pi@raspberrypi ~ $ i2cdetect -y 1 0123456789abcdef 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

converted by Web2PDFConvert.com

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.

Related

Posted in Electronics, Featured, Raspberry Pi and tagged arduino, raspberry pi on 25th May 2013. 96 Replies

← Raspberry Pi and Arduino Connected Over Serial GPIO

Raspberry Pi Voice Recognition Works Like Siri →

96 thoughts on “Raspberry Pi and Arduino Connected Using I2C” Robson converted by Web2PDFConvert.com

12th March 2017 at 12:56 am

Hello, On the voltage level converter, I believe it is not necessary because I2C works with open collector (drain), and only Raspberry Pi would have pullup resistors enabled. So the bus will work at 3.3V correctly. See this image: i1.wp.com/maxembedded.files.wordpress.com/2014/02/i2c-bus-interface-a-closer-look1.png Reply ↓

Robson 11th March 2017 at 1:37 pm

Nice, but you can use USB (serial) instead Reply ↓

sridhar 17th February 2017 at 12:24 pm

i connected every thing according to your tutorial. but data is not transferring, i am using raspi3 model b, arduino uno. i didnot get any errors while compiling. pl somebody help me to tell what type of erros may be. Reply ↓

Roger Ram Jet 16th February 2017 at 11:49 pm

Firstly thank you for writing this blog. I have taken your code and made it work between a Raspberry Pi zero and Arduino type (DFRobot bluno beetle). Press ‘1’ and get ‘1’ back. I then modified your Python code so that it missed out the manual input and ‘1’ was programmed to ‘var’ all the time. So it just looped round. I added a delay of time.sleep(0.5) after the writeNumber command. After reducing the delay down to roughly 0.01 or there abouts I hit the, what I believe to be, the clock stretching bug of the Raspberry Pi which I have been struggling with. Apparently the Raspberry Pi doesn’t do clock stretching but the Arduino does and there lies the bug. Some I2C sensors don’t do clock stretching so they are fine with the Raspberry Pi. Again what I believe from research on the internet. Again thank you for your code that confirmed that I hadn’t done something wrong with my code. These statements are made in good faith but please do your own research. Reply ↓

converted by Web2PDFConvert.com

Mirko Hessel-von Molo 6th July 2016 at 3:46 pm

Hi Oscar, thanks for your tutorial. However, I’m a bit puzzled about your statement that the Arduino does not have pull up resistors installed. Quite to the contrary, from the Arduino documentation I gather that the ATMega microcontrollers do have pull up resistors on the I2C lines, albeit very weak ones (20k Ohms to 70 kOhms, see e. g. http://playground.arduino.cc/Main/I2CBidirectionalLevelShifter) which are enabled by the Arduino Wire library. So as far as I can see, the hardware setup you’re proposing (using the Raspberry Pi pullup to 3.3 Volts) is a bit risky: When the I2C bus is idle, you have 3.3 Volts on the Raspberry Pi connected via the raspberry pullups and the arduino pullups to 5 Volts on the Arduino. Assuming the total resistance to be around 20 kOhms (the 1k8 resistors on the Raspberry don’t influence this much) this should lead to a continuous current of 85 micro-Ampere _into_ the 3.3 Volts port on the Raspberry. Can we be sure this is small enough not to mess things up on the Raspberry side? Reply ↓

Pavel 2nd July 2016 at 12:28 pm

Hi, Oscar, tell me pls, how i can connect more than 1 arduino? Maybe you have a article about it? Ore examples? I afraid try it myself. :-( Reply ↓

Oscar

Post author

9th July 2016 at 11:05 pm

no sorry i don’t, with I2C you should be able to connect more than 1 Arduino, you just need to set an unique address ID on each one… Google Arduino I2C you should be able to find a tutorial Reply ↓

Marco Tarantino 30th June 2016 at 11:04 am

Hi Oscar, Thanks for your post. I’ve used the examples of code you posted here in a project of mine. Recently, I’ve put that code on github and only later it occurred to me that your code is, well, yours. So, I would like to ask for your permission to share this code (you can find it here https://github.com/metisconverted by Web2PDFConvert.com

vela/raspmetis/blob/master/data_fetch.py). Admittedly, the present version contains what I believe are 13 lines in common with yours, but I still think you’re the author of those lines and, moreover, in the history there is a verbatim copy of your code. Reply ↓

Linus 3rd June 2016 at 11:17 am

Just a quick correction while using that logic lever shifter the conection that you tried is wrong should be GPIO0 (SDA) — | TX1 — TX0 | — A4 (SDA) NC — |RXO — RX1 | NC 3.3V — | LV — HV | — 5V GND — | GND — GND | — GND NC ————–|RX1 — RX0 | —– NC GPIO1 (SCL) — | TX1 — TX0 | — A5 (SCL) also made de order more as it is on the pdb. Reply ↓

Verlene 17th February 2016 at 11:10 am

When some one searches for his necessary thing, therefore he/she wants to be available that in detail, thus that thing is maintained over here. ironsteelcenter Reply ↓

jep 22nd February 2016 at 3:23 pm

Hi Oscar, The C++ code posted by Milliways2 didn’t compile for me, here’s a version that does. Compile with g++ -o i2ctest i2ctest.c -l wiringPi // I2cTest // // Based on https://oscarliang.com/raspberry-pi-arduino-connected-i2c/ // Requires WiringPi http://wiringpi.com/

converted by Web2PDFConvert.com

#include #include #include 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 while(true) { std::cout var; writeNumber(var); std::cout
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF