Thursday, February 19, 2009

I2C EEPROM for the Arduino

The Arduino is a nifty little board as most of you probably know already. I was doing a school project on it and found that I needed some external storage. Now, there are a lot of storage options available. SD cards and EEPROM on the SPI bus seem to be a popular choice, but I couldn't sacrifice 4 I/O pins just for storage.

I found code and tutorial for using I2C EEPROMs on the Arduino which was perfect since it would only take up 2 pins (pin 4 and 5) and I could put up to 8 EEPROMs on a single bus. The problem was that the tutorial was in Portuguese, (and I found another one in Spanish) so I ended up just fumbling through it myself. For the rest of you, here's the English guide.

The EEPROM Chip that i used was AT24C256B which I bought from Digi-key for $1.43, but any 24XX series EEPROM should be the same. Sparkfun carries the 24LC256 for $1.95 if you don't want to pay for Digi-key's ridiculous shipping charges (after shipping, Sparkfun will be much cheaper). The ones I listed above are in DIP-8 package and provide you with 256Kbits of storage (32KBytes) but you can purchase these in different packages and capacities. Since the 24LC is cheaper, the rest of the tutorial will assume using 24LC.

Wiring it together is super easy. To save everyone the trouble, I'll lay it out simple and straight forward:

Pin 1 2 and 3 determine the address of the chip; I2C uses 7 bit addresses + 1 control bit. With the code available on the Arduino Playground link above, you don't have to worry about the control bit. The EEPROM chip's address in binary will be 1010XXX where XXX is Address 2, Address 1, and Address 0 in that order. For example, if Pin 1 2 3 are Low Low High in that order, the binary address will be 1010001, or Hex 0x50.

For simplicity, I connected them all to Ground, thus giving me address of 1010000, or hex 0x50. It is important to remember to pull SDA and SDL up to 5V using a 1K resistor since those pins aren't pulled up internally at either end. Failing to pull them up will result in garbage when communicating. The picture below shows how I wired up my EEPROM:



The last part is actually using the code in your software. Since the creator for the functions linked above hasn't created a .h file for his stuff, you will simply have to copy and paste the entire snippit to the beginning of your code. Click here to get the code from Arduino Playground.

The code includes four functions i2c_eeprom_write_byte, i2c_eeprom_write_page, i2c_eeprom_read_byte, and i2c_eeprom_read_buffer. They are self explanatory if you read the code; for example, to write the data byte "0xAB" to the 1st block (remember a 256kbit EEPROM has 32708 blocks available) of the EEPROM whose address is 0x50, you would use:

i2c_eeprom_write_byte( 0x50, 1, 0xAB );

And to read the data you would write:

temp = i2c_eeprom_read_byte( 0x50, 1 );

That's it for this simple tutorial, those who want more information can read the EEPROM's datasheet and the details of the code provided.

Update: I found another guy who has a tutorial (Although it is in Spanish) of this up in his blog. He even has a picture of it all wired up on the breadboard. Click the picture below to jump to his tutorial

9 comments:

  1. Thanks so much for this tutorial. Waiting for mine to come in the mail :]

    ReplyDelete
  2. You write,
    "The EEPROM chip's address in binary will be 1010XXX where XXX is Address 2, Address 1, and Address 0 in that order. For example, if Pin 1 2 3 are Low Low High in that order, the binary address will be 1010001, or Hex 0x50"

    You meant "Hex 0x51", correct?

    ReplyDelete
  3. The pull-up resistors on the Arduino are being used when using the wire library. So the pull-up resistors in this circuit are probably not needed after all.

    Here's a copy-paste from http://www.arduino.cc/playground/Learning/I2C :

    ***
    Wire library will enable ATMEL internal Pullup's. So using additional pullup's with a short bus may not be required, for example interface only a single nearby EEPROM.
    ***

    ReplyDelete
  4. I've been using this code with a Microchip 24aa1025 EEPROM. It was only working intermittently for me until I realised it doesn't like consecutive read and write operations. I've added a delay of 5ms before each read and write and it seems to work fine now. Has anyone else had this problem, and is this the best way to fix it?

    ReplyDelete
  5. @ DontPanic:
    Below two snippets of the 24xx256 datasheet. It seems using a 5ms delay between writes is a good choice.
    "5 ms max write-cycle time"

    "This initiates
    the internal write cycle and during this time, the
    24XX256 will not generate acknowledge signals
    (Figure 6-1). If an attempt is made to write to the array
    with the WP pin held high, the device will acknowledge
    the command but no write cycle will occur, no data will
    be written, and the device will immediately accept a
    new command."

    ReplyDelete
  6. by my math (2^15) there should be 32768
    blocks am i doing something wrong???

    ReplyDelete
  7. hi,

    Couple of things I would like to clear up before you guys go scratching your head like i did.

    1. Pull up resistors NOT required.

    2. Pins 4 & 5 are Analog pins NOT digital!

    3. Dont forget to include Wire.begin() in void Setup() function.

    4. try pastebin.com/f3a36644b code to see any output!

    Thanks and hope these tips help. Good luck on your project.

    ReplyDelete