t r o n i x s t u f f

fun and learning with electronics

Tutorial: Arduino and the I2C bus – Part One

Please note that the tutorials are not currently compatible with Arduino IDE v1.0. Please continue to use v22 or v23 until further notice. 

The first chapter is here, the complete series is detailed here. Please note from November 1, 2010 files from tutorials will be found here.

Welcome back fellow arduidans!

Today we are going to start investigating the I2C data bus, and how we can control devices using it with our Arduino systems. The I2C bus can be a complex interface to master, so I will do my best to simplify it for you. In this article we will learn the necessary theory, and then apply it by controlling a variety of devices. Furthermore it would be in your interest to have an understanding of the binary, binary-coded decimal and hexadecimal number systems.

But first of all, what is it?

I2C is an acronym for “Inter-Integrated Circuit”. In the late 1970s, Philips’ semiconductor division (now NXP) saw the need for simplifying and standardising the data lines that travel between various integrated circuits in their products. Their solution was the I2C bus. This reduced the number of wires to two (SDA – data, and SCL – clock). Here is a nice introductory video from NXP:

Why would we want to use I2C devices?

As there are literally thousands of components that use the I2C interface! For example, click these supplier links to have a look at the range: NXP, Farnell, Digikey, Mouser, and RS

And our Arduino boards can control them all. There are many applications, such a real-time clocks, digital potentiometers, temperature sensors, digital compasses, memory chips, FM radio circuits, I/O expanders, LCD controllers, amplifiers, and so on. And you can have more than one on the bus at any time, in fact the maximum number of I2C devices used at any one time is 112.

From a hardware perspective, the wiring is very easy. Those of you with an Arduino Duemilanove, Uno or 100% compatible board, you will be using pins A4 for SDA (data) and A5 for SCL (clock).

If you are using an Arduino Mega, SDA is pin 20 and SCL is 21, so note that shields with I2C need to be specifically for the Mega. If you have another type of board, check your data sheet or try the Arduino team’s hardware website.  And finally, if you are using a bare DIP ATmega328-PU microcontroller, you will use pins 27 for SDA and 28 for SCL.

The bus wiring is simple:

If you are only using one I2C device, the pull-up resistors are (normally) not required, as the ATmega328 microcontroller in our Arduino has them built-in.  However if you are running a string of devices, use two 10 kilo ohm resistors. Like anything, some testing on a breadboard or prototype circuit will determine their necessity. Sometimes you may see in a particular device’s data sheet the use of different value pull-up resistors – for example 4.7k ohm. If so, heed that advice. The maximum length of an I2C bus is around one metre, and is a function of the capacitance of the bus. This distance can be extended with the use of a special IC, which we will examine during the next I2C chapter.

Each device can be connected to the bus in any order, and devices can be masters or slaves. In our Arduino situation, the board is the master and the devices on the I2C bus are the slaves. We can write data to a device, or read data from a device. By now you should be thinking “how do we differentiate each device on the bus?”… Each device has a unique address. We use that address in the functions described later on to direct our read or write requests to the correct device. It is possible to use two devices with identical addresses on an I2C bus, but that will be discussed in a later article.

As like most devices, we make use of an Arduino library, in this case <wire.h>. Then use the function Wire.begin(); inside of void setup() and we’re ready to go.

Sending data from our Arduino to the I2C devices requires two things: the unique device address (we need this in hexadecimal) and at least one byte of data to send. For example, the address of the part in example 20.1 (below) is 00101111 (binary) which is 0X2F in hexadecimal. Then we want to set the wiper value, which is a value between 0 and 127, or 0×00 and 0x7F in hexadecimal. So to set the wiper to zero, we would use the following three functions:

Wire.beginTransmission(0x2F);      // part address is 0x2F or 0101111b

This sends the device address down the SDA (data) line of the bus. It travels along the bus, and “notifies” the matching device that it has some data coming…

Wire.send(69); //

This sends the byte of data to the device – into the device register (or memory of sorts), which is waiting for it with open arms. Any other devices on the bus will ignore this. Note that you can only perform one I2C operation at a time! Then when we have finished sending data to the device, we “end transmission”. This tells the device that we’re finished, and frees up the I2C bus for the next operation:

