Last exercise show
Raspberry Pi master + Arduino slave i2c communication, write block of data from Pi to Arduino Uno, and read a single byte from Arduino Uno. In this post show how to echo multi-byte from Arduino in requestEvent, by calling Wire.write().
In Raspberry Pi, i2c master, it send block of data to Arduino Uno, i2c slave, by calling bus.write_i2c_block_data(), to trigger receiveEvent in Arduino.
then call number of bus.read_byte() to trigger requestEvent in Arduino. The first byte echo from Arduino is the number of byte to sent, then echo the data in reversed sequency.
i2c_uno.py 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_write = 0x01
i2c_cmd_read = 0x02
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_write, 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_write, bytesToSend)
# delay 0.1 second
# with delay will cause error of:
# IOError: [Error 5] Input/output error
time.sleep(0.1)
data = ""
numOfByte = bus.read_byte(i2c_address)
print numOfByte
for i in range(0, numOfByte):
data += chr(bus.read_byte(i2c_address));
print data
if r=='q':
exit=True
i2c_slave_12x6LCD.ino, 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;
int echonum = 0;
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);
Wire.onRequest(requestEvent);
}
void loop() {
}
char echo[32];
int index = 0;
void requestEvent(){
toggleLED();
if(index==0){
Wire.write(echonum);
}else{
Wire.write(echo[echonum-1-(index-1)]);
}
index++;
}
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(" ");
index = 0;
//display message received, as char
lcd.setCursor(0, 1);
for(int i=0; i<numOfBytes-1; i++){
char data = Wire.read();
lcd.print(data);
echo[i] = data;
}
echonum = numOfBytes-1;
}
void toggleLED(){
ledon = !ledon;
if(ledon){
digitalWrite(LED_PIN, HIGH);
}else{
digitalWrite(LED_PIN, LOW);
}
}