SlideShare a Scribd company logo
Connecting
Raspberry Pi to
Arduino using I2C
Raspberry Pi
This work is licensed under the
Creative Commons Attribution-
ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/b
y-sa/4.0/.
Revision 2
Companion Github
What is I2C?
The Inter-IC Bus (I-IC or I2C) standard defines the hardware and
electrical characteristics of the interface between nearby devices using
only two wires (and a third for ground reference).
SMBus was introduced by Intel as a tight subset of I2C, strictly defining
the interface between devices.
It is commonly used in televisions, computer components, and many
ADC and DAC and GPS devices.
The Raspberry Pi most commonly uses an SMBus implementation
in Python 2.x, and this is what we will concentrate on in this
document.
Connecting Devices
Identify SDA, SCL, and GND pins on both Raspberry Pi and the Arduino.
Connect SDA to SDA, SCL to SCL, and GND to GND between the two devices.
It is possible to connect the two devices directly to one another without a level
shifter, but it is not best practice. I2C levels for a low signal is 0.3Vcc and for a
high, 0.7Vcc. With the Raspberry Pi being a 3.3V device and the Arduino requiring
5V for Vcc, a logic level 'high' coming from the 3.3V Raspberry Pi is slightly below
the 0.7*5= 3.5V required for a definite logic 'high' in the Arduino.
Voltage Levels
The Raspberry Pi is a 3.3V device while the Arduino is a 5V device, but because
both devices are connected in open-drain configuration with relatively high pull-up
resistor values, it is unlikely damage will occur. The problem is that the
communication between the two devices is not guaranteed to work well due to the
3.5V minimum logic level 'high' required by the Arduino, and the Raspberry Pi input
is not 5V resistant.
A level shifter isolates the two different
voltages, while transmitting on/off information
in both directions.
Having said that, I have had reliable
communication between the Raspberry Pi and
the Arduino without any loss of data, but I am
worried about the Arduino accidently driving
one of the SDA or SCL pins to 5V as an output
if the program is not written carefully and
damaging the Raspberry Pi. User beware.
I2C Level Shifter
This rather complicated-looking circuit creates a bi-directional bus that can
automatically translate 3.3V bus signals into 5V signals and vice versa at full bus
speed. This is one of the simplest and cheapest level shifters and can easily be built
on a breadboard or soldered in a few minutes on any of the prototyping stripboards
available.
On the next slide, we look at
this circuit in detail
The Level Shifter
Isolating one of the two identical bus lines, we find an
enhancement-mode n-channel MOSFET the star of the
show. It's Gate is tied directly to the low-voltage Vcc. A
pull-up resistor connects the High voltage side to the
Drain, and another pulls the Source up to the Low voltage
side.
S1 and S2 simulate the Open-Drain connection that drives
the bus at the microcontroller.
With both switches open, Gate and Source are at the
same potential so the transistor is turned off. Both sides
are pulled up to their respective Vcc.
With S1 closed and S1 open, the source is pulled down to
0V, taking Vgs (Gate-Source Voltage) above the threshold
and turning the transistor on hard. This pulls the Drain side
down to 0V as well.
With S2 closed and S1 open, Drain is pulled to 0V and the
internal diode is forward-biased by the 3.3V, dropping the
source to around 0.6V. This is enough to pull Vgs again
beyond the threshold, opening the transistor and dragging
the bus down to 0V.
With both switches closed, both sides will be at 0V.
Setting Up Raspberry Pi
Getting the tools for Python2 and/or Python3...
1. Open a terminal window.
Enter “sudo apt-get install python-smbus” (2.x)
Or “sudo apt-get install python3-smbus” (3.x)
And “sudo apt-get install i2c-tools”
Reboot the Pi.
2. Open “Raspberry Pi Configuration” in the GUI or use
a terminal to enter 'sudo raspi-config'.
Enable I2C, save, and reboot.
3. Edit file 'etc/modules' using GUI text editor or
enter “sudo nano etc/modules”
If these two lines are not in there, type them;
i2c-bcm2708
I2c-dev
And save.
4. Edit file 'etc/modprobe.d/raspi-blacklist.comf' using
GUI editor or
Enter “sudo nano etc/modprobe.d/raspi-blacklist.conf”.
If these two lines exist, make sure a '#' is placed before
them, or delete them altogether..
#blacklist spi-bcm2708
#blacklist i2c-bcm2708
And save.
5. Finally, enter “sudo nano /boot/config.txt'. These two
lines should appear:
dtparam=i2c1=on
dtparam=i2c_arm=on
If not, make them so, and save.
Reboot.
Testing Raspberry Pi
Enter “i2cdetect -y 1” in a terminal window to
check that the I2C bus is available and running
on the Pi.
If everything is good, it will show a table of
addresses. If any I2C devices are available, their
addresses will be shown in hexadecimal.
It is worth entering “i2cdetect -F 1” to see which
SMBus calls are supported. It will save hours of
debugging to know that “SMBus Block Read” is
not supported, but “I2C Block Read” is
supported, and that “Block Process Call” is
meaningless as it is also not supported.
Preparing the Raspberry Pi
Start Python, and create a new file.
Import the SMBus library.
Create an SMBus object linked to I2C port 1.
Define the slaves address(es) to connect to.
Collect the data to be transmitted, or prepare the
data variables for reading back from the slave.
These instructions are for Python 2. Python 3 may have small differences.
import smbus
i2c_object = smbus.SMBus(1)
# Link to SMBus(0) on older Pi
addrSlave1 = 8
command = 0
dataList = [1,2,3,4,5]
i2c_object.write_i2c_block_data(addrSlave1,
command,
DataList)
getDataList = i2c_object.read_i2c_block_data(
addrSlave1,
command)
Preparing the Arduino
Start Arduino IDE
Include the Wire.h standard library for Arduino.
Set up the slave address.
Register a Wire function that will run when the
interrupt for receiving information from the Master
triggers.
The event is onReceive(function)
This event will react to information coming from
the master, and prepare for sending data back to
the master, if necessary.
Register a Wire function that will run when the
interrupt for returning data to the Master triggers.
This event is on onRequest(function)
When the interrupt fires, send data to the Master
that was requested.
#include <Wire.h>
const byte slaveAddr = 8;
void setup() {
Wire.begin(slaveAddr);
Wire.onReceive(i2cReceive);
Wire.onRequest(i2cTransmit);
}
void loop() {
}
void i2cReceive(int numBytes) {
byte rxByte;
while Wire.available() {
rxByte = Wire.read();
// Do something with the byte
}
}
Void i2cTransmit() {
Wire.write(...) // send requested data
}
Example Project
Using a Raspberry Pi 2 and an Arduino
Leonardo, we will connect up the I2C bus,
and connect an RGB LED to the Arduino. The
LED color and brightness will be controlled by
a Python program running on the Pi.
We will also simulate analog data to send
back to the Pi from the Arduino, a
temperature sensor and a light-level sensor.
The source code for both Arduino and
Raspberry Pi can be found on github at
mikeochtman.github.io/Pi_Arduino_I2C.
This drawing was created in Fritzing.
Interface Specification
Before we can communicate with the Arduino, we
need an interface specification which describes, in
detail, how and what data should be moved over
the bus from Master to Slave, and from Slave to
Master.
Type Description Access
Byte Command private
Byte Control private
Real Temperature Read Only
Real Light Level Read Only
Byte Brightness Red Read/Write
Byte Brightness Green Read/Write
Byte Brightness Blue Read/Write
Arduino Internal Data Table
Command Action
0x81 Read Temperature. Return int(round(temperature*100))
0x82 Read Light. Return int(round(light*100))
0x0A Write three bytes for brightness RGB
0x0B Write single byte, brightness Red channel
0x0C Write single byte, brightness Green channel
0x0D Write single byte, brightness Blue channel
0x90 Read three bytes brightness RGB
0x91 Read single byte, brightness Red channel
0x92 Read single byte, brightness Green channel
0x93 Read single byte, brightness Blue channel
Read,
no command
Return Slave Address, one Byte
Write,
No command
Master interrogating slave presence. Ignore
Other commands
Ignore. Master software has to deal with communication
exceptions, if any.
Arduino Software//The full software can be found on github at
// https://github.com/MikeOchtman/Pi_Arduino_I2C
//This is a simplified collection of
//the most important parts.
#include <Wire.h>
#define rxFault 0x80
#define txFault 0x40
#define slaveAddress 8
struct {
byte volatile command;
byte volatile control;
float volatile temperature;
float volatile light;
byte volatile brightR;
byte volatile brightG;
byte volatile brightB;
} commsTable;
byte volatile txTable[32];
// prepare data for sending over I2C
Void setup() {
Wire.begin(slaveAddress);
Wire.onReceive(i2cReceive);
Wire.onRequest(i2cTransmit);
}
Void loop() {
}
void i2cReceive(int byteCount) {
if (byteCount == 0) return;
byte command = Wire.read();
commsTable.command = command;
if (command < 0x80) {
i2cHandleRx(command, byteCount - 1);
} else {
i2cHandleTx(command);
}
}
byte i2cHandleRx(byte command, int numBytes) {
switch (command) {
case 0x0A:
if (Wire.available() == 3)
commsTable.brightR = Wire.read();
commsTable.brightG = Wire.read();
commsTable.brightB = Wire.read();
result = 3;
} else {
result = 0xFF;
}
break;
// and so on, one case for each command according to the
Interface Specification
default:
result = 0xFF;
}
if (result == 0xFF) commsTable.control |= rxFault;
return result;
}
Arduino Software, cont'd
byte i2cHandleTx(byte command) {
// If you are here, the I2C Master has requested
information
// If there is anything we need to do before the interrupt
// for the read takes place, this is where to do it.
return 0;
}
void i2cTransmit() {
// byte *txIndex = (byte*)&txTable[0];
byte numBytes = 0;
int t = 0;
switch (commsTable.command) {
case 0x00: // send slaveAddress.
txTable[0] = slaveAddress;
numBytes = 1;
break;
case 0x81: // send temperature
t = int(round(commsTable.temperature*100));
txTable[1] = (byte)(t >> 8);
txTable[0] = (byte)(t & 0xFF);
numBytes = 2;
break;
case 0x91: // send RGB Red channel
txTable[0] = commsTable.brightR;
numBytes = 1;
break;
// Again, create a case statement for each legal command
default:
commsTable.control |= txFault;
}
if (numBytes > 0) {
Wire.write((byte *)&txTable, numBytes);
}
}
Python Softwareimport smbus
import time
i2c = smbus.SMBus(1)
addr = 8 # address of the arduino I2C
##/* Interface Specification
## Data in a table thus:
## byte purpose
## 0: command
## 1: control
## 2-5: Current Temperature (read-only)
## 6-9: Current light level (read only)
## 10: Brightness for RED r/w
## 11: Brightness for GREEN r/w
## 12: Brightness for BLUE r/w
## Commands:
## Write with no command: Ignore
## Read with no command: Return slave address
## Command 0x81: read temperature;
## Integer returned, int(round(temp*100))
## Command 0x82: read light level;
## Integer returned, int(round(lux*100))
## Command 0x0A: Write three bytes to RGB
## Command 0x0B: Write single byte brightness red;
## Command 0x0C: Write single byte brightness green;
## Command 0x0D: Write single byte brightness blue;
## Command 0x90: read three bytes brightness RGB
## Command 0x91: read single byte brightness red;
## Command 0x92: read single byte brightness green;
## Command 0x93: read single byte brightness blue;
##
## All other values are ignored, no data returned.
RGB = [20,200,128]
temperature = 0
light_level = 0
i2c.write_quick(addr) # no data expected back
time.sleep(0.5)
print i2c.read_byte(addr) # expect the slave address
time.sleep(0.5)
print i2c.read_word_data(addr,0x81)/100.0 # temperature
time.sleep(0.5)
print i2c.read_word_data(addr,0x82)/100.0 # light level
time.sleep(0.5)
i2c.write_byte_data(addr, 0x0B, 12) # write Red value
time.sleep(0.5)
print i2c.read_byte_data(addr, 0x91) # write Green value
time.sleep(0.5)
i2c.write_byte_data(addr, 0x0C, 123) # write Blue value
time.sleep(0.5)
print i2c.read_byte_data(addr, 0x92) # get Green value
time.sleep(0.5)
i2c.write_byte_data(addr, 0x0D, 234) # write Blue value
time.sleep(0.5)
print i2c.read_byte_data(addr, 0x93) # get Blue value
time.sleep(0.5)
print i2c.read_i2c_block_data(addr, 0x90, 3) # get RGB
time.sleep(0.5)
i2c.write_i2c_block_data(addr, 0x0A, RGB) # set all RGB
time.sleep(0.5)
print i2c.read_i2c_block_data(addr, 0x90, 3) # get all RGB
time.sleep(0.5)
print i2c.read_i2c_block_data(addr, 0x10, 3) # force error
time.sleep(0.5)
The Python ResultsPython 2.7.9 results.
>>>
8
23.95
6.97
12
123
234
[12, 123, 234]
[20, 200, 128]
[0, 255, 255]
>>>
No event for write_quick()
Got back the slave Address.
Got the simulated temperature
Got the simulated light level
Set and read back Red channel
Set and read back Green channel
Set and read back Blue channel
Got back RGB values as a list.
Set new RGB values from a list
Read back the RGB values as a list
Forced a read error by sending wrong command.
RGB = [20,200,128]
i2c.write_quick(addr) # no data expected back
print i2c.read_byte(addr) # expect the slave address
print i2c.read_word_data(addr,0x81)/100.0 # temperature
print i2c.read_word_data(addr,0x82)/100.0 # light level
i2c.write_byte_data(addr, 0x0B, 12) # write Red value
print i2c.read_byte_data(addr, 0x91) # get Red value
i2c.write_byte_data(addr, 0x0C, 123) # write Green value
print i2c.read_byte_data(addr, 0x92) # get Green value
i2c.write_byte_data(addr, 0x0D, 234) # write Blue value
print i2c.read_byte_data(addr, 0x93) # get Blue value
print i2c.read_i2c_block_data(addr, 0x90, 3) # get RGB
i2c.write_i2c_block_data(addr, 0x0A, RGB) # set all RGB
print i2c.read_i2c_block_data(addr, 0x90, 3) # get all RGB
print i2c.read_i2c_block_data(addr, 0x10, 3) # force error
Instructions in Detail
Master (Rpi, Python) Slave (Arduino
Bus.write_quick(slave)
Used to check presence, or trigger event in slave without data
transfer.
Wire.onReceive() event triggered, but no data is sent.
Bytes received: 0. Bytes returned: 0.
Bus.write_byte(slave, data)
Can be used to instruct the slave to do any of up to 255 different
actions, or to place this byte in one predefined byte variable.
Wire.onReceive() event triggered. Single byte received.
Bytes received: 1. Bytes returned: 0.
ByteValue = Bus.read_byte(addr)
Read slave status or a single predefined value
Wire.onRequest() event triggered only. No data received.
Slave must return one defined byte.
Bytes received: 0. Bytes returned: 1.
Bus.write_byte_data(addr, command, byteValue)
Send slave some information to accompany a command.
Wire.onReceive() event triggered. Two bytes sent. First byte is a
command, second byte is the byte data to accompany it.
Bytes received: 2. Bytes returned: 0.
ByteValue = Bus.read_byte_data(addr, command)
Interrogate a slave about a specific piece of information
Wire.onReceive event triggered. One byte sent, a command for
which byte is requested from slave. Wire.onRequest() then
triggered, and one byte to be returned.
Bytes received: 1. Bytes returned: 1
Instructions in Detail
Master (Rpi, Python) Slave (Arduino
Bus.write_word_data(addr, command, integerVal)
Send slave extra information accompanying a specific command
Wire.onReceive() event triggered, three bytes send. First byte is
command, second is LSB, third is MSB of integer.
Bytes received: 3. Bytes returned: 0.
WordValue = Bus.read_word_data(addr, command)
Retrieve two bytes, first LSB, then MSB of an integer. Python knows
to rebuild the integer. Retrieve integer data from slave.
Wire.onReceive() event triggered. Single byte received, a
command. Wire.onRequest() event triggered, slave must send back
two bytes, first LSB, then MSB, of an integer.
Bytes received: 1. Bytes returned: 2.
Bus.write_block_data(addr, command, [list of bytes])
Sending unstructured data.
Wire.onReceive() event triggered. Several bytes sent. First byte is
command, second is number of following bytes, remainder of bytes
must be processes according to interface list.
Bytes received: > 2. Bytes returned: 0.
Bus.write_i2c_block_data(addr, command, [list of bytes])
Use this to fill a table of related bytes quickly.
Wire.onReceive() event triggered. Several bytes sent. First byte is a
command, remaining bytes to be processed according to interface.
Bytes received: > 1. Bytes returned: 0.
ByteList = Bus.read_i2c_block_data(addr, command)
Use this to read a table of related bytes quickly
Wire.onReceive event triggered. One byte sent, a command for
which byte is requested from slave. Wire.onRequest() then
triggered, requested bytes returned as per interface list.
Bytes received: 1. Bytes returned: > 1
Instructions in Detail
Master (Rpi, Python) Slave (Arduino
List = bus.read_block_data(addr, command, bytes)
will fail. Always returns the empty list. Do not use this function.
Wire.onReceive() event triggered, two bytes send. First byte is
command, second is number of bytes to return. OnRequest() event
is triggered, sending back the correct number of bytes
Bytes received: 2. Bytes returned: > 1.
Bus.block_process_call(addr, command, [vals])
Following the protocol, it reads the correct number of bytes sent
back, but random data appears in the list returned. Do not use.
Wire.onReceive() event triggered. Several bytes received, first
command, then count of bytes in [vals], then vals.
Wire.onRequest() triggered, return first count, then number of bytes
Bytes received: > 2. Bytes returned: > 2.
process_call(addr, command, val) does sent the integer 'val', but
does not trigger the interrupt to return data, so it returns the empty
list
Wire.onReceive() event triggered. Three bytes sent. First byte is
command, second is LSB and last is MSB. SMBus Specification is
to return two byte integer, but onRequest() event never triggered.
Bytes received: 3. Bytes returned: n/a.
Conclusions
Communication over I2C is quite simple to
implement using the SMBus library on the
Raspberry Pi, and the Wire.h library on the
Arduino..
Knowing what each SMBus Write and Read
instruction sends to the Arduino and what data
the Arduino is expected to send back is crucial
to successful implementation of the I2C/SMBus
protocol.
Before coding, have a clear Interface
Specification with a list of commands to be sent
to the Arduino, and clear instructions of what
should happen with the data sent and how to
return requested data.
It is also important to specify the reaction to
bad data.
The SMBus protocol document can be found at
http://smbus.org/specs/smbus20.pdf
The linux Python implementation document can be
found at
https://www.kernel.org/doc/Documentation/i2c/smb
us-protocol
Some of the SMBus protocol is not fully
programmed in the existing SMBus python
libraries, even though the functions are
available to include in the program.
These functions do not appear to work with the
arduino:
● read_block_data(addr, command, bytes)
● block_process_call(addr, command, [vals])
● process_call(addr, command, val)
All the other functions appear to operate
according to the specification.
This work is licensed under the
Creative Commons Attribution-
ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/b
y-sa/4.0/.
Compiled by Mike Ochtman.
Find me at
https://za.linkedin.com/in/mikeochtman

More Related Content

What's hot (20)

I2 c bus
I2 c bus
Akhil Srivastava
 
Multi mode multi corner (mmmc)
Multi mode multi corner (mmmc)
shaik sharief
 
Processors selection
Processors selection
Pradeep Shankhwar
 
IoT: An introduction
IoT: An introduction
JWORKS powered by Ordina
 
Sensor Networks Introduction and Architecture
Sensor Networks Introduction and Architecture
PeriyanayagiS
 
System-on-Chip
System-on-Chip
Lars Jacobs
 
Embedded Firmware Design and Development, and EDLC
Embedded Firmware Design and Development, and EDLC
JuliaAndrews11
 
Vlsi ppt priyanka
Vlsi ppt priyanka
Priyanka Gaur
 
Advance Peripheral Bus
Advance Peripheral Bus
SIVA NAGENDRA REDDY
 
SOC Processors Used in SOC
SOC Processors Used in SOC
Dr. A. B. Shinde
 
MIPI DevCon 2021: MIPI I3C Signal Integrity Challenges on DDR5-based Server P...
MIPI DevCon 2021: MIPI I3C Signal Integrity Challenges on DDR5-based Server P...
MIPI Alliance
 
Digital VLSI Design : Introduction
Digital VLSI Design : Introduction
Usha Mehta
 
ROS vs ROS2
ROS vs ROS2
Asit Deva
 
Introduction to ESP32 Programming [Road to RIoT 2017]
Introduction to ESP32 Programming [Road to RIoT 2017]
Alwin Arrasyid
 
Slow peripheral interfaces (i2 c spi uart)
Slow peripheral interfaces (i2 c spi uart)
PREMAL GAJJAR
 
Modified Gate Diffusion Input-MGDI
Modified Gate Diffusion Input-MGDI
shubham jha
 
VLSI-Physical Design- Tool Terminalogy
VLSI-Physical Design- Tool Terminalogy
Murali Rai
 
Unit 1 embedded systems and applications
Unit 1 embedded systems and applications
Dr.YNM
 
System On Chip
System On Chip
anishgoel
 
SoC Design
SoC Design
VinChip Systems - VinTrain VLSI Academy
 
Multi mode multi corner (mmmc)
Multi mode multi corner (mmmc)
shaik sharief
 
Sensor Networks Introduction and Architecture
Sensor Networks Introduction and Architecture
PeriyanayagiS
 
Embedded Firmware Design and Development, and EDLC
Embedded Firmware Design and Development, and EDLC
JuliaAndrews11
 
SOC Processors Used in SOC
SOC Processors Used in SOC
Dr. A. B. Shinde
 
MIPI DevCon 2021: MIPI I3C Signal Integrity Challenges on DDR5-based Server P...
MIPI DevCon 2021: MIPI I3C Signal Integrity Challenges on DDR5-based Server P...
MIPI Alliance
 
Digital VLSI Design : Introduction
Digital VLSI Design : Introduction
Usha Mehta
 
Introduction to ESP32 Programming [Road to RIoT 2017]
Introduction to ESP32 Programming [Road to RIoT 2017]
Alwin Arrasyid
 
Slow peripheral interfaces (i2 c spi uart)
Slow peripheral interfaces (i2 c spi uart)
PREMAL GAJJAR
 
Modified Gate Diffusion Input-MGDI
Modified Gate Diffusion Input-MGDI
shubham jha
 
VLSI-Physical Design- Tool Terminalogy
VLSI-Physical Design- Tool Terminalogy
Murali Rai
 
Unit 1 embedded systems and applications
Unit 1 embedded systems and applications
Dr.YNM
 
System On Chip
System On Chip
anishgoel
 

Viewers also liked (20)

I2C Bus (Inter-Integrated Circuit)
I2C Bus (Inter-Integrated Circuit)
Varun Mahajan
 
A seminar report on Raspberry Pi
A seminar report on Raspberry Pi
nipunmaster
 
Arduino & raspberry pi - Un connubio stimolante
Arduino & raspberry pi - Un connubio stimolante
Mirco Sbrollini
 
What is Firewall?
What is Firewall?
NetProtocol Xpert
 
Arduino (terminado)
Arduino (terminado)
Sergio Serrano Calviño
 
NGFW: MARKET GROWTH, DEPLOYMENTS, AND NSS TEST RESULTS
NGFW: MARKET GROWTH, DEPLOYMENTS, AND NSS TEST RESULTS
NSS Labs
 
PR_ALT_28072015_SiConTech_acquisition
PR_ALT_28072015_SiConTech_acquisition
Akhil Srivastava
 
Arduino arduino boardnano
Arduino arduino boardnano
clickengenharia
 
I2C Subsystem In Linux-2.6.24
I2C Subsystem In Linux-2.6.24
Varun Mahajan
 
Arduino nanomanual23
Arduino nanomanual23
clickengenharia
 
PT Docs on bpm'online English version
PT Docs on bpm'online English version
ООО "Программные Технологии"
 
Network Security: Protecting SOHO Networks
Network Security: Protecting SOHO Networks
Jim Gilsinn
 
S3 Group on Code Management - RDK Users Conference 2014
S3 Group on Code Management - RDK Users Conference 2014
S3 Group | TV Technology
 
HKG15-506: Comcast - Lessons learned from migrating the RDK code base to the ...
HKG15-506: Comcast - Lessons learned from migrating the RDK code base to the ...
Linaro
 
Reverse car-parking
Reverse car-parking
Salehin Rahman Khan
 
Решения Cisco для обеспечения кибербезопасности промышленных систем автоматиз...
Решения Cisco для обеспечения кибербезопасности промышленных систем автоматиз...
Компания УЦСБ
 
Размещение презентаций в Internet
Размещение презентаций в Internet
anxesenpa
 
Годовой отчет Cisco по информационной безопасности за 2016 год
Годовой отчет Cisco по информационной безопасности за 2016 год
Cisco Russia
 
How to Solve Real-Time Data Problems
How to Solve Real-Time Data Problems
IBM Power Systems
 
Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++
ppd1961
 
I2C Bus (Inter-Integrated Circuit)
I2C Bus (Inter-Integrated Circuit)
Varun Mahajan
 
A seminar report on Raspberry Pi
A seminar report on Raspberry Pi
nipunmaster
 
Arduino & raspberry pi - Un connubio stimolante
Arduino & raspberry pi - Un connubio stimolante
Mirco Sbrollini
 
NGFW: MARKET GROWTH, DEPLOYMENTS, AND NSS TEST RESULTS
NGFW: MARKET GROWTH, DEPLOYMENTS, AND NSS TEST RESULTS
NSS Labs
 
PR_ALT_28072015_SiConTech_acquisition
PR_ALT_28072015_SiConTech_acquisition
Akhil Srivastava
 
Arduino arduino boardnano
Arduino arduino boardnano
clickengenharia
 
I2C Subsystem In Linux-2.6.24
I2C Subsystem In Linux-2.6.24
Varun Mahajan
 
Network Security: Protecting SOHO Networks
Network Security: Protecting SOHO Networks
Jim Gilsinn
 
S3 Group on Code Management - RDK Users Conference 2014
S3 Group on Code Management - RDK Users Conference 2014
S3 Group | TV Technology
 
HKG15-506: Comcast - Lessons learned from migrating the RDK code base to the ...
HKG15-506: Comcast - Lessons learned from migrating the RDK code base to the ...
Linaro
 
Решения Cisco для обеспечения кибербезопасности промышленных систем автоматиз...
Решения Cisco для обеспечения кибербезопасности промышленных систем автоматиз...
Компания УЦСБ
 
Размещение презентаций в Internet
Размещение презентаций в Internet
anxesenpa
 
Годовой отчет Cisco по информационной безопасности за 2016 год
Годовой отчет Cisco по информационной безопасности за 2016 год
Cisco Russia
 
How to Solve Real-Time Data Problems
How to Solve Real-Time Data Problems
IBM Power Systems
 
Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++
ppd1961
 
Ad

Similar to I2c interfacing raspberry pi to arduino (20)

ELC 2016 - I2C hacking demystified
ELC 2016 - I2C hacking demystified
Igor Stoppa
 
ARDUINO AND ITS PIN CONFIGURATION
ARDUINO AND ITS PIN CONFIGURATION
soma saikiran
 
Using arduino and raspberry pi for internet of things
Using arduino and raspberry pi for internet of things
Sudar Muthu
 
M.Tech Internet of Things Unit - III.pptx
M.Tech Internet of Things Unit - III.pptx
AvinashAvuthu2
 
IoT Physical Devices and End Points.pdf
IoT Physical Devices and End Points.pdf
GVNSK Sravya
 
How to use an Arduino
How to use an Arduino
AntonAndreev13
 
Raspberry Pi with Java 8
Raspberry Pi with Java 8
javafxpert
 
Arduino Programming - Brief Introduction
Arduino Programming - Brief Introduction
NEEVEE Technologies
 
Getting Started With Raspberry Pi - UCSD 2013
Getting Started With Raspberry Pi - UCSD 2013
Tom Paulus
 
Taking the hard out of hardware
Taking the hard out of hardware
Ronald McCollam
 
Raspberry Pi - best friend for all your GPIO needs
Raspberry Pi - best friend for all your GPIO needs
Dobrica Pavlinušić
 
Arduino
Arduino
Jerin John
 
Sensors and Actuators in Arduino, Introduction
Sensors and Actuators in Arduino, Introduction
BibekPokhrel13
 
Arduino spooky projects_class3
Arduino spooky projects_class3
Anil Yadav
 
Interfacing the Raspberry Pi to the World
Interfacing the Raspberry Pi to the World
Omer Kilic
 
An hemmanur
An hemmanur
Sangeetha Marikkannan
 
Getting Started with Raspberry Pi - USC 2013
Getting Started with Raspberry Pi - USC 2013
Tom Paulus
 
Embedded Systems: Lecture 9: The Pi Control ARM
Embedded Systems: Lecture 9: The Pi Control ARM
Ahmed El-Arabawy
 
Arduino - Learning.pdf
Arduino - Learning.pdf
KhalilSedki1
 
Raspberry-Pi
Raspberry-Pi
Rehan Fazal
 
ELC 2016 - I2C hacking demystified
ELC 2016 - I2C hacking demystified
Igor Stoppa
 
ARDUINO AND ITS PIN CONFIGURATION
ARDUINO AND ITS PIN CONFIGURATION
soma saikiran
 
Using arduino and raspberry pi for internet of things
Using arduino and raspberry pi for internet of things
Sudar Muthu
 
M.Tech Internet of Things Unit - III.pptx
M.Tech Internet of Things Unit - III.pptx
AvinashAvuthu2
 
IoT Physical Devices and End Points.pdf
IoT Physical Devices and End Points.pdf
GVNSK Sravya
 
Raspberry Pi with Java 8
Raspberry Pi with Java 8
javafxpert
 
Arduino Programming - Brief Introduction
Arduino Programming - Brief Introduction
NEEVEE Technologies
 
Getting Started With Raspberry Pi - UCSD 2013
Getting Started With Raspberry Pi - UCSD 2013
Tom Paulus
 
Taking the hard out of hardware
Taking the hard out of hardware
Ronald McCollam
 
Raspberry Pi - best friend for all your GPIO needs
Raspberry Pi - best friend for all your GPIO needs
Dobrica Pavlinušić
 
Sensors and Actuators in Arduino, Introduction
Sensors and Actuators in Arduino, Introduction
BibekPokhrel13
 
Arduino spooky projects_class3
Arduino spooky projects_class3
Anil Yadav
 
Interfacing the Raspberry Pi to the World
Interfacing the Raspberry Pi to the World
Omer Kilic
 
Getting Started with Raspberry Pi - USC 2013
Getting Started with Raspberry Pi - USC 2013
Tom Paulus
 
Embedded Systems: Lecture 9: The Pi Control ARM
Embedded Systems: Lecture 9: The Pi Control ARM
Ahmed El-Arabawy
 
Arduino - Learning.pdf
Arduino - Learning.pdf
KhalilSedki1
 
Ad

Recently uploaded (20)

Automatic plant watering system using GSM and moisture sensors.
Automatic plant watering system using GSM and moisture sensors.
asmarajput51
 
Predictive Maintenance- From fixing to predicting problems
Predictive Maintenance- From fixing to predicting problems
Nabeel35708
 
最新版德国不来梅艺术学院毕业证(HfK毕业证书)原版定制
最新版德国不来梅艺术学院毕业证(HfK毕业证书)原版定制
Taqyea
 
Computer project for ai and non ai robot
Computer project for ai and non ai robot
shivaniarora32567
 
最新版英国伦敦大学皇家霍洛威学院毕业证(RHUL毕业证书)原版定制
最新版英国伦敦大学皇家霍洛威学院毕业证(RHUL毕业证书)原版定制
Taqyea
 
Muscular_System_Scaffold_Presentation.pptx
Muscular_System_Scaffold_Presentation.pptx
Manikantan70
 
最新版西班牙梅南德斯·佩拉尤国际大学毕业证(UIMP毕业证书)原版定制
最新版西班牙梅南德斯·佩拉尤国际大学毕业证(UIMP毕业证书)原版定制
Taqyea
 
Windows Cleaner Software By Yamicsoft.pptx
Windows Cleaner Software By Yamicsoft.pptx
yamicsoft458
 
Cocaine Use disorders.pptx research on it
Cocaine Use disorders.pptx research on it
rajanirprasadkrishna
 
Max Power products list 2024 compone.pdf
Max Power products list 2024 compone.pdf
jmglpa
 
Human Computer Interactions Lecture 1.pptx
Human Computer Interactions Lecture 1.pptx
ShavinGopee2
 
How_Volcanshgsgsgsgsgsgsgsggsoes_Work.pptx
How_Volcanshgsgsgsgsgsgsgsggsoes_Work.pptx
zyx10283746
 
OB_ICF_PPT.pdf nsnsnsnnsnnsnennenenneennenenne
OB_ICF_PPT.pdf nsnsnsnnsnnsnennenenneennenenne
dibaynlucero
 
最新版美国杜比克大学毕业证(UD毕业证书)原版定制
最新版美国杜比克大学毕业证(UD毕业证书)原版定制
taqyea
 
String.pptxihugyftgrfxdf bnjklihugyfthfgxvhbjihugyfthcgxcgvjhbkipoihougyfctgf...
String.pptxihugyftgrfxdf bnjklihugyfthfgxvhbjihugyfthcgxcgvjhbkipoihougyfctgf...
minifriendofyou
 
miiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirs.pptx
miiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirs.pptx
ChandanKumarMajhi4
 
[Back2School] Timing Checks- Chapter 5.pdf
[Back2School] Timing Checks- Chapter 5.pdf
Ahmed Abdelazeem
 
Custom Hardware design for image processing.pptx
Custom Hardware design for image processing.pptx
DevanshuGaur5
 
artifical intelligence and its usage in biology
artifical intelligence and its usage in biology
chaned5
 
File Handling ppt.pptx shjd dbkd z bdjdb d
File Handling ppt.pptx shjd dbkd z bdjdb d
ssusere1e8b7
 
Automatic plant watering system using GSM and moisture sensors.
Automatic plant watering system using GSM and moisture sensors.
asmarajput51
 
Predictive Maintenance- From fixing to predicting problems
Predictive Maintenance- From fixing to predicting problems
Nabeel35708
 
最新版德国不来梅艺术学院毕业证(HfK毕业证书)原版定制
最新版德国不来梅艺术学院毕业证(HfK毕业证书)原版定制
Taqyea
 
Computer project for ai and non ai robot
Computer project for ai and non ai robot
shivaniarora32567
 
最新版英国伦敦大学皇家霍洛威学院毕业证(RHUL毕业证书)原版定制
最新版英国伦敦大学皇家霍洛威学院毕业证(RHUL毕业证书)原版定制
Taqyea
 
Muscular_System_Scaffold_Presentation.pptx
Muscular_System_Scaffold_Presentation.pptx
Manikantan70
 
最新版西班牙梅南德斯·佩拉尤国际大学毕业证(UIMP毕业证书)原版定制
最新版西班牙梅南德斯·佩拉尤国际大学毕业证(UIMP毕业证书)原版定制
Taqyea
 
Windows Cleaner Software By Yamicsoft.pptx
Windows Cleaner Software By Yamicsoft.pptx
yamicsoft458
 
Cocaine Use disorders.pptx research on it
Cocaine Use disorders.pptx research on it
rajanirprasadkrishna
 
Max Power products list 2024 compone.pdf
Max Power products list 2024 compone.pdf
jmglpa
 
Human Computer Interactions Lecture 1.pptx
Human Computer Interactions Lecture 1.pptx
ShavinGopee2
 
How_Volcanshgsgsgsgsgsgsgsggsoes_Work.pptx
How_Volcanshgsgsgsgsgsgsgsggsoes_Work.pptx
zyx10283746
 
OB_ICF_PPT.pdf nsnsnsnnsnnsnennenenneennenenne
OB_ICF_PPT.pdf nsnsnsnnsnnsnennenenneennenenne
dibaynlucero
 
最新版美国杜比克大学毕业证(UD毕业证书)原版定制
最新版美国杜比克大学毕业证(UD毕业证书)原版定制
taqyea
 
String.pptxihugyftgrfxdf bnjklihugyfthfgxvhbjihugyfthcgxcgvjhbkipoihougyfctgf...
String.pptxihugyftgrfxdf bnjklihugyfthfgxvhbjihugyfthcgxcgvjhbkipoihougyfctgf...
minifriendofyou
 
miiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirs.pptx
miiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirs.pptx
ChandanKumarMajhi4
 
[Back2School] Timing Checks- Chapter 5.pdf
[Back2School] Timing Checks- Chapter 5.pdf
Ahmed Abdelazeem
 
Custom Hardware design for image processing.pptx
Custom Hardware design for image processing.pptx
DevanshuGaur5
 
artifical intelligence and its usage in biology
artifical intelligence and its usage in biology
chaned5
 
File Handling ppt.pptx shjd dbkd z bdjdb d
File Handling ppt.pptx shjd dbkd z bdjdb d
ssusere1e8b7
 

I2c interfacing raspberry pi to arduino

  • 1. Connecting Raspberry Pi to Arduino using I2C Raspberry Pi This work is licensed under the Creative Commons Attribution- ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/b y-sa/4.0/. Revision 2 Companion Github
  • 2. What is I2C? The Inter-IC Bus (I-IC or I2C) standard defines the hardware and electrical characteristics of the interface between nearby devices using only two wires (and a third for ground reference). SMBus was introduced by Intel as a tight subset of I2C, strictly defining the interface between devices. It is commonly used in televisions, computer components, and many ADC and DAC and GPS devices. The Raspberry Pi most commonly uses an SMBus implementation in Python 2.x, and this is what we will concentrate on in this document.
  • 3. Connecting Devices Identify SDA, SCL, and GND pins on both Raspberry Pi and the Arduino. Connect SDA to SDA, SCL to SCL, and GND to GND between the two devices. It is possible to connect the two devices directly to one another without a level shifter, but it is not best practice. I2C levels for a low signal is 0.3Vcc and for a high, 0.7Vcc. With the Raspberry Pi being a 3.3V device and the Arduino requiring 5V for Vcc, a logic level 'high' coming from the 3.3V Raspberry Pi is slightly below the 0.7*5= 3.5V required for a definite logic 'high' in the Arduino.
  • 4. Voltage Levels The Raspberry Pi is a 3.3V device while the Arduino is a 5V device, but because both devices are connected in open-drain configuration with relatively high pull-up resistor values, it is unlikely damage will occur. The problem is that the communication between the two devices is not guaranteed to work well due to the 3.5V minimum logic level 'high' required by the Arduino, and the Raspberry Pi input is not 5V resistant. A level shifter isolates the two different voltages, while transmitting on/off information in both directions. Having said that, I have had reliable communication between the Raspberry Pi and the Arduino without any loss of data, but I am worried about the Arduino accidently driving one of the SDA or SCL pins to 5V as an output if the program is not written carefully and damaging the Raspberry Pi. User beware.
  • 5. I2C Level Shifter This rather complicated-looking circuit creates a bi-directional bus that can automatically translate 3.3V bus signals into 5V signals and vice versa at full bus speed. This is one of the simplest and cheapest level shifters and can easily be built on a breadboard or soldered in a few minutes on any of the prototyping stripboards available. On the next slide, we look at this circuit in detail
  • 6. The Level Shifter Isolating one of the two identical bus lines, we find an enhancement-mode n-channel MOSFET the star of the show. It's Gate is tied directly to the low-voltage Vcc. A pull-up resistor connects the High voltage side to the Drain, and another pulls the Source up to the Low voltage side. S1 and S2 simulate the Open-Drain connection that drives the bus at the microcontroller. With both switches open, Gate and Source are at the same potential so the transistor is turned off. Both sides are pulled up to their respective Vcc. With S1 closed and S1 open, the source is pulled down to 0V, taking Vgs (Gate-Source Voltage) above the threshold and turning the transistor on hard. This pulls the Drain side down to 0V as well. With S2 closed and S1 open, Drain is pulled to 0V and the internal diode is forward-biased by the 3.3V, dropping the source to around 0.6V. This is enough to pull Vgs again beyond the threshold, opening the transistor and dragging the bus down to 0V. With both switches closed, both sides will be at 0V.
  • 7. Setting Up Raspberry Pi Getting the tools for Python2 and/or Python3... 1. Open a terminal window. Enter “sudo apt-get install python-smbus” (2.x) Or “sudo apt-get install python3-smbus” (3.x) And “sudo apt-get install i2c-tools” Reboot the Pi. 2. Open “Raspberry Pi Configuration” in the GUI or use a terminal to enter 'sudo raspi-config'. Enable I2C, save, and reboot. 3. Edit file 'etc/modules' using GUI text editor or enter “sudo nano etc/modules” If these two lines are not in there, type them; i2c-bcm2708 I2c-dev And save. 4. Edit file 'etc/modprobe.d/raspi-blacklist.comf' using GUI editor or Enter “sudo nano etc/modprobe.d/raspi-blacklist.conf”. If these two lines exist, make sure a '#' is placed before them, or delete them altogether.. #blacklist spi-bcm2708 #blacklist i2c-bcm2708 And save. 5. Finally, enter “sudo nano /boot/config.txt'. These two lines should appear: dtparam=i2c1=on dtparam=i2c_arm=on If not, make them so, and save. Reboot.
  • 8. Testing Raspberry Pi Enter “i2cdetect -y 1” in a terminal window to check that the I2C bus is available and running on the Pi. If everything is good, it will show a table of addresses. If any I2C devices are available, their addresses will be shown in hexadecimal. It is worth entering “i2cdetect -F 1” to see which SMBus calls are supported. It will save hours of debugging to know that “SMBus Block Read” is not supported, but “I2C Block Read” is supported, and that “Block Process Call” is meaningless as it is also not supported.
  • 9. Preparing the Raspberry Pi Start Python, and create a new file. Import the SMBus library. Create an SMBus object linked to I2C port 1. Define the slaves address(es) to connect to. Collect the data to be transmitted, or prepare the data variables for reading back from the slave. These instructions are for Python 2. Python 3 may have small differences. import smbus i2c_object = smbus.SMBus(1) # Link to SMBus(0) on older Pi addrSlave1 = 8 command = 0 dataList = [1,2,3,4,5] i2c_object.write_i2c_block_data(addrSlave1, command, DataList) getDataList = i2c_object.read_i2c_block_data( addrSlave1, command)
  • 10. Preparing the Arduino Start Arduino IDE Include the Wire.h standard library for Arduino. Set up the slave address. Register a Wire function that will run when the interrupt for receiving information from the Master triggers. The event is onReceive(function) This event will react to information coming from the master, and prepare for sending data back to the master, if necessary. Register a Wire function that will run when the interrupt for returning data to the Master triggers. This event is on onRequest(function) When the interrupt fires, send data to the Master that was requested. #include <Wire.h> const byte slaveAddr = 8; void setup() { Wire.begin(slaveAddr); Wire.onReceive(i2cReceive); Wire.onRequest(i2cTransmit); } void loop() { } void i2cReceive(int numBytes) { byte rxByte; while Wire.available() { rxByte = Wire.read(); // Do something with the byte } } Void i2cTransmit() { Wire.write(...) // send requested data }
  • 11. Example Project Using a Raspberry Pi 2 and an Arduino Leonardo, we will connect up the I2C bus, and connect an RGB LED to the Arduino. The LED color and brightness will be controlled by a Python program running on the Pi. We will also simulate analog data to send back to the Pi from the Arduino, a temperature sensor and a light-level sensor. The source code for both Arduino and Raspberry Pi can be found on github at mikeochtman.github.io/Pi_Arduino_I2C. This drawing was created in Fritzing.
  • 12. Interface Specification Before we can communicate with the Arduino, we need an interface specification which describes, in detail, how and what data should be moved over the bus from Master to Slave, and from Slave to Master. Type Description Access Byte Command private Byte Control private Real Temperature Read Only Real Light Level Read Only Byte Brightness Red Read/Write Byte Brightness Green Read/Write Byte Brightness Blue Read/Write Arduino Internal Data Table Command Action 0x81 Read Temperature. Return int(round(temperature*100)) 0x82 Read Light. Return int(round(light*100)) 0x0A Write three bytes for brightness RGB 0x0B Write single byte, brightness Red channel 0x0C Write single byte, brightness Green channel 0x0D Write single byte, brightness Blue channel 0x90 Read three bytes brightness RGB 0x91 Read single byte, brightness Red channel 0x92 Read single byte, brightness Green channel 0x93 Read single byte, brightness Blue channel Read, no command Return Slave Address, one Byte Write, No command Master interrogating slave presence. Ignore Other commands Ignore. Master software has to deal with communication exceptions, if any.
  • 13. Arduino Software//The full software can be found on github at // https://github.com/MikeOchtman/Pi_Arduino_I2C //This is a simplified collection of //the most important parts. #include <Wire.h> #define rxFault 0x80 #define txFault 0x40 #define slaveAddress 8 struct { byte volatile command; byte volatile control; float volatile temperature; float volatile light; byte volatile brightR; byte volatile brightG; byte volatile brightB; } commsTable; byte volatile txTable[32]; // prepare data for sending over I2C Void setup() { Wire.begin(slaveAddress); Wire.onReceive(i2cReceive); Wire.onRequest(i2cTransmit); } Void loop() { } void i2cReceive(int byteCount) { if (byteCount == 0) return; byte command = Wire.read(); commsTable.command = command; if (command < 0x80) { i2cHandleRx(command, byteCount - 1); } else { i2cHandleTx(command); } } byte i2cHandleRx(byte command, int numBytes) { switch (command) { case 0x0A: if (Wire.available() == 3) commsTable.brightR = Wire.read(); commsTable.brightG = Wire.read(); commsTable.brightB = Wire.read(); result = 3; } else { result = 0xFF; } break; // and so on, one case for each command according to the Interface Specification default: result = 0xFF; } if (result == 0xFF) commsTable.control |= rxFault; return result; }
  • 14. Arduino Software, cont'd byte i2cHandleTx(byte command) { // If you are here, the I2C Master has requested information // If there is anything we need to do before the interrupt // for the read takes place, this is where to do it. return 0; } void i2cTransmit() { // byte *txIndex = (byte*)&txTable[0]; byte numBytes = 0; int t = 0; switch (commsTable.command) { case 0x00: // send slaveAddress. txTable[0] = slaveAddress; numBytes = 1; break; case 0x81: // send temperature t = int(round(commsTable.temperature*100)); txTable[1] = (byte)(t >> 8); txTable[0] = (byte)(t & 0xFF); numBytes = 2; break; case 0x91: // send RGB Red channel txTable[0] = commsTable.brightR; numBytes = 1; break; // Again, create a case statement for each legal command default: commsTable.control |= txFault; } if (numBytes > 0) { Wire.write((byte *)&txTable, numBytes); } }
  • 15. Python Softwareimport smbus import time i2c = smbus.SMBus(1) addr = 8 # address of the arduino I2C ##/* Interface Specification ## Data in a table thus: ## byte purpose ## 0: command ## 1: control ## 2-5: Current Temperature (read-only) ## 6-9: Current light level (read only) ## 10: Brightness for RED r/w ## 11: Brightness for GREEN r/w ## 12: Brightness for BLUE r/w ## Commands: ## Write with no command: Ignore ## Read with no command: Return slave address ## Command 0x81: read temperature; ## Integer returned, int(round(temp*100)) ## Command 0x82: read light level; ## Integer returned, int(round(lux*100)) ## Command 0x0A: Write three bytes to RGB ## Command 0x0B: Write single byte brightness red; ## Command 0x0C: Write single byte brightness green; ## Command 0x0D: Write single byte brightness blue; ## Command 0x90: read three bytes brightness RGB ## Command 0x91: read single byte brightness red; ## Command 0x92: read single byte brightness green; ## Command 0x93: read single byte brightness blue; ## ## All other values are ignored, no data returned. RGB = [20,200,128] temperature = 0 light_level = 0 i2c.write_quick(addr) # no data expected back time.sleep(0.5) print i2c.read_byte(addr) # expect the slave address time.sleep(0.5) print i2c.read_word_data(addr,0x81)/100.0 # temperature time.sleep(0.5) print i2c.read_word_data(addr,0x82)/100.0 # light level time.sleep(0.5) i2c.write_byte_data(addr, 0x0B, 12) # write Red value time.sleep(0.5) print i2c.read_byte_data(addr, 0x91) # write Green value time.sleep(0.5) i2c.write_byte_data(addr, 0x0C, 123) # write Blue value time.sleep(0.5) print i2c.read_byte_data(addr, 0x92) # get Green value time.sleep(0.5) i2c.write_byte_data(addr, 0x0D, 234) # write Blue value time.sleep(0.5) print i2c.read_byte_data(addr, 0x93) # get Blue value time.sleep(0.5) print i2c.read_i2c_block_data(addr, 0x90, 3) # get RGB time.sleep(0.5) i2c.write_i2c_block_data(addr, 0x0A, RGB) # set all RGB time.sleep(0.5) print i2c.read_i2c_block_data(addr, 0x90, 3) # get all RGB time.sleep(0.5) print i2c.read_i2c_block_data(addr, 0x10, 3) # force error time.sleep(0.5)
  • 16. The Python ResultsPython 2.7.9 results. >>> 8 23.95 6.97 12 123 234 [12, 123, 234] [20, 200, 128] [0, 255, 255] >>> No event for write_quick() Got back the slave Address. Got the simulated temperature Got the simulated light level Set and read back Red channel Set and read back Green channel Set and read back Blue channel Got back RGB values as a list. Set new RGB values from a list Read back the RGB values as a list Forced a read error by sending wrong command. RGB = [20,200,128] i2c.write_quick(addr) # no data expected back print i2c.read_byte(addr) # expect the slave address print i2c.read_word_data(addr,0x81)/100.0 # temperature print i2c.read_word_data(addr,0x82)/100.0 # light level i2c.write_byte_data(addr, 0x0B, 12) # write Red value print i2c.read_byte_data(addr, 0x91) # get Red value i2c.write_byte_data(addr, 0x0C, 123) # write Green value print i2c.read_byte_data(addr, 0x92) # get Green value i2c.write_byte_data(addr, 0x0D, 234) # write Blue value print i2c.read_byte_data(addr, 0x93) # get Blue value print i2c.read_i2c_block_data(addr, 0x90, 3) # get RGB i2c.write_i2c_block_data(addr, 0x0A, RGB) # set all RGB print i2c.read_i2c_block_data(addr, 0x90, 3) # get all RGB print i2c.read_i2c_block_data(addr, 0x10, 3) # force error
  • 17. Instructions in Detail Master (Rpi, Python) Slave (Arduino Bus.write_quick(slave) Used to check presence, or trigger event in slave without data transfer. Wire.onReceive() event triggered, but no data is sent. Bytes received: 0. Bytes returned: 0. Bus.write_byte(slave, data) Can be used to instruct the slave to do any of up to 255 different actions, or to place this byte in one predefined byte variable. Wire.onReceive() event triggered. Single byte received. Bytes received: 1. Bytes returned: 0. ByteValue = Bus.read_byte(addr) Read slave status or a single predefined value Wire.onRequest() event triggered only. No data received. Slave must return one defined byte. Bytes received: 0. Bytes returned: 1. Bus.write_byte_data(addr, command, byteValue) Send slave some information to accompany a command. Wire.onReceive() event triggered. Two bytes sent. First byte is a command, second byte is the byte data to accompany it. Bytes received: 2. Bytes returned: 0. ByteValue = Bus.read_byte_data(addr, command) Interrogate a slave about a specific piece of information Wire.onReceive event triggered. One byte sent, a command for which byte is requested from slave. Wire.onRequest() then triggered, and one byte to be returned. Bytes received: 1. Bytes returned: 1
  • 18. Instructions in Detail Master (Rpi, Python) Slave (Arduino Bus.write_word_data(addr, command, integerVal) Send slave extra information accompanying a specific command Wire.onReceive() event triggered, three bytes send. First byte is command, second is LSB, third is MSB of integer. Bytes received: 3. Bytes returned: 0. WordValue = Bus.read_word_data(addr, command) Retrieve two bytes, first LSB, then MSB of an integer. Python knows to rebuild the integer. Retrieve integer data from slave. Wire.onReceive() event triggered. Single byte received, a command. Wire.onRequest() event triggered, slave must send back two bytes, first LSB, then MSB, of an integer. Bytes received: 1. Bytes returned: 2. Bus.write_block_data(addr, command, [list of bytes]) Sending unstructured data. Wire.onReceive() event triggered. Several bytes sent. First byte is command, second is number of following bytes, remainder of bytes must be processes according to interface list. Bytes received: > 2. Bytes returned: 0. Bus.write_i2c_block_data(addr, command, [list of bytes]) Use this to fill a table of related bytes quickly. Wire.onReceive() event triggered. Several bytes sent. First byte is a command, remaining bytes to be processed according to interface. Bytes received: > 1. Bytes returned: 0. ByteList = Bus.read_i2c_block_data(addr, command) Use this to read a table of related bytes quickly Wire.onReceive event triggered. One byte sent, a command for which byte is requested from slave. Wire.onRequest() then triggered, requested bytes returned as per interface list. Bytes received: 1. Bytes returned: > 1
  • 19. Instructions in Detail Master (Rpi, Python) Slave (Arduino List = bus.read_block_data(addr, command, bytes) will fail. Always returns the empty list. Do not use this function. Wire.onReceive() event triggered, two bytes send. First byte is command, second is number of bytes to return. OnRequest() event is triggered, sending back the correct number of bytes Bytes received: 2. Bytes returned: > 1. Bus.block_process_call(addr, command, [vals]) Following the protocol, it reads the correct number of bytes sent back, but random data appears in the list returned. Do not use. Wire.onReceive() event triggered. Several bytes received, first command, then count of bytes in [vals], then vals. Wire.onRequest() triggered, return first count, then number of bytes Bytes received: > 2. Bytes returned: > 2. process_call(addr, command, val) does sent the integer 'val', but does not trigger the interrupt to return data, so it returns the empty list Wire.onReceive() event triggered. Three bytes sent. First byte is command, second is LSB and last is MSB. SMBus Specification is to return two byte integer, but onRequest() event never triggered. Bytes received: 3. Bytes returned: n/a.
  • 20. Conclusions Communication over I2C is quite simple to implement using the SMBus library on the Raspberry Pi, and the Wire.h library on the Arduino.. Knowing what each SMBus Write and Read instruction sends to the Arduino and what data the Arduino is expected to send back is crucial to successful implementation of the I2C/SMBus protocol. Before coding, have a clear Interface Specification with a list of commands to be sent to the Arduino, and clear instructions of what should happen with the data sent and how to return requested data. It is also important to specify the reaction to bad data. The SMBus protocol document can be found at http://smbus.org/specs/smbus20.pdf The linux Python implementation document can be found at https://www.kernel.org/doc/Documentation/i2c/smb us-protocol Some of the SMBus protocol is not fully programmed in the existing SMBus python libraries, even though the functions are available to include in the program. These functions do not appear to work with the arduino: ● read_block_data(addr, command, bytes) ● block_process_call(addr, command, [vals]) ● process_call(addr, command, val) All the other functions appear to operate according to the specification. This work is licensed under the Creative Commons Attribution- ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/b y-sa/4.0/. Compiled by Mike Ochtman. Find me at https://za.linkedin.com/in/mikeochtman