Raspberry Pi Arduino I2C Interface

by Lewis Loflin

What follows is the code used in my YouTube video above and an explanation of its operation. This is a very basic demo that will be used as a basis for more complex programs.

The first program was written for the Raspberry Pi in python. Python is a high level, general purpose interpreted language. High level in the fact it's remote from the underlying hardware. Being an interpreted language means each line of code is read, interpreted, and implemented as it's running. Python is best used for numbers and strings.

It's for those reasons python is worthless for machine control. Yes it has some GPIO and an I2C interface, but those can be accessed only with additional libraries but the system is still slow being an interpreted language. While it can read some I2C or SPI sensors it would be far better to use a micro-controller such as Arduino to deal with hardware control, while the Raspberry Pi using Tkinter would create a general user interface.

These two programs, one for Raspberry Pi, the other for Arduino respectively, demonstrate how both devices exchange information back in forth in single bytes over I2C.

While the GPIO and I2C on Raspberry Pi are three volts, my Arduino Nano was operating at five volts. Raspberry Pi has it's own pull ups for I2C so don't use external resistors tied to five volts. The Arduino works just fine.

Note that the Arduino is operating in the SLAVE mode with Raspberry Pi as MASTER that limits Arduino's access to the I2C buss. I borrowed my serial LCD program and modified it for this demo. One could rewrite this to operate a non-serial LCD connection by re-writing the ssrWrite() routine and some changes in electrical connections.

For more on that see http://www.bristolwatch.com/arduino/arduino4a.html.


# Code for Raspberry Pi
# This program writes a value of o-255 to Arduino via I2C.
# This is written to work on Python 2.7

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
    
var = 0
while True:
    writeNumber(var)
    print "RPI: Hi Arduino, I sent you ", var
    # sleep 0.5 second
    time.sleep(.5)

    number = readNumber()
    print "Arduino: Hey RPI, I received a digit ", number
    print # skip a line

    var = var + 1
    if var > 255:
        var = 0	
serial LCD display circuit
LCD connection to Arduino

 
/*
Arduino code.
This is for use with the Raspberry Pi through the
I2C. RPi sends a value from 0-255 which is displayed
on the LCD display. Arduino echoes back a response and
the number sent from RPi.

LCD section taken from
http://www.bristolwatch.com/arduino/arduino4a.html

*/

#define Bit_out 12 // Pin 1-2 SN74164
#define CLK 11 // Pin 9 SN74164
#define RS 7  // Pin 4 LCD
#define E 8  // Pin 6 LCD

#define SLAVE_ADDRESS 0x04
int number = 0;
int state = 0;

// location LCD row 0 col 0 or line 1 LCD
#define Line1 0x80  
// location row 1 col 0 or line 2 LCD
#define Line2 0x80 + 0x40  

#include <Wire.h>

void setup() {
  pinMode(Bit_out, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(RS, OUTPUT);
  pinMode(E, OUTPUT);

  digitalWrite(CLK, LOW); 
  // LCD in command mode default
  digitalWrite(RS, LOW); 
  digitalWrite(E, HIGH);
  initLCD(); // se below
  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);

  // define callbacks for i2c communication
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
  typeln("Arduino Ready!", Line1);
  typeln("Number = ", Line2);
}

void loop() {
  delay(100);
} // end loop

// location is place on LCD display. 
void typeInt(int k, int location)   {
  char array1[10];
  itoa(k, array1, 10); // int to string
  typeln(array1, location);
}

void typeChar(byte val)   {
  ssrWrite(val);
  digitalWrite(RS, HIGH);
  pulseOut(E);
  digitalWrite(RS, LOW);
}

void writeCommand(byte val)   {

  ssrWrite(val); // send byte to 74164
  digitalWrite(RS, LOW); // make sure RS in Com mode
  pulseOut(E);
}


// Below we pass a pointer to array1[0].
void typeln(char *s, int location)   {
  delayMicroseconds(1000);
  writeCommand(location); // where to begin 
  while (*s)  typeChar(*(s++));
}  // end typeln

// inverts state of pin, delays, then reverts state back
void    pulseOut(byte x)   {
  byte z = digitalRead(x);
  delayMicroseconds(10);
  z = !z; // reverse state
  digitalWrite(x, z);
  z = !z; // return to original state
  digitalWrite(x, z);
} // end pulsout()


void ssrWrite(byte val)  {  // shift data to 74164
  for (int j=1; j<=8; j++)  {   // shift out MSB first
    byte  temp = val & B10000000; // MSB out first
    if (temp == 0x80) digitalWrite(Bit_out, HIGH); 
    else digitalWrite(Bit_out, LOW); 
    pulseOut(CLK); 
    val = val << 1; // shift one place left
  }  // next j
}  // end byteWrite


void initLCD(void)   {

  writeCommand(0x38); // setup for 2 lines
  writeCommand(0x0F); // blinking cursor
  writeCommand(0x01); // clear
  writeCommand(0x02); // home
}


void ClearDisplay(void)   {
  writeCommand(0x01); // clear
  writeCommand(0x02); // home
}



// callback for received data
void receiveData(int byteCount){

  while(Wire.available()) { 
    number = Wire.read();
    typeInt(number, Line2 + 9);


  }
}  // end while

// callback for sending data
void sendData(){
  Wire.write(number);
}




YouTube Videos:
MCP4725 12-Bit DAC Interface to Raspberry Pi
ADS1115 4-Channel ADC Uses I2C with Raspberry Pi
Interface I2C LCD to Raspberry Pi in C
Pulse-Width-Modulation with Raspberry Pi
Using Geany Text editor C Programming
Raspberry Pi Blink Demo
MAX6675 Raspberry Pi Demo

Videos:
Raspberry Pi, Arduino, and Learning Linux
Raspberry PI Arduino Advanced Interface
Tkinter with Raspberry Pi and PCF8591 AD-DA Sensor

Linux Videos

Live Linux Distro for Using Printer Port with Electronics
Using the powerful Rox-Filer system in Linux
Use FEH under Linux for a Wallpaper Setter
How to create Symbolic links in Linux