Wednesday, January 7, 2015

Raspberry Pi + Arduino i2c communication, Wire.write() multi-byte from Arduino requestEvent

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);
 }
}

No comments:

Post a Comment

Subscribe to: Post Comments (Atom)

AltStyle によって変換されたページ (->オリジナル) /