Sunday, December 14, 2014

Raspberry Pi send block of data to Arduino using I2C

In this example, Raspberry Pi programmed using Python with smbus library, act as I2C master, ask user enter something as string, then send to Arduino Uno in blocks of data. In Arduino side, act as I2C slave, interpret received data in number of bytes, command, and body of data, to display on 16x2 LCD display.


Prepare on Raspberry Pi for I2C communication, refer to previous post "Communication between Raspberry Pi and Arduino via I2C, using Python".

Connection between Raspberry Pi, Arduino Uno and 16x2 LCD:


i2c_slave_12x6LCD.ino sketch run on Arduino Uno.
/*
 LCD part reference to:
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

#include <LiquidCrystal.h>
#include <Wire.h>

#define LED_PIN 13
boolean ledon = HIGH;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte slave_address = 7;

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print startup message to the LCD.
  lcd.print("Arduino Uno");
  
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);
  
  Wire.begin(slave_address);
  Wire.onReceive(receiveEvent);
}

void loop() {

}

void receiveEvent(int howMany) {
  lcd.clear();
  
  int numOfBytes = Wire.available();
  //display number of bytes and cmd received, as bytes
  lcd.setCursor(0, 0);
  lcd.print("len:");
  lcd.print(numOfBytes);
  lcd.print(" ");
  
  byte b = Wire.read();  //cmd
  lcd.print("cmd:");
  lcd.print(b);
  lcd.print(" ");

  //display message received, as char
  lcd.setCursor(0, 1);
  for(int i=0; i<numOfBytes-1; i++){
    char data = Wire.read();
    lcd.print(data);
  }
  
  toggleLED();
}

void toggleLED(){
  ledon = !ledon;
  if(ledon){
    digitalWrite(LED_PIN, HIGH);
  }else{
    digitalWrite(LED_PIN, LOW);
  }
}

i2c_uno.py, python program run on Raspberry Pi.
#have to run 'sudo apt-get install python-smbus'
#in Terminal to install smbus
import smbus
import time
import os

# display system info
print os.uname()

bus = smbus.SMBus(1)

# I2C address of Arduino Slave
i2c_address = 0x07
i2c_cmd = 0x01

def ConvertStringToBytes(src):
    converted = []
    for b in src:
        converted.append(ord(b))
    return converted

# send welcome message at start-up
bytesToSend = ConvertStringToBytes("Hello Uno")
bus.write_i2c_block_data(i2c_address, i2c_cmd, bytesToSend)

# loop to send message
exit = False
while not exit:
    r = raw_input('Enter something, "q" to quit"')
    print(r)
    
    bytesToSend = ConvertStringToBytes(r)
    bus.write_i2c_block_data(i2c_address, i2c_cmd, bytesToSend)
    
    if r=='q':
        exit=True


next:
- Raspberry Pi + Arduino i2c communication, write block and read byte


WARNING:
Somebody advise to use I2C Logic Level Converter between Raspberry Pi and Arduino, otherwise the RPi's ports will be burnt! So, please think about it and take your own risk.

No comments: