Raspberry Pi & Arduino I2C

Raspberry Pi & Arduino I2C

Postby Dan » Mon Jan 21, 2013 10:09 am

In my process of doing my Roomba Bot. I first choose to use I2C for the interface of the Raspberry Pi & the Arduino however with the need of a more robust reply system from the Arduino I choose to go with SPI. Anyhow, I thought I would post a quick tut on how to do a I2C connection just in case someone else needed to use it for some project they might have. NOTE** you will need a bidirectional level-shifter/bridge or you can burn up your Raspberry pi because of the voltage difference.

Arduino:

To get I2C running on the Arduino is really easy with the "Wire" library. http://arduino.cc/en/Reference/Wire
My use of the library is the Arduino as the slave.
First you will need to import the wire library
Code: Select all
#include "Wire.h"


Also in the header part of the Arduino code you will need to define you slave address for the Arduino (if you using the Adruino as the slave if not then no need for a address define)
Code: Select all
#define SLAVE_ADDRESS 0x2A


We also need an Array for the receiving data that is coming in from the master.
char thisArray[7];

In the "Setup" code you will initialize the i2c communication.
first we need to use the
Code: Select all
being()
method to define our relationship with the master/slave. If the Arduino was the master then the initialize would just be a simple call of the method as such
Code: Select all
Wire.begin();
. However we are going to use it as the slave. To do this we pass the slave address as the single arg
Code: Select all
Wire.begin(SLAVE_ADDRESS);
.

I personally like to define events instead of just looping though in a conditional loop.
So in the "Setup" I also define the "onRecieve" event and the "onRequest" event. You pass into them the method to call as the arg.
Code: Select all
Wire.onReceive(recData);

Code: Select all
Wire.onRequest(sendData);


So now we have the "setup" finished we need to define the two methods we used as arg's.

The "onReceive" pass in the number of bytes being read from the master as an int.
so we are defining our method signaure as
Code: Select all
void recData(int bytesIn)


I used a byte indexer for the incoming data.
Code: Select all
Byte index = 0;


Here we will use a while loop to keep recieving data as its coming into us.
Code: Select all
while(Wire.available())


While we are inside the loop we will read in the data into the array we create earlyer and increase the indexer as we go though the data.

Code: Select all
{
thisArray[index] = Wire.read();
    index++;
}


Now depending on your use you can use this data or as I wanted is a usable string for a later switch condition. So I also in the recData method I create a array to string loop

Code: Select all
String array_ ="";// this can be a global define or a local depending on you useage of it.
 for(int i = 1; i <= byteCount -1; i++)
    {
  array_ += thisArray[i];
}



Now for the reply method "sendData".
Its singure has no arg's. so it will be
Code: Select all
void sendData()

its up to your app what you reply with but here we are just replying with a single
byte to the master.
Code: Select all
{   
  Wire.write(1); 
}


So the Arduino code put all together looks like this.
Code: Select all
#include "Wire.h"

#define SLAVE_ADDRESS 0x2A

char thisArray[7];

void setup()
{
  Serial.begin(9600);
 
    // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);
   
  // define callbacks for i2c communication
  Wire.onReceive(recData);
  Wire.onRequest(sendData);
}

void loop()
{
}

void recData(int byteCount)

  byte index = 0;
 
  while(Wire.available())
  {
    thisArray[index] = Wire.read();
    index++;
  }
 
  String array_ ="";
  for(int i = 1; i <= byteCount -1; i++)
    {array_ += thisArray[i];}
  Serial.println(array_);
}

void sendData()
{   
  Wire.write(0); 
}


now for the Raspberry Pi

Raspberry Pi:

By default I2C is disabled on the Pi. Instead of explaining the steps here to enable it. This link will explain it for me http://www.instructables.com/id/Raspberry-Pi-I2C-Python/step2/Enable-I2C/

So we will start with the belief you have i2c ready to go on the Pi.
There was plenty of c, c++ code for I2C to use, But I wanted to use Python as my controlling language. There is a library for python and i2c called "quick2wire" and it looks ok, but I thought it looked as complex as just writing the code without the library.

I am choosing to keep it simple in this example to show how it can work.

Just to make sure you know something about python it is indentation based.
So lets do our imports
we need smbus and time for this example.
Code: Select all
import smbus
import time


Now we need to define a instance of smbus and pass in the I2c bus of the raspberry pi.
Code: Select all
bus = smbus.SMBus(0)


Now we will define our address of the slave (the Arduino)
Code: Select all
slave_address = 0x2a


We are going to define three methods for us to call in a endless loop.
The first one is call stringtobytes, it coverts the string passed into it to bytes.
Code: Select all
def stringtobytes(val):
          retval = []
          for c in val:
                     retval.append(ord(c))
          return retval


next we will create our write to slave function. We first define our message, then convert it to bytes and then send it to the slave.

Code: Select all
def helloSlave(input):
        message = stringtobytes(input)
        bus.write_i2c_block_data(address,0,message)


Our next one is our read function. It just reads the incoming byte.

Code: Select all
def read():
     info = bus.read_byte_data(address,0)
     return info


Now we have our functions we will write our endless loop and just to show the usage of the functions. So our complete python script will look like this

Code: Select all
import smbus
import time
bus = smbus.SMBus(0)
slave_address = 0x2a

def stringtobytes(val)
         retval = []
         for c in val:
               retval.append(ord(c))
         return retval
def helloSlave(input):
        message = stringtobytes(input)
        bus.write_i2c_block_data(address,0,message)
def read()
        info = bus.read_byte_data(address,0)
        return info
# this is the endless loop
while True: 
         helloSlave("hey")
         time.sleep(0.7)
         print read()


If you use this sample codes you should see "hey" in the Arduino serial screen
and a 0 in the Pi terminal screen.

If you have any question let me know and I will help as much as I can. Also please over look any goofy grammar errors plz.

Dan
Dan
FCW Member
 
Posts: 205
Joined: Tue Aug 30, 2011 2:18 pm
Location: Granite Falls

Re: Raspberry Pi & Arduino I2C

Postby cifefak614 » Wed Mar 24, 2021 11:55 pm

Cash App has introduced its own debit card that can be used just like any other bank debit card. The Cash App card is known as Cash Card and can be used to make payments, shop at merchants or even withdraw cash from an ATM-like any traditional bank debit card. The Cash Card is linked to the Cash App account so money is debited from your Cash App account and not your bank account.
protonmail login |
cash app login |
amazon login |
cash app login |
www.amazon.com/mytv |
cash app login |
cash app login
aol mail login |
yahoo mail login |
yahoo mail sign |
aol mail login
paypal login
office.com/setup
cifefak614
 
Posts: 3
Joined: Tue Nov 10, 2020 5:12 am
Location: unitedstate


Return to Microprocessors

Who is online

Users browsing this forum: No registered users and 1 guest

cron