Near Future Laboratory » Blog Archive » Arduino and the Two

advertisement
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Arduino and the Two-Wire Interface (TWI/I2C)
Including A Short Didactic Parenthetical On
Making TWI Work On An Arduino Mini
I have been using the Arduino and Atmel microcontroller’s generally using the SPI (serial-peripheral
interface), but decided to look at the two-wire (a.k.a. I2C) interface as well. I’m doing this partially because
it would be good to know how it works, but also because it’s electrically more compact. It only uses twowires, rather than the four required for SPI, so schematic designs and board layouts become a bit more
manageable. The trade-off is a little bit more complicated protocols semantics, but nothing out of control.
(I’m also looking at using a two-axis accelerometer that’s much less expensive than the three-axis one I’ve
been using – $4 versus $15. For some experiments, two-axes may be perfectly fine, and I’m happy to save
the $11.)
The first step was making sure the Arduino would handle the TWI – there’s pretty much no reason it
shouldn’t, because the Atmega8 certainly handles it. So, the next step was finding out how best to handle
TWI transactions.
To do this, I consulted the Atmega8 specification sheet, which has a pretty thorough explanation of the
protocol and the implementation details on the Atmega8. (There are also a couple of useful application notes
available here and here.) It’s so thorough that I had to print it out. I got a pretty good understanding of how
it works but before I started coding, I noticed that there were some TWI libraries both in avrlibc and in the
“Wire” library in Wiring.org happens to be packaged as a “sanctioned” external library for Arduino, so that
was pretty much that.
Nicholas Zambetti, who wrote the Wire library, pretty much told me it should work with no problems, and
he was pretty much right. No problems. His library abstracts the TWI innards really nicely, so I don’t have
to muck with any Atmega registers or anything of that sort.
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 1 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
I hooked up my Arduino to a handy accelerometer for testing. (I’m still using the expensive LIS3LV02DQ.)
Analog In 4 goes to SDA, and Analog In 5 goes to SCL. I have pull-up resistors on those lines, but Nicolas
explains that his library enables the internal pull-ups on the Atmega, so I can probably pull those from my
breadboard. Either way, it’s working just fine, even with the external pull-up resistors. (I’m using 4.7k
resistors.)
(I also found in one weird situation that I had to explicitly clear the clock prescaler to get the UART
functioning properly. This was while getting TWI working on an AT90USB1287 – TWI worked fine, but
the UART was spitting out garbage. On chips where the clock prescaler can be set through the fuses, it’s
important to verify that the prescaler isn’t hard wired to divide the clock. This’ll cause anything that is
dependent on timing to potentially be off kilter. In my case, the UART was expecting an 8MHz clock to
determine timing and baud rate, but the clock was being divided in hardware – not even in the firmware.)
Wire/TWI (I2C) on the Arduino Mini
Getting TWI working on the Arduino Mini (Although the Arduino and Arduino Mini share a name, they
don’t share the same processor. The Arduino Mini uses an ATmega168, while the Arduino..normal.. uses an
ATmega8. You’ll need to recompile/re-”verify” the Wire library files in order to get TWI to work on the
ATmega168/Arduino Mini. There’s a thing or two you’ll have to do by hand to get this to work, and you’ll
need to do it each time you move code that’s using the Wire library to a different processor. In other words,
when you decide to port the code to the ATmega8, or you put an ATmega16 in your Arduino, or whatever â
€” you’ll need to recompile these libraries. Here’s the drill:
Navigate in a file browser or command prompt to the root of your Arduino file hierarchy. Then go into:
lib/targets/libraries/Wire/
delete Wire.o
lib/targets/libraries/Wire/utility
delete twi.o
Once you’ve done this, make one modification to the header file twi.h in lib/targets/libraries/Wire/utility.
Look around line 27 for a commented out line like this:
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 2 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
//#define ATMEGA8
Un-comment it (take out the “//” in the front.) This’ll ensure that the internal pull-up resistors on the
ATmega8 are enabled when you’re developing for the normal Arduino. You’ll only need to make this
change to twi.h once and for all. Future builds of Arduino should have this fixed.
For those who are curious — pull-up resistors are required on the TWI lines — SCL and SDA. You may
use your own external pull-ups, but enabling the internal ones saves you the hassle. But, I don’t think you’ll
do much harm if you have the internal one’s enabled and use external ones. But, generally you’ll want to
avoid having both internal and external pull-ups.)
Anyway. These modifications described above should get TWI working on the Arduino Mini.)
Here’s the code I wrote and ran:
#include <Wire.h>
//
//
//
//
//
//
//
TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer
Using the Wire library (created by Nicholas Zambetti)
http://wiring.org.co/reference/libraries/Wire/index.html
On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the Atmega8
The Wire class handles the TWI transactions, abstracting the nitty-gritty to make
prototyping easy.
void setup()
{
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);
Serial.begin(9600);
CLKPR = (1<<CLKPCE);
CLKPR = 0;
Wire.begin(); // join i2c bus (address optional for master)
Wire.beginTransmission(0x1D);
Wire.send(0x20); // CTRL_REG1 (20h)
Wire.send(0x87); // Device on, 40hz, normal mode, all axis's enabled
Wire.endTransmission();
}
void loop()
{
byte z_val_l, z_val_h, x_val_l, x_val_h, y_val_l, y_val_h;
int z_val, x_val, y_val;
//Serial.println("hello?");
//byte in_byte;
// transmit to device with address 0x1D
// according to the LIS3L* datasheet, the i2c address of is fixed
// at the factory at 0011101b (0x1D)
Wire.beginTransmission(0x1D);
// send the sub address for the register we want to read
// this is for the OUTZ_H register
// n.b. supposedly masking the register address with 0x80,
// you can do multiple reads, with the register address auto-incremented
Wire.send(0x28);
// stop transmitting
Wire.endTransmission();
// Now do a transfer reading one byte from the LIS3L*
// This data will be the contents of register 0x28
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
x_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x29); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 3 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
x_val_h = Wire.receive();
}
x_val = x_val_h;
x_val <<= 8;
x_val += x_val_l;
// Y Axis
Wire.beginTransmission(0x1D); Wire.send(0x2A); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
y_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x2B); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
y_val_h = Wire.receive();
}
y_val = y_val_h;
y_val <<= 8;
y_val += y_val_l;
// Z Axis
Wire.beginTransmission(0x1D); Wire.send(0x2C); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
z_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x2D); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
z_val_h = Wire.receive();
}
z_val = z_val_h;
z_val <<= 8;
z_val += z_val_l;
// Set up to read the next register
// Supposedly, if you set the most significant bit of
// the register address to 1, you can do a multiple read,
// with the register address auto-incrementing. This way, you
// don't have to do another write — specifying the next register —
// before reading the next register value. This would be very good, but
// with a cursory attempt, I have yet to make this work.
/*
Wire.beginTransmission(0x1D); // transmit to device #4
Wire.send(0x2C);
// read outx_h
// stop transmitting
Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
z_val_l = Wire.receive();
}
z_val = z_val_h;
z_val <<= 8;
z_val += z_val_l;
// z axis acceleration, all set.
// Perfectly still and with the z-axis parallel to the ground, it should be about 1024-ish
// (I find in practice it is around 1019.)
// When the z-axis is orthogonal to the ground, it should be zero.
// 1024 is +1g acceleration, or normal gravity
// 2048 is +2g
// 0 is 0g
Serial.println(z_val, DEC);
*/
Serial.print(x_val, HEX); Serial.print(" ");Serial.print(y_val, HEX); Serial.print(" "); Serial.println(z_val, HEX);
delay(100);
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 4 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
}
Technorati Tags: Arduino, DIY
Related Dispatches:
1. Propeller and Arduino Not the most exciting thing, but an interesting challenge here. I’m trying to get a Parallax
Propeller chip to...
2. Finding The Way – HMC6352 Digital Compass Since I was asked, and asked again, I’ll toss this technotopia
solutions nugget to demonstrate that, despite the evidence...
3. Reflow Skillet I picked up a nice electric skillet from Target to do some surface-mount technology work. It was on sale...
4. Laboratories, Accelerometers And Kitchen Crockery The Memsic 6202 Accelerometer, fresh out o’the skillet.
We’ve been out of the Laboratory proper — the place where things...
previous post: « Flavonoid Notes...
next post: » Quick Note on...
About This Post
You’re currently reading “Arduino and the Two-Wire Interface (TWI/I2C) Including A Short Didactic
Parenthetical On Making TWI Work On An Arduino Mini,” an entry on Near Future Laboratory
Published:
01.11.07 / 6pm
Category:
Arduino, Atmel, Flavonoid, Hardware, How To, Motion, Projects, Software, sensor
17 Comments
Jump to comment form | comments rss [?] | trackback uri [?]
RSS feed | Trackback URI
17 Comments »
Comment by Daniel
2008-02-09 10:23:13
Hi,
how do you call those flexible wires that you are using and where did you get them?
Thanks,
Daniel
Reply to this comment
Comment by Julian
2008-02-11 13:21:35
They are just jumper wires, sold from Jameco and also Spark Fun electronics has some as
well. (http://www.sparkfun.com/commerce/product_info.php?products_id=8431)
Reply to this comment
Comment by Matthew
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 5 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
2008-02-19 23:31:50
Julian, thanks for your excellent example of the TWI on the Arduino. It helped me get up and
running in no time. I have one question though, I tried to take your example a little further
by writing my own I2C code (instead of using the wire library) and to do multiple reads from
the accelerometer. However, I cannot get it to work. Did you ever get the multiple read
functionality to work? I could swear I’m following the LIS3LV02DQ data sheet to the T.
Thanks!
Reply to this comment
Comment by Felixe
2008-04-15 01:05:54
What’s the part number or manufacturer for those cheap accelerometers?
Reply to this comment
Comment by Julian
2008-04-15 09:48:16
Felixe,
They’re ST Microelectronics’ LIS3LV02DQ, a 3-axis accelerometer with digital outputs.
I get the break-out boards from Spark Fun Electronics:
http://tinyurl.com/mfa6g
They’re not particularly inexpensive — about $15 single quantities for the individual pieces,
and $43 on the break-out board.
Julian
Reply to this comment
Comment by MrScary
2008-07-08 04:40:01
Here is a working example based on the code above that does multiple reads at once for
reading all three axis.. I’m using this sketch on an arduino nano.. Thanks for the original
example
#include <wire.h>
// TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer
// Using the Wire library (created by Nicholas Zambetti)
// http://wiring.org.co/reference/libraries/Wire/index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the
Atmega8
// The Wire class handles the TWI transactions, abstracting the nitty-gritty to make
// prototyping easy.
#define OUTX_L 0×28
#define OUTX_H 0×29
#define OUTY_L 0×2A
#define OUTY_H 0×2B
#define OUTZ_L 0×2C
#define OUTZ_H 0×2D
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 6 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
#define XAXIS 0
#define YAXIS 1
#define ZAXIS 2
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin( 9600 );
Wire.beginTransmission( 0×1D );
Wire.send( 0×20 ); // CTRL_REG1 ( 20h )
Wire.send( 0×87 ); // Device on, 40hz, normal mode, all axis’s enabled
Wire.endTransmission();
}
void loop() {
int val[3];
// transmit to device with address 0×1D
// according to the LIS3L* datasheet, the i2c address of is fixed
// at the factory at 0011101b (0×1D)
Wire.beginTransmission( 0×1D );
// send the sub address for the *first* register we want to read
// this is for the OUTX_L register
// set the MSB so we can do multiple reads, with the register address auto-incremented
Wire.send( OUTX_L | 0×80);
// stop transmitting
Wire.endTransmission();
// Now do a transfer reading six bytes from the LIS3L*
// This data will be the contents of the X Y and Z registers
Wire.requestFrom( 0×1D, 6 );
while ( Wire.available() < 6 ) {
// this isn’t really necessary
// a better thing to do would be to set up an onReceive handler,
// buffer the data and go off and do something else if the data isn’t ready
delay( 5 );
}
// read the data
for ( int i = 0; i < 3; i++ ) {
// read low byte
byte low = Wire.receive();
// read the high byte
val[i] = ( Wire.receive() << 8 ) + low;
}
// do something with the values
Serial.print( ” x_val = ” );
Serial.print( val[XAXIS], DEC );
Serial.print( ” y_val = ” );
Serial.print( val[YAXIS], DEC );
Serial.print( ” z_val = ” );
Serial.println( val[ZAXIS], DEC );
delay( 250 );
}
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 7 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Reply to this comment
Comment by Bryan
2008-08-18 09:26:36
Hi, I’ve had success with the Arduino Diecimila(Atmega168) with the accelerometer quite
well.
A newbie question:
This time, I’ve got a SFE’s Skinny(Atmega168v, 8MHz) with 3.3v logic level.
In this case, do I have reflect the changes in the clock speed for the I2C connection?
Thanks a lot.
Bryan
Reply to this comment
Comment by Julian
2008-08-18 11:43:19
Ooh. I haven’t heard of the Skinny, but it sounds quite useful!
I’m guessing that you don’t need to make any adjustments in the source code. The
LilyPad Arduino, which also runs at 8MHz can be specified under the menu item “Tools>Board” — that should compile your code with the correct F_CPU define of 8000000
without you mucking about under the hood.
Reply to this comment
Comment by Bryan
2008-08-19 10:12:21
Thank you, Julian.
Great, I don’t have to pull my hair out for the source coding adustments!
The menu item selection will do the job for me! Wow.
Bryan
(Comments wont nest below this level)
Reply here
Comment by Bryan
2008-09-18 10:03:30
Hi, Julian.
After I’ve received my Skinny, 8MHz clock with 3.3volt logic, from the SFE, I had to
solve the problem with the program uploading to the Skinny.
Since I already had success, using your didactic instructions, with Arduino Diecimila –
I2C of LIS3LV02DQ – hooked up to my PC, I did not suspect the poor old FTDI
driver. No success even with numerous changing of reset button timings!
Anyway,long story short, I found the FTDI driver should be updated, and intalled the
new one last week. The uploding works great.
I still have to connect the Accelerometer to my Skinny at 3.3V.
I understand I’m quite a bit behind schedule.
My Skinny will be soon connected.
Thanks for your help.
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 8 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Bryan
(Comments wont nest below this level)
Comment by Julian
2008-09-21 02:18:22
Hey, thanks for the notes Bryan! Keep me up to date with how it all works.
Julian
Reply here
Comment by Henry
2008-09-29 13:05:43
Hi Julian
Thanks for your very informative example
I’ve been trying to get a Lilypad to talk to sparkfun’s capacitive sensing module (based on
the AD7746) – but i’ve’ got almost nowhere with it!
Have you any experience with this chip?
cheers,
-henry
Reply to this comment
Comment by Julian
2008-09-30 01:17:37
Hey Henry,
I’ve never tried this part, but I actually think I have it on a break out board
somewhere..just never got to it. I used the AD7150 though, which is also an I2C device.
Never really had any particular problems with it.
Where have you gotten with the AD7746? I can probably help you debug..
.julian.
Reply to this comment
Name (required)
E-mail (required - never shown publicly)
URI
Your Comment (smaller size | larger size)
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 9 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del
datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped=""> in your comment.
Add comment
Trackback responses to this post
Anderson Miller - project blog » Physical Computing - Final
How to Connect Multiple Arduino Microcontrollers with I2C | Hack N Mod
Arduino I2C « Mike’s Brain
Electronic improvements « NEar Space LABoratory
Recent Posts
Brand Obama
Tangled Knots
Interoperability
Incongruence Between Public & Private
David Byrne Urbanism
Drama, Boredom, Simply Infovisualized
National Science Foundation Creative “IT” RFP
Approaches To Design
SXSW 2010 Interactive Proposal – Design Fiction
Eduardo Galeano Contemplates History’s Paradoxes
Pogoplug and The Rise of Network Fog
Personas Web
Generative Urban Design
Pastiche, Scenarios, Design, Communication
Lift Asia 09 Jeju Korea, Sept 17-18
Categories
3D Printed (9)
Advertising (6)
Air Guitar Hero (2)
Announcement (1)
Announcements & Calls For Things (8)
Apparatus for Capturing Other Points of View (1)
Approaches to Design (1)
Arduino (22)
Atmel (27)
Book Review (2)
Book Stuff (95)
Cartography (15)
Conference (20)
Contexts (9)
Design (95)
Design Art Technology (61)
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 10 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Design as Strategy (8)
Design Fiction (29)
Design Fiction Chronicles (7)
Design for Implications (71)
Design Technology (27)
Display (6)
Disruption (20)
Drift Deck (3)
Failure (2)
Flavonoid (28)
General (173)
Global Consequences (1)
Hardware (61)
Health and Fitness (4)
How To (41)
Improvisation (14)
Infrastructure (4)
Innovation (41)
Interaction Terms (18)
Interface (20)
Keyboard (5)
Landscape (18)
Landscape as Interface (19)
Measures of Things (3)
Mobile (43)
MobZombies (4)
Money (2)
Motion (43)
New Interaction Rituals (21)
Nokia (5)
Observations (80)
PDPal (2)
Peculiar (37)
Photo (11)
Play (28)
Post-GUI (21)
Post-Optimal Design (13)
Pre-GUI (3)
Presence Awareness (1)
Presentation (5)
Printed Circuit Board (2)
Projects (47)
Propeller (5)
Proposal (4)
Proposed (3)
Protocols and Practices (1)
Proximity (13)
PSX (11)
Psychogeography (13)
scenario (11)
Science Fiction (2)
science technology studies (18)
Security (5)
sensor (24)
Sharing (2)
SiteNav (4)
Slow Messenger (9)
Social Practice (36)
Software (14)
Spain (2)
The Future (2)
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 11 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Themes (2)
Theory (74)
Thoughtful Act (6)
Thoughtless Acts (5)
Time (23)
Tools (1)
Touch (14)
Tourism (9)
Travel (10)
Trust (6)
Undesign (11)
Undisciplinarity (35)
Urban (36)
user experience (10)
WiFiArtCache (1)
WiFiKu (1)
Workshop (4)
Worry Wand (1)
writing (19)
Pages
About
Julian Press Photos
Julian’s Bio
Nicolas’ Bio
The Near Future Laboratory Process
Tactical Research Associates
Contact
Essays
Presentations
Projects
Drift Deck (Analog Edition)
Drift Deck Proposal
Flavonoid
Flavonoid — 1st Prototype
Flavonoid — 2nd Prototype
Flavonoid — 3rd Prototype
Flavonoid — 5th Prototype
Flavonoid — 7th Prototype
High Chair
Projects Briefly
PSX — Social Engineering Katamari Damacy
Slow Messenger
Vis-a-Vis
WiFiKu
Workshops
Most Read Posts
Chalkbot Versus GraffitiWriter...Round One! Ready....FIGHT!
Design Fiction: A Short Essay on Design, Science, Fact and Fiction
Overlap 09
Call for Artists — Locative Cinema Commission
Measuring the Immeasurable
Follow Curiosity, Not Careers
Design Fiction Chronicles: The Stability of Food Futures
Design Fiction Chronicles: The Interlaced Histories of Star Trek & Mobile Phones
William H. Whyte Revisited: An Experiment With An Apparatus for Capturing Other Points of View
Design Fiction Chronicles: Cylon Hybrids "Tweet" Prophecy or Prattle
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 12 of 13
Near Future Laboratory » Blog Archive » Arduino and the Two-Wire Int…A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini
9/30/09 11:04 AM
Archives
Select Month
Powered by Hemingway & Ninja Monkeys! flavored Wordpress.
Entries RSS Comments RSS
http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
Page 13 of 13
Download