Wire.endTransmission();

Some devices may have more than one register, and require more bytes of data in each transmission. For example, the DS1307 real-time clock IC has eight registers to store timing data, each requiring eight bits of data (one byte):

However with the DS1307  - the entire lot need to be rewritten every time. So in this case we would use eight wire.send(); functions every time. Each device will interpret the byte of data sent to it, so you need the data sheet for your device to understand how to use it.

Receiving data from an I2C device into our Arduino requires two things: the unique device address (we need this in hexadecimal) and the number of bytes of data to accept from the device. Receiving data at this point is a two stage process. If you review the table above from the DS1307 data sheet, note that there is eight registers, or bytes of data in there. The first thing we need to do is have the I2C device start reading from the first register, which is done by sending a zero to the device:

Wire.beginTransmission(device_address);
Wire.send(0);
Wire.endTransmission();

Now the I2C device will send data from the first register when requested. We now need to ask the device for the data, and how many bytes we want. For example, if a device held three bytes of data, we would ask for three, and store each byte in its own variable (for example, we have three variables of type byte: a, b, and c. The first function to execute is:

Wire.requestFrom(device_address, 3);

Which tells the device to send three bytes of data back to the Arduino. We then immediately follow this with:

*a = Wire.receive();
*b = Wire.receive();
*c = Wire.receive();

We do not need to use Wire.endTransmission() when reading data. Now that the requested data is in their respective variables, you can treat them like any ordinary byte variable.

For a more detailed explanation of the I2C bus, read this explanatory document by NXP. Now let’s use our I2C knowledge by controlling a range of devices…

Example 20.1

A new part for today, the Microchip MCP4018T digital linear potentiometer. The value of this model is 10 kilo ohms. Inside this tiny, tiny SMD part is a resistor array consisting of 127 elements and a wiper that we control by sending a value of between 0 and 127 (in hexadecimal) down the I2C bus. This is a volatile digital potentiometer, it forgets the wiper position when the power is removed. However naturally there is a compromise with using such a small part, it is only rated for 2.5 milliamps – but used in conjunction with op amps and so on. For more information, please consult the data sheet.

As this is an SMD part, for breadboard prototyping purposes it needed to be mounted on a breakout board. Here it is in raw form:

Above the IC is a breakout board. Consider that the graph paper is 5mm square! It is the incorrect size, but all I have. However soldering was bearable. Put a drop of solder on one pad of the breakout board, then hold the IC with tweezers in one hand, and reheat the solder with the other hand – then push the IC into place. A few more tiny blobs of solder over the remaining pins, and remove the excess with solder wick. Well … it worked for me:

Our example schematic is as follows:


As you can see, the part is simple to use, your signal enters pin 6 and the result of the voltage division is found on pin 5. Please note that this is not a replacement for a typical mechanical potentiometer, we can’t just hook this up as a volume or motor-speed control! Again, please read the data sheet.

Control is very simple, we only need to send one byte of data down, the hexadecimal reference point for the wiper, e.g.:

Wire.beginTransmission(0x2F);      // part address is 0x2F or 0101111b
Wire.send(0x3F); //
Wire.endTransmission();

Here is a quick demonstration that moves the wiper across all points: (download)

/*
Example 20.1  Microchip MCP4018 digital potentiometer demonstration sketch
 http://tronixstuff.com/tutorials > chapter 20  CC by-sa v3.0
*/
int dt = 2000; // used for delay duration
byte rval = 0x00; // used for value sent to potentiometer
#include "Wire.h"
#define pot_address 0x2F // each I2C object has a unique bus address, the MCP4018 is 0x2F or 0101111 in binary
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void potLoop()
// sends values of 0x00 to 0x7F to pot in order to change the resistance
// equates to 0~127
{
for (rval=0; rval<128; rval++)
{
Wire.beginTransmission(pot_address);
 Wire.send(rval);
  Wire.endTransmission();
 Serial.print(" sent -  ");
Serial.println(rval, HEX);
delay(dt);
}
}
  void loop()
{
  potLoop();
}

and a video demonstration:


Example 20.2

Now we will read some data from an I2C device. Our test subject is the ST Microelectronics CN75 temperature sensor. Again, we have another SMD component, but the CN75 is the next stage larger than the part from example 20.1. Thankfully this makes the soldering process much easier, however still requiring some delicate handiwork:

First, a small blob of solder, then slide the IC into it. Once that has cooled, you can complete the rest and solder the header pins into the breakout board:

Our example schematic is as follows:


Pins 5, 6 and 7 determine the final three bits of the device address – in this case they are all set to GND, which sets the address to 1001000. This allows you to use multiple sensors on the same bus. Pin 3 is not used for basic temperature use, however it is an output for the thermostat functions, which we will examine in the next chapter.

As a thermometer it can return temperatures down to the nearest half of a degree Celsius. Although that may not be accurate enough, it was designed for automotive and thermostat use. For more details please read the data sheet. The CN75 stores the temperature data in two bytes, let’s call them A and B. So we use

Wire.requestFrom(cn75address, 2)

with the second paramater as 2, as we want two bytes of data. Which we then store using the following functions:

*a = Wire.receive(); // first received byte stored here
*b = Wire.receive(); // second received byte stored here

where *a and *b are variables of the type byte.

And as always, there is a twist to decoding the temperature from these bytes. Here are two example pieces of sample data:

Example bytes one: 00011001 10000000
Example bytes two: 11100111 00000000

The bits in each byte note particular values… the most significant bit (leftmost) of byte A determines whether it is below or above zero degrees – 1 for below zero. The remaining seven bits are the binary representation of the integer part of the temperature; if it is below zero, we subtract 128 from the value of the whole byte and multiply by -1. The most significant bit of byte B determines the fraction, either zero or half a degree. So as you will see in the following example sketch (download), there is some decision making done in showCN75data():

/* Example 20.2
ST Microelectronics CN75 Digital Temperature sensor demonstration sketch
CC by-sa v3.0
*/
#include "Wire.h"
#define cn75address 0x48 // with pins 5~7 set to GND, the device address is 0x48
void setup()
{
Wire.begin(); // wake up I2C bus  Serial.begin(9600);
}
void getCN75data(byte *a, byte *b)
{
 // move the register pointer back to the first register
 Wire.beginTransmission(cn75address); // "Hey, CN75 @ 0x48! Message for you"
Wire.send(0);        // "move your register pointer back to 00h"
Wire.endTransmission(); // "Thanks, goodbye..."
// now get the data from the CN75
Wire.requestFrom(cn75address, 2); // "Hey, CN75 @ 0x48 - please send me the contents of your first two registers"
 *a = Wire.receive(); // first received byte stored here
*b = Wire.receive(); // second received byte stored here
}
void showCN75data()
{
byte aa,bb;
 float temperature=0;
 getCN75data(&aa,&bb);
if (aa>127) // check for below zero degrees
{
 temperature=((aa-128)*-1);
if (bb==128)    // check for 0.5 fraction
{
 temperature-=0.5;
  }
 }   else // it must be above zero degrees
 {
  temperature=aa;
  if (bb==128)   // check for 0.5 fraction
 {
temperature+=0.5;
 }
 }
Serial.print("Temperature = ");
Serial.print(temperature,1);
Serial.println(" degrees C");
delay(1000);
}
void loop()
{
 showCN75data();
}

And here is the result from the serial monitor:

Example 20.3

Now that we know how to read and write data to devices on the I2C bus – here is an example of doing both, with a very popular device – the Maxim DS1307 real-time clock IC. Maxim have written an good data sheet. For those of you new to the world of tronixstuff, we use this part quite often, for example with our Arduino RTC shield and modifications, or blinky – the one-eyed clock. It is an 8-pin DIP IC that allows timing with accuracy down to a few seconds a day:

Furthermore, it also has a programmable square-wave generator. Connection and use is quite simple:

However some external components are required: a 32.768 kHz crystal, a 3V battery for time retention when the power is off, and a 10k ohm pullup resistor is required if using as a square-wave generator. You can use the SQW and timing simultaneously. If we have a more detailed look at the register map for the DS1307:

We see that the first seven registers are for timing data, the eighth is the square-wave control, and then another eight RAM registers. In this chapter we will look at the first eight only. Hopefully you have noticed that various time parameters are represented by less than eight bits of data – the DS1307 uses binary-coded decimal. But don’t panic, we have some functions to do the conversions for us.

However, in general  - remember that each bit in each register can only be zero or one – so how do we represent a register’s contents in hexadecimal? First, we need to find the binary representation, then convert that to hexadecimal. So, using the third register of the DS1307 as an example, and a time of 12:34 pm – we will read from left to right. Bit 7 is unused, so it is 0. Bit 6 determines whether the time kept is 12- or 24-hour time. So we’ll choose 1 for 12-hour time. Bit 5 (when bit 6 is 0) is the AM/PM indicator – choose 1 for PM. Bit 4 represents the left-most digit of the time, that is the 1 in 12:34 pm. So we’ll choose 1. Bits 3 to 0 represent the BCD version of 2 which is 0010.

So to store 12pm as hours we need to write 00110010 as hexadecimal into the hours register – which is 0×32.

Reading data from the DS1307 should be easy for you now, reset the register pointed, then request seven bytes of data and receive them into seven variables. The device address is 0×68.  For example:

Wire.beginTransmission(0x68);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second     = bcdToDec(Wire.receive();
*minute     = bcdToDec(Wire.receive();
*hour       = bcdToDec(Wire.receive();
*dayOfWeek  = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month      = bcdToDec(Wire.receive());
*year       = bcdToDec(Wire.receive());

At which point the time data will need to be converted to decimal numbers, which we will take care of in the example sketch later. Setting the time, or controlling the square-wave output is another long operation – you need to write seven variables to set the time or eight to change the square-wave output. For example, the time:

Wire.beginTransmission(0x68);
Wire.send(0);
Wire.send(decToBcd(second));
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();

The decToBcd is a function defined in our example to convert the decimal numbers to BCD suitable for the DS1307.

You can also address each register individually. We will demonstrate doing this with an explanation of how to control the DS1037′s in built square-wave generator (download sketch):

/*
DS1307 Square-wave machine
 Used to demonstrate the four different square-wave outputs from Maxim DS1307
 See page nine of data sheet for more information
 John Boxall - tronixstuff.wordpress.com
 */
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 // each I2C object has a unique bus address, the DS1307 is 0x68
void setup()
{
  Wire.begin();
}
void sqw1() // set to 1Hz
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x07); // move pointer to SQW address
  Wire.send(0x10); //  sends 0x10 (hex) 00010000 (binary)
  Wire.endTransmission();
}
void sqw2() // set to 4.096 kHz
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x07); // move pointer to SQW address
  Wire.send(0x11); //  sends 0x11 (hex) 00010001 (binary)
  Wire.endTransmission();
}
void sqw3() // set to 8.192 kHz
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x07); // move pointer to SQW address
  Wire.send(0x12); // sends 0x12 (hex) 00010010 (binary)
  Wire.endTransmission();
}
void sqw4() // set to 32.768 kHz (the crystal frequency)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x07); // move pointer to SQW address
  Wire.send(0x13); // sends 0x13 (hex) 00010011 (binary)
  Wire.endTransmission();
}
void sqwOff()
// turns the SQW off
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x07); // move pointer to SQW address
  Wire.send(0x00); // turns the SQW pin off
  Wire.endTransmission();
}
void loop()
{
  sqw1();
  delay(5000);
  sqw2();
  delay(5000);
  sqw3();
  delay(5000);
  sqw4();
  delay(5000);
  sqwOff();
  delay(5000);
}

