Binerry
Raspberry Pi with I2C-Arduino-Slave

Since Raspberry Pi has only about 8 GPIO’s (or up to 17 if you reconfigure UART, SPI and I2C as GPIO) or for some other reasons, it may be helpful to combine Raspberry Pi with another μC or PIC (or even a ready-to-use μC-/PIC-Board like Arduino, Netduino or Pinguino) e.g. to get more I/O’s or just to seperate two different application areas. Such a combination is surely easy to setup via serial or usb - but at least if serial/usb is already in use or if you are thinking about using more than one further μC or PIC its getting a bit clumsy. Much more flexible and cleaner will be a solution via I2C - in this case you can easily address up to 128 slaves.

So why not combine Raspberry Pi with for example Arduino? Certainly a connection via serial of both devices sounds much easier but really is not. An i2c-slave configuration on Arduino is realized within a few minutes via Arduino’s Wire-Library. You just need to define an address for the slave and two callback-methods for sending and receiving data. Thats all:

void setup()
{
  // define slave address (0x2A = 42)
  #define SLAVE_ADDRESS 0x2A

  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);
  
  // define callbacks for i2c communication
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
}

// callback for received data
void receiveData(int byteCount)
{
    […]
}

// callback for sending data
void sendData()
{
    […]
}

The connection of Raspberry Pi with Arduino is a small tricky proposition since its running at 5V and also all logic levels are 5V, too. The RPi however is running at 3V3 and only accepts 3V3 logic levels. (Once again: Remember that a higher voltage may destroy your RPi.) So in this case you need a bidirectional level-shifter/bridge which shifts/translates and isolates the intercommunication via i2c between both devices. You will find some more informations about this in a previous blog post (I2C-Level-Shifter / I2C-Bridge).

If you have connected both devices like above you can check if your RaspberryPi detects your Arduino-slave via i2cdetect. (Remember that Raspberry Pi needs an actual firmware with an i2c enabled and supported kernel). Ensure that you have loaded the i2c-dev-module before.

sudo modprobe i2c-dev
sudo i2cdetect -y -a 0

If everything works fine it will find a device on address 0x2A and you can proceed with testing it. For this scenario i’ve written some lines of c-code. For accessing I2C within c you need to include the i2c-dev- and i2c-header-files. Creating a connection and requesting data is quite easy and straight forward:

#include <linux/i2c-dev.h>
#include <linux/i2c.h>

int deviceHandle;
char buffer[7];

int main (void)
{
  // initialize buffer
  buffer[0] = 0x00;
 
  // open device on /dev/i2c-0
  deviceHandle = open(“/dev/i2c-0”, O_RDWR);
 
  // connect to arduino as i2c slave
  int deviceI2CAddress = 0x2A;  // (0x2A = 42)
  ioctl(deviceHandle, I2C_SLAVE, deviceI2CAddress);
 
  // begin transmission and request acknowledgement
  write(deviceHandle, buffer, 1);
 
  // close connection and return
  close(deviceHandle);
  return 0;
}

I’ve connected some leds and a relay to Arduino for testing the basic operation over i2c. As you can see in the top image i’ve used my own prototyping clone of Arduino consisting of an ATmega328P with Arduino Bootloader and 5V + 3V3 voltage regulators. Its also running at 16MHz and operating at 5V and its fully compatible with the Arduino IDE - so this scenario will run on every Arduino (e.g. Uno, Leonardo, Mega or Nano).

You can download my Arduino and Raspberry Pi sample code from my github-repository or as zip-package. Just load it within Arduino IDE, build and upload it. On Raspberry Pi build i2c-arduino.c (cc -o i2c-arduino i2c-arduino.c) and run it (sudo ./i2c-arduino). The code is licensed under GPL and is distributed without any warranty. Feel free to test and play with it.

  1. nxtw reblogged this from binerry
  2. binerry posted this
Blog comments powered by Disqus