8 Communicating Using I2C and SPI
8 Communicating Using I2C and SPI
13.0 Introduction
7KH,&,QWHU,QWHJUDWHG&LUFXLWDQG63,6HULDO3HULSKHUDO,QWHUIDFHVWDQGDUGVZHUH
FUHDWHGWRSURYLGHVLPSOHZD\VIRUGLJLWDOLQIRUPDWLRQWREHWUDQVIHUUHGEHWZHHQVHQVRUV
DQGPLFURFRQWUROOHUVVXFKDV$UGXLQR$UGXLQROLEUDULHVIRUERWK,&DQG63,PDNHLW
HDV\IRU\RXWRXVHERWKRIWKHVHSURWRFROV
7KH FKRLFH EHWZHHQ ,& DQG 63, LV XVXDOO\ GHWHUPLQHG E\ WKH GHYLFHV \RX ZDQW WR
FRQQHFW6RPHGHYLFHVSURYLGHERWKVWDQGDUGVEXWXVXDOO\DGHYLFHRUFKLSVXSSRUWV
RQHRUWKHRWKHU
,&KDVWKHDGYDQWDJHWKDWLWRQO\QHHGVWZRVLJQDOFRQQHFWLRQVWR$UGXLQRXVLQJ
PXOWLSOHGHYLFHVRQWKHWZRFRQQHFWLRQVLVIDLUO\HDV\DQG\RXJHWDFNQRZOHGJPHQW
WKDWVLJQDOVKDYHEHHQFRUUHFWO\UHFHLYHG7KHGLVDGYDQWDJHVDUHWKDWWKHGDWDUDWHLV
VORZHUWKDQ63,DQGGDWDFDQRQO\EHWUDYHOLQJLQRQHGLUHFWLRQDWDWLPHORZHULQJWKH
GDWDUDWHHYHQPRUHLIWZRZD\FRPPXQLFDWLRQLVQHHGHG,WLVDOVRQHFHVVDU\WRFRQQHFW
SXOOXSUHVLVWRUVWRWKHFRQQHFWLRQVWRHQVXUHUHOLDEOHWUDQVPLVVLRQRIVLJQDOVVHHWKH
LQWURGXFWLRQWR&KDSWHUIRUPRUHRQSXOOXSV
7KHDGYDQWDJHVRI63,DUHWKDWLWUXQVDWDKLJKHUGDWDUDWHDQGLWKDVVHSDUDWHLQSXW
DQGRXWSXWFRQQHFWLRQVVRLWFDQVHQGDQGUHFHLYHDWWKHVDPHWLPH,WXVHVRQHDGGL
WLRQDOOLQHSHUGHYLFHWRVHOHFWWKHDFWLYHGHYLFHVRPRUHFRQQHFWLRQVDUHUHTXLUHGLI
\RXKDYHPDQ\GHYLFHVWRFRQQHFW
0RVW$UGXLQRSURMHFWVXVH63,GHYLFHVIRUKLJKGDWDUDWHDSSOLFDWLRQVVXFKDV(WKHUQHW
DQGPHPRU\FDUGVZLWKMXVWDVLQJOHGHYLFHDWWDFKHG,&LVPRUHW\SLFDOO\XVHGZLWK
VHQVRUVWKDWGRQWQHHGWRVHQGDORWRIGDWD
7KLVFKDSWHUVKRZVKRZWRXVH,&DQG63,WRFRQQHFWWRFRPPRQGHYLFHV,WDOVR
VKRZVKRZWRFRQQHFWWZRRUPRUH$UGXLQRERDUGVWRJHWKHUXVLQJ,&IRUPXOWLERDUG
DSSOLFDWLRQV
389
I2C
7KHWZRFRQQHFWLRQVIRUWKH,&EXVDUHFDOOHG6&/DQG6'$7KHVHDUHDYDLODEOHRQ
DVWDQGDUG$UGXLQRERDUGXVLQJDQDORJSLQIRU6&/ZKLFKSURYLGHVDFORFNVLJQDO
DQGDQDORJSLQIRU6'/ZKLFKLVIRUWUDQVIHURIGDWDRQWKH0HJDXVHGLJLWDOSLQ
IRU6'$DQGSLQIRU6&/2QHGHYLFHRQWKH,&EXVLVFRQVLGHUHGWKHPDVWHUGHYLFH
,WVMRELVWRFRRUGLQDWHWKHWUDQVIHURILQIRUPDWLRQEHWZHHQWKHRWKHUGHYLFHVVODYHV
WKDWDUHDWWDFKHG7KHUHPXVWEHRQO\RQHPDVWHUDQGLQPRVWFDVHVWKH$UGXLQRLVWKH
PDVWHUFRQWUROOLQJWKHRWKHUFKLSVDWWDFKHGWRLW)LJXUHGHSLFWVDQ,&PDVWHU
ZLWKPXOWLSOH,&VODYHV
)LJXUH$Q,&PDVWHUZLWKRQHRUPRUH,&VODYHV
,&GHYLFHVQHHGDFRPPRQJURXQGWRFRPPXQLFDWH7KH$UGXLQR*QG
SLQPXVWEHFRQQHFWHGWRJURXQGRQHDFK,&GHYLFH
6ODYHGHYLFHVDUHLGHQWLILHGE\WKHLUDGGUHVVQXPEHU(DFKVODYHPXVWKDYHDXQLTXH
DGGUHVV6RPH,&GHYLFHVKDYHDIL[HGDGGUHVVDQH[DPSOHLVWKHQXQFKXFNLQ5HF
LSHZKLOHRWKHUVDOORZ\RXWRFRQILJXUHWKHLUDGGUHVVE\VHWWLQJSLQVKLJKRUORZ
VHH5HFLSHRUE\VHQGLQJLQLWLDOL]DWLRQFRPPDQGV
$UGXLQRXVHVELWYDOXHVWRVSHFLI\,&DGGUHVVHV6RPHGHYLFHGDWD
VKHHWVXVHELWDGGUHVVYDOXHV,I\RXUVGRHVGLYLGHWKDWYDOXHE\WR
JHWWKHFRUUHFWELWYDOXH
,&DQG63,RQO\GHILQHKRZFRPPXQLFDWLRQWDNHVSODFHEHWZHHQGHYLFHVWKHPHV
VDJHVWKDWQHHGWREHVHQWGHSHQGRQHDFKLQGLYLGXDOGHYLFHDQGZKDWLWGRHV<RXZLOO
QHHGWRFRQVXOWWKHGDWDVKHHWIRU\RXUGHYLFHWRGHWHUPLQHZKDWFRPPDQGVDUHUHTXLUHG
WRJHWLWWRIXQFWLRQDQGZKDWGDWDLVUHTXLUHGRUUHWXUQHG
SPI
5HFHQW$UGXLQRUHOHDVHVIURPUHOHDVHLQFOXGHDOLEUDU\WKDWDOORZVFRPPXQLFD
WLRQZLWK63,GHYLFHV63,KDVVHSDUDWHLQSXWODEHOHG026,DQGRXWSXWODEHOHG
0,62OLQHVDQGDFORFNOLQH7KHVHWKUHHOLQHVDUHFRQQHFWHGWRWKHUHVSHFWLYHOLQHV
RQRQHRUPRUHVODYHV6ODYHVDUHLGHQWLILHGE\VLJQDOLQJZLWKWKH6ODYH6HOHFW66OLQH
)LJXUHVKRZVWKH63,FRQQHFWLRQV
)LJXUH6LJQDOFRQQHFWLRQVIRU63,PDVWHUDQGVODYHV
7KHSLQQXPEHUVWRXVHIRUWKH63,SLQVDUHVKRZQLQ7DEOH
7DEOH$UGXLQRGLJLWDOSLQVXVHGIRU63,
SPI signal Standard Arduino board Arduino Mega
SCLK (clock) 13 52
MISO (data out) 12 50
MOSI (data in) 11 51
SS (slave select) 10 53
See Also
$SSOLFDWLRQV QRWH FRPSDULQJ ,& WR 63, KWWSZZZPD[LPLFFRPDSSQRWHVLQGH[
PYSLG
$UGXLQR:LUHOLEUDU\UHIHUHQFHKWWSZZZDUGXLQRFFHQ5HIHUHQFH:LUH
$UGXLQR63,OLEUDU\UHIHUHQFHKWWSZZZDUGXLQRFFSOD\JURXQG&RGH6SL
Solution
%OLQN0LVDSUHDVVHPEOHGFRORU/('PRGXOHWKDWJHWV\RXVWDUWHGZLWK,&ZLWKPLQ
LPDOIXVV
,QVHUWWKH%OLQN0SLQVRQWRDQDORJSLQVWKURXJKDVVKRZQLQ)LJXUH
)LJXUH%OLQN0PRGXOHSOXJJHGLQWRDQDORJSLQV
7KHIROORZLQJVNHWFKLVEDVHGRQ5HFLSHEXWLQVWHDGRIGLUHFWO\FRQWUROOLQJWKH
YROWDJHRQWKHUHGJUHHQDQGEOXH/('HOHPHQWV,&FRPPDQGVDUHVHQWWRWKH%OLQN0
PRGXOHZLWKLQVWUXFWLRQVWRSURGXFHDFRORUEDVHGRQWKHUHGJUHHQDQGEOXHOHYHOV
7KH hueToRGBIXQFWLRQLVWKHVDPHDVZKDWZHXVHGLQ5HFLSHDQGLVQRWUHSHDWHG
KHUHVRFRS\WKHIXQFWLRQLQWRWKHERWWRPRI\RXUVNHWFKEHIRUHFRPSLOLQJWKLVERRNV
ZHEVLWHKDVWKHFRPSOHWHVNHWFK
/*
* BlinkM sketch
* This sketch continuously fades through the color wheel
*/
#include <Wire.h>
void setup()
{
Wire.begin(); // set up Arduino I2C support
void loop()
{
int brightness = 255; // 255 is maximum brightness
hueToRGB( color, brightness); // call function to convert hue to RGB
// write the RGB values to BlinkM
7KHIROORZLQJVNHWFKXVHVDIXQFWLRQQDPHG hueToRGBWKDWZDVLQWURGXFHGLQ&KDS
WHUWRFRQYHUWDQLQWHJHUYDOXHLQWRLWVUHGJUHHQDQGEOXHFRPSRQHQWV
// function to convert a color to its Red, Green, and Blue components.
void hueToRGB( int hue, int brightness)
{
unsigned int scaledHue = (hue * 6);
unsigned int segment = scaledHue / 256; // segment 0 to 5 around color wheel
unsigned int segmentOffset = scaledHue - (segment * 256); // position within
the segment
switch(segment ) {
case 0: // red
R = brightness;
G = next;
B = complement;
break;
Discussion
7KH:LUHOLEUDU\LVDGGHGWRWKHVNHWFKXVLQJWKHIROORZLQJ
#include <Wire.h>
)RUPRUHGHWDLOVDERXWXVLQJOLEUDULHVVHH&KDSWHU
7KHFRGHLQsetupLQLWLDOL]HVWKH:LUHOLEUDU\DQGWKHKDUGZDUHLQWKH$UGXLQRWRGULYH
6&$DQG6'/RQDQDORJSLQVDQGDQGWXUQVRQWKHSLQVXVHGWRSRZHUWKH%OLQN0
PRGXOH
7KHloopFRGHFDOOVWKHIXQFWLRQhueToRGBWRFDOFXODWHWKHUHGJUHHQDQGEOXHYDOXHV
IRUWKHFRORU
7KH5*DQG%YDOXHVDUHVHQWWR%OLQN0XVLQJWKLVVHTXHQFH
Wire.beginTransmission(address); // start an I2C message to the BlinkM address
Wire.send('c'); // 'c' is a command to fade to the color that follows
Wire.send(R); // value for red
Wire.send(B); // value for blue
Wire.send(G); // value for green
Wire.endTransmission(); // complete the I2C message
$OOGDWDWUDQVPLVVLRQWR,&GHYLFHVIROORZVWKLVSDWWHUQbeginTransmissionDQXPEHU
RIsendPHVVDJHVDQGendTransmission
)LJXUH0XOWLSOH%OLQN0PRGXOHVFRQQHFWHGWRJHWKHU
(DFK %OLQN0 FDQ GUDZ XS WR P$ VR LI \RXUH XVLQJ PRUH WKDQ D
KDQGIXOWKH\VKRXOGEHSRZHUHGXVLQJDQH[WHUQDOVXSSO\
<RXQHHGWRVHWHDFK%OLQN0WRDGLIIHUHQW,&DGGUHVVDQG\RXFDQXVHWKH%OLQN0
7HVWHUVNHWFKWKDWFRPHVZLWKWKH%OLQN0H[DPSOHVGRZQORDGDEOHIURPKWWSWKLQJP
FRPILOHDGPLQWKLQJPGRZQORDGV%OLQN0B([DPSOHV]LS
&RPSLOHDQGXSORDGWKH%OLQN07HVWHUVNHWFK3OXJHDFK%OLQN0PRGXOHLQWR$UGXLQR
RQHDWDWLPHVZLWFKRIISRZHUZKHQFRQQHFWLQJDQGGLVFRQQHFWLQJWKHPRGXOHV8VH
WKH%OLQN07HVWHUVFDQFRPPDQGsWRGLVSOD\WKHFXUUHQWDGGUHVVDQGXVHWKHAFRP
PDQGWRVHWHDFKPRGXOHWRDGLIIHUHQWDGGUHVV
$IWHUDOOWKH%OLQN0VKDYHDXQLTXHDGGUHVV\RXFDQVHWWKH addressYDULDEOHLQWKH
SUHFHGLQJVNHWFKWRWKHDGGUHVVRIWKH%OLQN0\RXZDQWWRFRQWURO7KLVH[DPSOHDV
VXPHVDGGUHVVHVIURPWR
#include <Wire.h>
void setup()
{
Wire.begin(); // set up Arduino I2C support
void loop()
{
int brightness = 255; // 255 is maximum brightness
hueToRGB( color, brightness); // call function to convert hue to RGB
// write the RGB values to each BlinkM
setColor(addressA, R,G,B);
setColor(addressB, G,B,R);
setColor(addressA, B,R,G);
See Also
7KH%OLQN08VHU0DQXDOKWWSWKLQJPFRPILOHDGPLQWKLQJPGRZQORDGV%OLQN0BGD
WDVKHHWSGI
([DPSOH$UGXLQRVNHWFKHVKWWSWKLQJPFRPILOHDGPLQWKLQJPGRZQORDGV%OLQN0B([
DPSOHV]LS
Solution
7KHQXQFKXFNXVHVDSURSULHWDU\SOXJ,I\RXGRQWZDQWWRXVH\RXUQXQFKXFNZLWK
\RXU:LLDJDLQ\RXFDQFXWWKHOHDGWRFRQQHFWLW$OWHUQDWLYHO\LWLVSRVVLEOHWRXVHD
VPDOOSLHFHRIPDWUL[ERDUGWRPDNHWKHFRQQHFWLRQVLQWKHSOXJLI\RXDUHFDUHIXOWKH
SLQRXWVDUHVKRZQLQ)LJXUHRU\RXFDQEX\DQDGDSWHUPDGHE\7RGERWKWWS
WRGERWFRPEORJZLLFKXFNZLLQXQFKXFNDGDSWHUDYDLODEOH
)LJXUH&RQQHFWLQJDQXQFKXFNWR$UGXLQR
byte accx;
void setup()
{
Serial.begin(9600);
nunchuck_setpowerpins();
nunchuck_init();
}
void loop()
{
nunchuck_get_data();
accx = nunchuck_accelx();
if( accx >= 75 && accx <= 185)
{
// map returns a value from 0 to 63 for values from 75 to 185
byte y = map(accx, 75, 185, 0, 63);
Serial.print(y);
}
delay(100); // the time in milliseconds between redraws
}
Discussion
,&LVRIWHQXVHGLQFRPPHUFLDOSURGXFWVVXFKDVWKHQXQFKXFNIRUFRPPXQLFDWLRQ
EHWZHHQGHYLFHV7KHUHDUHQRRIILFLDOGDWDVKHHWVIRUWKLVGHYLFHEXWWKHQXQFKXFN
VLJQDOLQJ ZDV DQDO\]HG UHYHUVH HQJLQHHUHG WR GHWHUPLQH WKH FRPPDQGV QHHGHG WR
FRPPXQLFDWHZLWKLW
<RXFDQXVHWKHIROORZLQJ3URFHVVLQJVNHWFKWRGLVSOD\DOLQHWKDWIROORZVWKHQXQFKXFN
PRYHPHQWDVVKRZQLQ)LJXUHVHH&KDSWHUIRUPRUHRQXVLQJ3URFHVVLQJWR
UHFHLYH$UGXLQRVHULDOGDWDDOVRVHH&KDSWHUIRUDGYLFHRQVHWWLQJXSDQGXVLQJ3UR
FHVVLQJZLWK$UGXLQR
// Processing sketch to draw line that follows nunchuck data
import processing.serial.*;
void setup()
{
void draw()
{
if ( myPort.available() > 0) { // If data is available,
int y = myPort.read(); // read it and store it in val
background(255); // Set background to white
line(0,63-y,127,y); // draw the line
}
}
)LJXUH1XQFKXFNPRYHPHQWUHSUHVHQWHGE\WLOWHGOLQHLQ3URFHVVLQJ
7KHVNHWFKLQFOXGHVWKH:LUHOLEUDU\IRU,&FRPPXQLFDWLRQDQGWKH nunchuck_funcs
FRGHIURPWKHHDUOLHUOLQN
#include <Wire.h> // initialize wire
#include "nunchuck_funcs.h"
:LUHKLVWKH,&OLEUDU\WKDWLVLQFOXGHGZLWKWKH$UGXLQRUHOHDVH
QXQFKXFNBIXQFVKLVWKHQDPHRIWKHOLEUDU\IRUFRPPXQLFDWLQJZLWKWKHQXQFKXFN
XVLQJ,&
7KHOLEUDU\KLGHVWKH,&LQWHUIDFHEXWKHUHLVDQRYHUYLHZRIKRZWKLVOLEUDU\XVHV,&
7KH nunchuck_setpowerpinsIXQFWLRQLVXVHGWRSURYLGHSRZHUWKURXJKDQDORJSLQV
DQG7KLVLVRQO\QHHGHGLIWKHQXQFKXFNDGDSWHULVSURYLGLQJWKHSRZHUVRXUFH7KH
FRGHVHWVWKHVHSLQVDVRXWSXWVZLWKSLQ LOWDQGSLQHIGH8VLQJGLJLWDOSLQVDVD
SRZHUVRXUFHLVQRWXVXDOO\UHFRPPHQGHGXQOHVV\RXDUHFHUWDLQDVZLWKWKHQXQ
FKXFNWKDWWKHGHYLFHEHLQJSRZHUHGZLOOQRWH[FHHGDSLQVPD[LPXPFXUUHQWFDSD
ELOLW\P$VHH&KDSWHU
,&FRPPXQLFDWLRQVWDUWVZLWKWire.begin(),QWKLVH[DPSOH$UGXLQRDVWKHPDVWHU
LVUHVSRQVLEOHIRULQLWLDOL]LQJWKHGHVLUHGVODYHGHYLFHWKHQXQFKXFNRQDGGUHVV[
7KHIROORZLQJOLQHWHOOVWKH:LUHOLEUDU\WRSUHSDUHWRVHQGDPHVVDJHWRWKHGHYLFHDW
KH[DGHFLPDODGGUHVV[
beginTransmission(0x52);
Wire.sendSXWVWKHJLYHQYDOXHVLQWRDEXIIHUZLWKLQWKH:LUHOLEUDU\ZKHUHGDWDLVVWRUHG
XQWLOWire.endTransmissionLVFDOOHGWRDFWXDOO\GRWKHVHQGLQJ
nunchuck_get_dataLVXVHGWRUHFHLYHGDWDIURPWKHQXQFKXFN
// returns 1 on successful read. returns 0 on failure
int nunchuck_get_data()
{
int cnt=0;
Wire.requestFrom (0x52, 6);// request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
nunchuck_buf[cnt] = nunchuck_decode_byte(Wire.receive());
cnt++;
}
nunchuck_send_request(); // send request for next data payload
// If we received the 6 bytes, then go print them
if (cnt >= 5) {
return 1; // success
}
return 0; //failure
}
7KLVXVHVWKH:LUHOLEUDU\ requestFromIXQFWLRQWRJHWVL[E\WHVRIGDWDIURPGHYLFH
[WKHQXQFKXFN
Wire.available ZRUNV OLNH Serial.available VHH &KDSWHU WR LQGLFDWH KRZ PDQ\
E\WHVKDYHEHHQUHFHLYHGEXWRYHUWKH,&LQWHUIDFHUDWKHUWKDQWKHVHULDOLQWHUIDFH
,I GDWD LV DYDLODEOH LW LV UHDG XVLQJ Wire.receive DQG WKHQ GHFRGHG XVLQJ
nunchuck_decode_byte'HFRGLQJLVUHTXLUHGWRFRQYHUWWKHYDOXHVVHQWLQWRQXPEHUV
WKDWDUHXVDEOHE\\RXUVNHWFKDQGWKHVHDUHVWRUHGLQDEXIIHUQDPHGnunchuck_buf
$UHTXHVWLVVHQWIRUWKHQH[WVL[E\WHVRIGDWDVRWKDWLWZLOOEHUHDG\DQGZDLWLQJIRU
WKHQH[WFDOOWRJHWGDWD
accx = nunchuck_accelx();
7KHIXQFWLRQnunchuck_accelxLVXVHGWRJHWWKHYDOXHRIDFFHOHUDWLRQLQWKH[D[LVIURP
WKHQXQFKXFNDQGVWRUHLWLQWKHYDULDEOHaccx
Solution
7KLVVROXWLRQXVHVWKH:LUHOLEUDU\WRDFFHVVDQ57&,WXVHVWKHVDPHKDUGZDUHDVLQ
5HFLSH)LJXUHVKRZVWKHFRQQHFWLRQV
/*
* I2C_RTC sketch
* example code for using Wire library to access real-time clock
*
*/
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop()
{
Wire.beginTransmission(DS1307_CTRL_ID);
Wire.send(0x00);
Wire.endTransmission();
// request the 7 data fields (secs, min, hr, dow, date, mth, yr)
Wire.requestFrom(DS1307_CTRL_ID, NumberOfFields);
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(Hour);
printDigits(Minute);
printDigits(Second);
Serial.print(" ");
Serial.print(Day);
Serial.print(" ");
Serial.print(Month);
Serial.print(" ");
Serial.print(Year);
Serial.println();
// utility function for clock display: prints preceding colon and leading 0
void printDigits(int digits){
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
)LJXUH&RQQHFWLQJDUHDOWLPHFORFN
Discussion
$OWKRXJKWKLVUHFLSHXVHVWKHVDPHKDUGZDUHDVLQ5HFLSHLWDFFHVVHVWKHKDUGZDUH
WKURXJKH[SOLFLW,&FDOOVLQVWHDGRIWKURXJKDOLEUDU\VRWKDWWKHLQWHUDFWLRQEHWZHHQ
$UGXLQRDQGWKH,&FORFNFDQEHFOHDUO\VHHQ
7KHIROORZLQJOLQHLQLWLDOL]HVWKH57&
Wire.beginTransmission(DS1307_CTRL_ID);
Wire.send(0x00);
Wire.endTransmission();
7KHrequestFromPHWKRGRIWKH:LUHOLEUDU\LVXVHGWRUHTXHVWVHYHQWLPHILHOGVIURP
WKHFORFNDS1307_CTRL_IDLVWKHDGGUHVVLGHQWLILHURIWKHFORFN
Wire.requestFrom(DS1307_CTRL_ID, NumberOfFields);
7KH GDWH DQG WLPH YDOXHV DUH REWDLQHG E\ PDNLQJ VHYHQ FDOOV WR WKH Wire.receive
PHWKRG
bcd2dec(Wire.receive()
See Also
5HFLSHSURYLGHVGHWDLOVRQKRZWRVHWWKHWLPHRQWKHFORFN
Solution
7KLV UHFLSH XVHV WKH /& ,&HQDEOHG VHULDO ((3520 IURP 0LFURFKLS )LJ
XUHVKRZVWKHFRQQHFWLRQV
)LJXUH,&((3520FRQQHFWLRQV
7KLVUHFLSHSURYLGHVIXQFWLRQDOLW\VLPLODUWRWKH$UGXLQR((3520OLEUDU\VHH5HF
LSH EXW LW XVHV DQ H[WHUQDO ((3520 FRQQHFWHG XVLQJ ,& WR SURYLGH JUHDWO\
LQFUHDVHGVWRUDJHFDSDFLW\
void setup()
{
Serial.begin(9600);
Wire.begin();
void loop()
{
Discussion
7KLVUHFLSHVKRZVWKH/&ZKLFKKDV.RIPHPRU\DOWKRXJKWKHUHDUHVLPLODU
FKLSV ZLWK KLJKHU DQG ORZHU FDSDFLWLHV WKH PLFURFKLS OLQN LQ WKLV UHFLSHV 6HH $OVR
VHFWLRQKDVDFURVVUHIHUHQFH7KHFKLSVDGGUHVVLVVHWXVLQJWKHWKUHHSLQVPDUNHG
$WKURXJK$DQGLVLQWKHUDQJH[WR[DVVKRZQLQ7DEOH
7DEOH$GGUHVVYDOXHVIRU/&
A0 A1 A2 Address
Gnd Gnd Gnd 0x50
+5V Gnd Gnd 0x51
Gnd +5V Gnd 0x52
+5V +5V Gnd 0x53
Gnd Gnd +5V 0x54
+5V Gnd +5V 0x55
+5V +5V Gnd 0x56
+5V +5V +5V 0x57
8VHRIWKH:LUHOLEUDU\LQWKLVUHFLSHLVVLPLODUWRLWVXVHLQ5HFLSHVDQGVR
UHDGWKURXJKWKRVHIRUDQH[SODQDWLRQRIWKHFRGHWKDWLQLWLDOL]HVDQGUHTXHVWVGDWDIURP
DQ,&GHYLFH
7KH:LUHOLEUDU\FDQUHDGRUZULWHXSWRE\WHVLQDVLQJOHUHTXHVW
$WWHPSWLQJ WRUHDG RU ZULWH PRUHWKDQ WKLV FDQUHVXOWLQE\WHVEHLQJ
GLVFDUGHG
7KHSLQPDUNHG:3LVIRUVHWWLQJZULWHSURWHFWLRQ,WLVFRQQHFWHGWRJURXQGLQWKH
FLUFXLWKHUHWRHQDEOHWKH$UGXLQRWRZULWHWRPHPRU\&RQQHFWLQJLWWR9SUHYHQWV
DQ\ZULWHVIURPWDNLQJSODFH7KLVFRXOGEHXVHGWRZULWHSHUVLVWHQWGDWDWRPHPRU\
DQGWKHQSUHYHQWLWIURPEHLQJRYHUZULWWHQDFFLGHQWDOO\
See Also
7KH /& GDWD VKHHW KWWSZZPLFURFKLSFRPGRZQORDGVHQGHYLFHGRFQ
SGI
,I\RXQHHGWRVSHHGXSZULWHV\RXFDQUHSODFHWKHPVGHOD\ZLWKDVWDWXVFKHFNWR
GHWHUPLQHLIWKH((3520LVUHDG\WRZULWHDQHZE\WH6HHWKH$FNQRZOHGJH3ROOLQJ
WHFKQLTXHGHVFULEHGLQ6HFWLRQRIWKHGDWDVKHHW
$FURVVUHIHUHQFHRIVLPLODU,&((3520VZLWKDZLGHUDQJHRIFDSDFLWLHVLVDYDLODEOH
DWKWWSZZPLFURFKLSFRPGRZQORDGVHQ'HYLFH'RFGSGI
$VKLHOGLVDYDLODEOHWKDWFRPELQHVUHDGLQJWHPSHUDWXUHVWRULQJLQ((3520DQG
VHJPHQWGLVSOD\KWWSVWRUHJUDYLWHFKXVVHJPHQWVKLHOGKWPO
Solution
7KLVUHFLSHXVHVWKH703WHPSHUDWXUHVHQVRUIURP7H[DV,QVWUXPHQWV<RXFRQQHFW
DVLQJOH703DVVKRZQLQ)LJXUH
/*
* I2C_Temperature sketch
* I2C access the TMP75 digital Thermometer
*
*/
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(TMP75_ID);
Wire.send(1); // 1 is the configuration register
// set default configuration, see data sheet for significance of config bits
Wire.send(0);
Wire.endTransmission();
Wire.beginTransmission(TMP75_ID);
Wire.send(0); // set pointer register to 0 (this is the 12-bit temperature)
Wire.endTransmission();
void loop()
{
Wire.requestFrom(TMP75_ID, NumberOfFields);
tempHighByte = Wire.receive();
tempLowByte = Wire.receive();
Serial.print("Integer temperature is ");
)LJXUH703,&WKHUPRPHWHU
Discussion
$VZLWKDOOWKH,&GHYLFHVLQWKLVFKDSWHUVLJQDOLQJLVWKURXJKWKHWZRZLUH6&/DQG
6'$SLQV3RZHUDQGJURXQGQHHGWREHFRQQHFWHGWRWKHGHYLFHDVZHOOWRSRZHULW
SetupVHQGVGDWDWRFRQILJXUHWKHGHYLFHIRUQRUPDORSHUDWLRQWKHUHDUHDQXPEHURI
RSWLRQVIRUVSHFLDOL]HGDSSOLFDWLRQVLQWHUUXSWVSRZHUGRZQHWFEXWWKHYDOXHXVHG
KHUHLVIRUQRUPDOPRGHZLWKDSUHFLVLRQRI&
7RJHWWKHGHYLFHWRVHQGWKHWHPSHUDWXUHZLWKWKH$UGXLQRDVWKHPDVWHUWKHFRGH
LQloopWHOOVWKHVODYHDWWKHDGGUHVVJLYHQE\WKHFRQVWDQWTMP75_IDWKDWLWZDQWVWZR
E\WHVRIGDWD
Wire.requestFrom(TMP75_ID, NumberOfFields);
7KHILUVWE\WHLVWKHLQWHJHUYDOXHRIWKHWHPSHUDWXUHLQGHJUHHV&HOVLXV7KHVHFRQG
E\WHFRQWDLQVIRXUVLJQLILFDQWELWVLQGLFDWLQJWKHIUDFWLRQDOWHPSHUDWXUH
7KHWZRE\WHVDUHFRQYHUWHGWRDELWZRUGVHH&KDSWHUDQGWKHQVKLIWHGE\IRXU
WRIRUPWKHELWQXPEHU$VWKHILUVWIRXUELWVDUHWKHIUDFWLRQDOWHPSHUDWXUHWKHYDOXH
LVDJDLQVKLIWHGE\IRXUWRJHWWKHIORDWLQJSRLQWYDOXH
7KH713FDQEHFRQILJXUHGIRUHLJKWGLIIHUHQWDGGUHVVHVDOORZLQJHLJKWGHYLFHVWR
EHFRQQHFWHGWRWKHVDPHEXVVHH)LJXUH7KLVVNHWFKXVHV,&DGGUHVV[
WKH703DGGUHVVSLQVODEHOHG$FRQQHFWHGWR9DQG$DQG$FRQQHFWHGWR
*QG7DEOHVKRZVWKHFRQQHFWLRQVIRUWKHHLJKWDGGUHVVHV
)LJXUH0XOWLSOHGHYLFHVZLWK6'$DQG6&/FRQQHFWHGLQSDUDOOHOZLWKGLIIHUHQWDGGUHVVHV
7DEOH$GGUHVVYDOXHVIRU703
A0 A1 A2 Address
Gnd Gnd Gnd 0x48
+5V Gnd Gnd 0x49
Gnd +5V Gnd 0x4A
+5V +5V Gnd 0x4B
Gnd Gnd +5V 0x4C
+5V Gnd +5V 0x4D
+5V +5V Gnd 0x4E
+5V +5V +5V 0x4F
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(TMP75_ID+i);
Wire.send(0); // set pointer register to 0 (this is the 12-bit temperature)
Wire.endTransmission();
}
}
void loop()
{
for(int i=0; i < NumberOfDevices; i++)
{
byte id = TMP75_ID + i; // address IDs are consecutive
Wire.requestFrom(id, NumberOfFields);
tempHighByte = Wire.receive();
tempLowByte = Wire.receive();
Serial.print(id,HEX); // print the device address
Serial.print(": integer temperature is ");
Serial.print(tempHighByte, DEC);
<RXFDQDGGPRUHGHYLFHVE\FKDQJLQJWKHFRQVWDQW NumberOfDevicesDQGZLULQJWKH
GHYLFHVWRXVHDGGUHVVHVWKDWDUHFRQVHFXWLYHLQWKLVH[DPSOHVWDUWLQJIURP[
See Also
7KH703GDWDVKHHWKWWSIRFXVWLFRPGRFVSURGIROGHUVSULQWWPSKWPO
6HH5HFLSHIRUPRUHRQWKHwordIXQFWLRQ
Solution
7KLVUHFLSHXVHVWKH*UDYLWHFKVHJPHQWGLVSOD\VKLHOGWKDWKDVWKH6$$,&WR
VHJPHQWGULYHUIURP3KLOLSVVHH)LJXUH
)LJXUH*UDYLWHFK,&VKLHOG
#include <Wire.h>
int segment,decade;
void setup() {
Serial.begin(9600);
Wire.begin(); /* Join I2C bus */
Wire.beginTransmission(LedDrive);
Wire.send(0);
Wire.send(B01000111); // show digits 1 through 4, use maximum drive current
Wire.endTransmission();
}
void loop()
{
for (segment = 0; segment < 8; segment++)
{
Wire.beginTransmission(LedDrive);
Wire.send(1);
for (decade = 0 ; decade < 4; decade++)
{
byte bitValue = bit(segment);
Wire.send(bitValue);
}
Wire.endTransmission();
delay (250);
}
}
Discussion
7KH6$$FKLSXVLQJDGGUHVV[LVLQLWLDOL]HGLQsetup7KHYDOXHXVHGFRQILJ
XUHVWKHFKLSWRGLVSOD\IRXUGLJLWVXVLQJPD[LPXPGULYHFXUUHQWVHHWKHGDWDVKHHW
VHFWLRQRQFRQWUROELWVIRUFRQILJXUDWLRQGHWDLOV
7KH loopFRGHOLJKWVHDFKVHJPHQWLQVHTXHQFHRQDOOWKHGLJLWV7KH Wire.send(1);
FRPPDQGWHOOVWKHFKLSWKDWWKHQH[WUHFHLYHGE\WHZLOOGULYHWKHILUVWGLJLWDQGVXEVH
TXHQWE\WHVZLOOGULYHVHTXHQWLDOGLJLWV
,QLWLDOO\DYDOXHRI1LVVHQWIRXUWLPHVDQGWKHFKLSOLJKWVWKH$WRSVHJPHQWRQDOO
IRXUGLJLWV6HH&KDSWHUIRUPRUHRQXVLQJWKHbitIXQFWLRQ
7KHYDOXHRIsegmentLVLQFUHPHQWHGLQWKHforORRSDQGWKLVVKLIWVWKHbitValueWROLJKW
WKHQH[W/('VHJPHQWLQVHTXHQFH
13.6 Driving Four 7-Segment LEDs Using Only Two Wires | 413
(DFKELWSRVLWLRQFRUUHVSRQGVWRDVHJPHQWRIWKHGLJLW7KHVHELWSRVLWLRQYDOXHVFDQ
EHFRPELQHGWRFUHDWHDQXPEHUWKDWZLOOWXUQRQPRUHWKDQRQHVHJPHQW
7KH IROORZLQJ VNHWFK ZLOO GLVSOD\ D FRXQW IURP WR 7KH DUUD\ FDOOHG
lookup[10]FRQWDLQVWKHYDOXHVQHHGHGWRFUHDWHWKHQXPHUDOVIURPWRLQDVHJPHQW
#include <Wire.h>
int count;
void setup()
{
Wire.begin(); // join I2C bus (address optional for master)
// delay(500);
}
void loop()
{
Wire.beginTransmission(LedDrive);
Wire.send(0);
Wire.send(B01000111); // init the 7-segment driver - see data sheet
Wire.endTransmission();
7KHIROORZLQJVWDWHPHQWFKHFNVLIWKHYDOXHLV0DQGLWVQRWWKHILUVWOHDVWVLJQLILFDQW
GLJLW
if(number == 0 && i > 0)
,IVRLWVHQGVDYDOXHRI0ZKLFKWXUQVRIIDOOVHJPHQWVIRUWKDWGLJLW7KLVVXSSUHVVHV
OHDGLQJ]HURVEXWLWGLVSOD\VDVLQJOH]HURLIWKHQXPEHUSDVVHGWRWKHIXQFWLRQZDV0
See Also
6$$GDWDVKHHWKWWSZZZQ[SFRPGRFXPHQWVGDWDBVKHHW6$$B&19SGI
$VKLHOGLVDYDLODEOHWKDWFRPELQHVUHDGLQJWHPSHUDWXUHVWRULQJLQ((3520DQG
VHJPHQWGLVSOD\KWWSVWRUHJUDYLWHFKXVVHJPHQWVKLHOGKWPO
13.6 Driving Four 7-Segment LEDs Using Only Two Wires | 415
13.7 Integrating an I2C Port Expander
Problem
<RXZDQWWRXVHPRUHLQSXWRXWSXWSRUWVWKDQ\RXUERDUGSURYLGHV
Solution
<RXFDQXVHDQH[WHUQDOSRUWH[SDQGHUVXFKDVWKH3&)$ZKLFKKDVHLJKWLQSXW
RXWSXWSLQVWKDWFDQEHFRQWUROOHGXVLQJ,&7KHVNHWFKFUHDWHVDEDUJUDSKZLWKHLJKW
/('V)LJXUHVKRZVWKHFRQQHFWLRQV
)LJXUH3&)$SRUWH[SDQGHUGULYLQJHLJKW/('V
7KHVNHWFKKDVWKHVDPHIXQFWLRQDOLW\DVGHVFULEHGLQ5HFLSHEXWLWXVHVWKH,&
SRUWH[SDQGHUWRGULYHWKH/('VVRWKDWRQO\WZRSLQVDUHUHTXLUHG
/*
* I2C_7segment
* Uses I2C port to drive a bar graph
* Turns on a series of LEDs proportional to a value of an analog sensor.
* see Recipe 7.5
*/
#include <Wire.h>
void setup()
{
Wire.begin(); // set up Arduino I2C support
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(analogInPin); // read the analog in value
ledLevel = map(sensorValue, 0, 1023, 0, NbrLEDs); // map to number of LEDs
for (int led = 0; led < NbrLEDs; led++)
{
if (led < ledLevel ) {
bitWrite(ledBits,led, HIGH); // turn on LED if less than the level
}
else {
bitWrite(ledBits,led, LOW); // turn off LED if higher than the level
}
// send the value to I2C
Wire.beginTransmission(address);
Wire.send(ledBits);
Wire.endTransmission();
}
delay(100);
}
Discussion
7KHUHVLVWRUVVKRXOGEHRKPVRUPRUHVHH&KDSWHUIRULQIRUPDWLRQRQVHOHFWLQJ
UHVLVWRUV
7KH3&)$KDVDORZHUFDSDFLW\IRUGULYLQJ/('VWKDQ$UGXLQR,I
\RX QHHG PRUH FDSDFLW\ UHIHU WR WKH GDWD VKHHW IRU GHWDLOV VHH 5HF
LSHIRUDPRUHDSSURSULDWHGHYLFH
<RXFDQFKDQJHWKHDGGUHVVE\FKDQJLQJWKHFRQQHFWLRQVRIWKHSLQVPDUNHG$
$DQG$DVVKRZQLQ7DEOH
7RXVHWKHSRUWH[SDQGHUIRULQSXWUHDGDE\WHIURPWKHH[SDQGHUDVIROORZV
Wire.requestFrom(address, 1);
if(Wire.available())
{
data = Wire.receive();
Serial.println(data,BIN);
}
See Also
3&)GDWDVKHHWKWWSZZZQ[SFRPGRFXPHQWVGDWDBVKHHW3&)SGI
Solution
7KLV UHFLSH SURYLGHV VLPLODU IXQFWLRQDOLW\ WR 5HFLSH EXW LW RQO\ UHTXLUHV WKUHH
RXWSXWSLQV7KHWH[WKHUHH[SODLQVWKH63,FRPPDQGVXVHGWRFRPPXQLFDWHZLWKWKH
0$;GHYLFH)LJXUHVKRZVWKHFRQQHFWLRQV
*
SPI_Max7221_0019
*/
#include <SPI.h>
const int slaveSelect = 10; //pin used to enable the active slave
int count = 0;
void setup()
{
SPI.begin(); // initialize SPI
pinMode(slaveSelect, OUTPUT);
digitalWrite(slaveSelect,LOW); //select slave
// prepare the 7221 to display 7-segment data - see data sheet
sendCommand(12,1); // normal mode (default is shutdown mode);
sendCommand(15,0); // Display test off
sendCommand(10,8); // set medium intensity (range is 0-15)
sendCommand(11,numberOfDigits); // 7221 digit scan limit command
sendCommand(9,255); // decode command, use standard 7-segment digits
digitalWrite(slaveSelect,HIGH); //deselect slave
}
void loop()
{
displayNumber(count);
count = count + 1;
if( count > maxCount)
count = 0;
delay(100);
}
Discussion
7KH0$;QHHGVDFRPPRQFDWKRGH/('7KHSLQRXWVLQ)LJXUHDUHIRUD
/LWH2Q/7'*-DPHFR7KLVLVDWZRGLJLWVHJPHQW/('DQGWKH
FRUUHVSRQGLQJVHJPHQWVIRUHDFKGLJLWPXVWEHFRQQHFWHGWRJHWKHU)RUH[DPSOHWKH
GHFLPDOSRLQWLVRQSLQIRUGLJLWDQGSLQIRUGLJLW7KHILJXUHLQGLFDWHVWKDWSLQV
DQGDUHFRQQHFWHGWRJHWKHUDQGZLUHGWRWKH0$;SLQ
7KH0$;FDQGLVSOD\XSWRHLJKWGLJLWVRUDQ[PDWUL[DQGLVFRQWUROOHGE\
VHQGLQJFRPPDQGVWKDWGHWHUPLQHZKLFK/('VHJPHQWLVOLW
$IWHULQLWLDOL]LQJWKHOLEUDU\WKH63,FRGHLVFRQWDLQHGZLWKLQWKHsendCommandIXQFWLRQ
%HFDXVH63,XVHVWKHVHOHFWVODYHZLUHFRQQHFWHGWRWKHFKLSWKHFKLSLVVHOHFWHGE\
VHWWLQJWKDWSLQLOW$OO63,FRPPDQGVDUHWKHQUHFHLYHGE\WKDWFKLSXQWLOLWLVVHWHIGH
SPI.transferLVWKHOLEUDU\IXQFWLRQIRUVHQGLQJDQ63,PHVVDJH7KLVFRQVLVWVRIWZR
SDUWVDQXPHULFDOFRGHWRVSHFLI\ZKLFKUHJLVWHUVKRXOGUHFHLYHWKHPHVVDJHIROORZHG
E\WKHDFWXDOGDWD7KHGHWDLOVIRUHDFK63,GHYLFHFDQEHIRXQGLQWKHGDWDVKHHW
SetupLQLWLDOL]HVWKHE\VHQGLQJFRPPDQGVWRZDNHXSWKHFKLSLWVWDUWVXSLQD
ORZSRZHUPRGHDGMXVWWKHGLVSOD\LQWHQVLW\VHWWKHQXPEHURIGLJLWVDQGHQDEOH
GHFRGLQJIRUVHJPHQWGLVSOD\V(DFKFRPPDQGFRQVLVWVRIDFRPPDQGLGHQWLILHUUH
IHUUHGWRDVDUHJLVWHULQWKHGDWDVKHHWDQGDYDOXHIRUWKDWFRPPDQG
&RPPDQGQXPEHUVWKURXJKDUHXVHGWRFRQWUROWKHGLJLWV7KHIROORZLQJFRGH
ZRXOGOLJKWWKHVHJPHQWVWRGLVSOD\WKHQXPEHULQWKHILUVWOHIWPRVWGLJLW1RWHWKDW
GLJLWQXPEHUVVKRZQLQWKHGDWDVKHHWDQG)LJXUHVWDUWIURPVR\RXPXVW
UHPHPEHUWKDW\RXFRQWUROGLJLWZLWKFRPPDQGGLJLWZLWKFRPPDQGDQGVRRQ
sendCommand(1, 5); // display 5 on the first digit
<RXFDQVXSSUHVVOHDGLQJ]HURVE\DGGLQJWZROLQHVRIFRGHLQdisplayNumberWKDWVHQG
[IWRWKHWREODQNWKHVHJPHQWVLIWKHUHVLGXDOYDOXHLV
void displayNumber( int number)
{
for(int i = 0; i < numberOfDigits; i++)
Download from Wow! eBook <www.wowebook.com>
{
byte character = number % 10;
7KHQH[WWZROLQHVDUHDGGHGWRVXSSUHVVOHDGLQJ]HURV
if(number == 0 && i > 0)
character = 0xf; // value to blank the 7221 segments
sendCommand(numberOfDigits-i, character);
number = number / 10;
}
}
Solution
7KHWZRVNHWFKHVLQWKLVUHFLSHVKRZKRZ,&FDQEHXVHGDVDFRPPXQLFDWLRQVOLQN
EHWZHHQWZRRUPRUH$UGXLQRERDUGV)LJXUHVKRZVWKHFRQQHFWLRQV
7KHPDVWHUVHQGVFKDUDFWHUVUHFHLYHGRQWKHVHULDOSRUWWRDQ$UGXLQRVODYHXVLQJ,&
/*
* I2C_Master
* Echo Serial data to an I2C slave
*/
#include <Wire.h>
void setup()
{
Wire.begin();
}
void loop()
{
char c;
if(Serial.available() > 0 )
{
// send the data
Wire.beginTransmission(address); // transmit to device
Wire.send(c);
Wire.endTransmission();
}
}
7KHVODYHSULQWVFKDUDFWHUVUHFHLYHGRYHU,&WRLWVVHULDOSRUW
/*
* I2C_Slave
* monitors I2C requests and echoes these to the serial port
*
*/
void setup()
{
Wire.begin(address); // join I2C bus using this address
Wire.onReceive(receiveEvent); // register event to handle requests
}
void loop()
{
// nothing here, all the work is done in receiveEvent
}
Discussion
7KLVFKDSWHUIRFXVHGRQ$UGXLQRDVWKH,&PDVWHUDFFHVVLQJYDULRXV,&VODYHV+HUH
DVHFRQG$UGXLQRDFWVDVDQ,&VODYHWKDWUHVSRQGVWRUHTXHVWVIURPDQRWKHU$UGXLQR
7HFKQLTXHVFRYHUHGLQ&KDSWHUIRUVHQGLQJE\WHVRIGDWDFDQEHDSSOLHGKHUH7KH
:LUHOLEUDU\GRHVQRWKDYHDSULQWPHWKRGEXWLWVQRWGLIILFXOWWRDGGWKLV
7KHIROORZLQJVNHWFKFUHDWHVDQREMHFWQDPHGI2CDebugWKDWVHQGVLWVRXWSXWRYHU,&
8VLQJWKLVZLWKWKH,&VODYHVNHWFKVKRZQSUHYLRXVO\HQDEOHV\RXWRSULQWGDWDRQWKH
PDVWHUZLWKRXWXVLQJWKHVHULDOSRUWWKHVODYHVVHULDOSRUWLVXVHGWRGLVSOD\WKHRXWSXW
/*
* I2C_Master
* Sends serial data to an I2C slave
*/
#include <Wire.h>
I2CDebugClass::I2CDebugClass()
{
}
boolean I2CDebugClass::begin(int id)
{
I2CAddress = id; // save the slave's address
Wire.begin(); // join I2C bus (address optional for master)
return true;
}
void I2CDebugClass::write(byte c)
{
if( count == 0)
{
// here if the first char in the transmission
Wire.beginTransmission(I2CAddress); // transmit to device
}
Wire.send(c);
// if the I2C buffer is full or an end of line is reached, send the data
// BUFFER_LENGTH is defined in the Wire library
if(++count >= BUFFER_LENGTH || c == '\n')
{
// send data if buffer full or newline character
Wire.endTransmission();
count = 0;
}
}
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
val = analogRead(sensorPin); // read the voltage on the pot (val ranges
from 0 to 1023)
Serial.println(val);
I2CDebug.println(val);
}
See Also
&KDSWHUKDVPRUHLQIRUPDWLRQRQXVLQJWKH$UGXLQRSULQWIXQFWLRQDOLW\