Here is the SQW output in action – we measure the frequency using my very old Tek CFC-250:

For further DS1307 examples, I will not repeat myself and instead direct you to the list of many tronixstuff articles that make use of the DS1307.

So there you have it – hopefully an easy to understand introduction to the world of the I2C bus and how to control the devices within. Part two of my I2C tutorial has now been published, as well as an article about the NXP SAA1064 LED display driver IC and the Microchip MC23017 16-bit port expander IC.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

October 20, 2010 - Posted by | arduino, education, I2C, learning electronics, microcontrollers | , , , , , , , , , , , , , , , , , , , , , , , , ,

35 Comments »

  1. The Bus Pirate is a handy device for playing with I2C

    Comment by Andy Gelme | October 21, 2010 | Reply

    • Oh! I forgot about that. Which is very shameful considering I have one around here somewhere… will fire it up for part two…

      Comment by John Boxall | October 21, 2010 | Reply

  2. Excellent tutorial! I like how you dive into the details instead of just showing us how to use the libraries.

    Might you consider doing the same with SPI? I have sensors using both of these protocols.

    Comment by Phil Hutchinson | October 21, 2010 | Reply

    • G’Day Phil
      Thanks for your comment. I try to make things as useful as possible, that is – if you read it, you can then do it.
      SPI? OK, I’ll put it on the list.
      have fun
      john

      Comment by John Boxall | October 21, 2010 | Reply

  3. Thanks for another incredibly well-crafted tutorial. This has to be the single best explanation of I2C for Arduino anywhere.

    For part 2, could you please include an example which utilizes the Lego NXT Mindstorms ultrasonic sensor?

    Thanks again!

    Comment by Stephen Borg | October 21, 2010 | Reply

    • Hello Stephen
      Thank you for your kind comments. Lego NXT? Crikey. To be honest I haven’t played with lego for about 26 years. :) Though I do miss my trains.
      *ahem* anyway. Unless you need the Lego-enclosure, wouldn’t it be easier to use something like this? http://bit.ly/aLndTF
      cheers
      john

      Comment by John Boxall | October 21, 2010 | Reply

      • I still have both my old Lego *and* my old trains ;)

        As an owner of an NXT set I was thinking along the lines of repurposing existing devices rather than purchasing new ones. I was a little wary of trying I2C with my ultrasonic sensor without guidance, but I find your tutorials more than reasonable and trustworthy enough to take a swing at it.

        Thanks again!

        Comment by Stephen Borg | October 22, 2010

      • Trains! Oh well, enjoy yourself.
        I found a quote in this webpage – http://www.tau.ac.il/~stoledo/lego/i2c-8574/ – “The ultrasound-sensor block in NXT-G does use the I2C functionality, but it is specific to the ultrasound sensor and cannot be used with other I2C chips” but cannot find an explanation why. Food for thought, but have fun!
        cheers
        john

        Comment by John Boxall | October 22, 2010

  4. Thanks for the tutorial – helpful.

    Wondering if there is a typo – when you say:

    —– Wire.send(0x2F); //

    Shouldn’t that be 0x7F as the data to be sent?

    Comment by skinnytod | October 30, 2010 | Reply

    • Hello
      Thanks for that, I appreciate it when people actually read it properly :)
      We could use any value between 0 and 127; or 0×00 and 0x7F in hexadecimal – it was just an example for the wiper position parameter. We have done this in the sketch for example 20.1
      cheers
      john

      Comment by John Boxall | October 30, 2010 | Reply

  5. Great tutorial – Thanks! One question: You state near the beginning that “Those of you with an Arduino Duemilanove, Uno or 100% compatible board, you will be using pins A4 for SDA (data) and A5 for SCL (clock).” Why are we using the analog pins? I want to use them for other things. Can we use the digital pins to run this bus?

    Comment by William Gentles | December 10, 2010 | Reply

  6. Hi John,

    Many thanks for your thoughtful and detailed tutorials for those of us who don’t necessarily come from a long history of working with electronics and components. I’ve been tinkering for just under two years and have picked up some knowledge via many kind people’s tutorials, however have had to many times seek out clarification by doing at least 5 – 10 similar tutorials. On the other hand, your work is really well thought out and presents the material without assuming loads of prior knowledge. Well done and keep up the good work mate!
    Rich.

    Comment by Rich Carthew | April 7, 2011 | Reply

    • Hello Rich
      Thank you very much for your positive feedback, I really appreciate it.
      have a great day
      john

      Comment by John Boxall | April 7, 2011 | Reply

  7. i need help to program an fm transmitter module that uses i2c, have no clue of how to write the arduino sketch to do this. have all the data on this module dont know how to post attachement on this email. somebody please help.

    Comment by FRED AFSHAR | April 9, 2011 | Reply

  8. John, if I can also leave a suggestion for Fred- hope that’s OK?

    Fred, If you enjoy reading and tinkering in general, you could also try:

    Making Things Talk by Tom Igoe.
    Tom has produced a very well rounded book- well worth the money, and it has an entire chapter on fm transmitters.
    http://oreilly.com/catalog/9780596510510

    Comment by Rich Carthew | April 10, 2011 | Reply

  9. Fantastic explanation, specially those tricks and twists…

    Comment by Carlos Estrada | May 16, 2011 | Reply

    • Hello Carlos
      Thank you for your positive feedback, I really appreciate it.
      Cheers
      John

      Comment by John Boxall | May 16, 2011 | Reply

  10. Hello John,

    Is it mandatory to use the dereference operator (*) ? Why ?

    Comment by nesdnuma | June 10, 2011 | Reply

    • Yes, but the reason escapes me right now.

      Comment by John Boxall | June 11, 2011 | Reply

    • That’s the only way to let a function to directly manipulate its arguments. Instead of passing by value which would create a local copy of the variable in the function scope, you pass by reference thus the function gets the pointer to the variable not the variable value.. the function can then deference the variable to write in the correct slice of memory.

      Comment by Fabio Varesano | June 11, 2011 | Reply

      • Awesome, thanks for that Fabio

        Comment by John Boxall | June 28, 2011

  11. Hi there,

    now, how do I let the Arduino talk with two devices with identical I2C addreses?

    Comment by Ralf | June 25, 2011 | Reply

  12. I’m learning so much from this site. I have a simple question though. If a hex number like 1F = 31, what does the 0x in 0x1F mean?

    Thanks, Russ

    Comment by Russ | October 11, 2011 | Reply

    • The Arduino programming language has its origins in C, which prefixes all hexadecimal numbers with 0x. Very happy to hear you are learning from the site.
      cheers
      John

      Comment by John Boxall | October 11, 2011 | Reply

  13. lots of thanks for an informative tutorial!!

    Comment by Gayathri.T.N. | October 22, 2011 | Reply

    • Thank you, glad you enjoyed it.
      John

      Comment by John Boxall | October 22, 2011 | Reply

  14. Hi!
    M designing a part of student satellite which includes i2c protocol!
    I’m required to interface LPC1769 and a MEMS Gyro using I2C..
    can u please give me the interfacing details of interfacing…
    if not where can i get the information for it???
    plese help me out…!!!Hope you’ll do the needfull..

    Comment by Gayathri.T.N | October 22, 2011 | Reply

  15. Hi!
    First thank you for this really exciting tutorial.
    I have two questions concerning how to hook up 2 or more Interfaces via I2C.
    At the moment I would like to hook up this two devices simultaneously:

    http://www.sparkfun.com/products/8661
    AND
    http://www.varesano.net/projects/hardware/FreeIMU

    1) How can I find out if I will need a pull up resistor for SDA and SCL and how can I find out the size of it?

    2) In the setup of the heartrate monitor I have “Serial.begin(9600);” while in the example code for the FreeIMU I find “Serial.begin(115200);”.
    I this a problem? Sorry, but I am an absolute beginner in electronics.

    Hope someone can help and explain,
    Thomas

    Comment by Thomas | November 20, 2011 | Reply

    • The Polar monitor is simple enough, see http://bildr.org/2011/08/heartrate-arduino/. The FreeIMU will be a pain, from what I can see it runs on 3.3V not 5V – so will need some logic-level conversions for the I2C bus. Please ask the FreeIMU people about this. The value for pull-ups is going to be hard to determine as it depends on the distance on your circuit’s I2C bus and a few other factors. Disable the FreeIMU’s internal pull-ups and experiment with values of between 2k2 and 10k0 ohms.
      If the two devices talk at different serial speeds, there isn’t a way around that.
      good luck
      john

      Comment by John Boxall | November 20, 2011 | Reply

  16. Hi John,
    I’m a big fan of your Arduino tutorials. Great job. I started reading relatively late, but I hope to catch up soon. I really enjoyed your explanation of the I2C bus, and actually used that knowledge with a digital compass.
    I’m wondering if you could write a little about UART in one of the future installments. Some issues concerning serial communication like the RTS line etc. are still a bit unclear to me. Many thanks!

    Comment by Marek | February 9, 2012 | Reply

    • Thank you for your feedback Marek.
      Could you please be more specific in your request?
      Thanks
      John

      Comment by John Boxall | February 9, 2012 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,241 other followers