Previous Entry Share Next Entry
Tutorial: i2c SRAM for the Arduino
maha_peek_cartoon
tibman wrote in arduino_related

External RAM for the arduino? Yes please!


This one is easy, once you get the part. I honestly could only fine one supplier of DIP style i2c ram, Digikey had some from NXP but NXP says it is discontinued. The date on the datasheet is 1999 (/me giggles). The RAM works very well though. I will give you everything you need to get this tiny ram chip up and running, without needing to decipher the datasheet.

Part Description: IC SRAM 256x8 bits w/ i2c INTRFC 8-DIP
Digikey part number: PCF8570P
Price from Digikey: $2.21 US on 6 Aug 09

First, i'm going to answer "but why not flash/eeprom?". Because i want to go crazy on my RAM without worrying about limited write cycles or wear leveling. Also i wanted speed.. with eeprom you have to respect read/write delays. There is zero delay with this ram.

Anyways, on with it! There are two parts, wiring it up and coding it. Wiring is easy, follow the diagram. Serial Data is analog 4 and Serial Clock is analog 5 on your arduino (the main parts of i2c).

arduino,ram,electronics,i2c
Wiring diagram

The ram's i2c address is 1010xyz. To make a pin zero, connect it to ground. To make it one, connect it to +5 v. I just connected all three to ground which makes the address 1010000(binary)or 0x50(hex) or 80(integer).

Ok, the next part is the code. This one took me a little bit to get the way i wanted it, but you can take this code without having to reinvent the wheel. It's just a simple read and simple write function. Feel free to expand them into multi-byte read/writes.



//Write to i2c SRAM
void memw(int i2c_addr, word address, byte data)
{
  Wire.beginTransmission(i2c_addr);
  Wire.send((byte)lowByte(address));
  Wire.send((byte)highByte(address));
  Wire.send(data);
  Wire.endTransmission();
}

//Read from i2c SRAM
byte memr(int i2c_addr, word address)
{
  Wire.beginTransmission(i2c_addr);
  Wire.send((byte)lowByte(address));
  Wire.send((byte)highByte(address));
  Wire.endTransmission();
  Wire.requestFrom(i2c_addr,1); //only one byte

  if(Wire.available())
  { return Wire.receive(); }
  return B00000000; //FIXME - Report an error here
}



To enable i2c on your arduino is easy, make the start of your sketch look like this:


#include <Wire.h>

void setup()
{
  Wire.begin();
}



Finally to actually use the ram, here's an example sketch that writes "arduino_related" to ram and reads it from memory, outputing to Serial.


#include <Wire.h>

//ram i2c address
int addr = 80; //B1010000;

//string to write
byte str[] = "arduino_related";

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  //write str to ram
  for(int i=0; i<sizeof(str)-1; i++)
    {
      memw(addr,i*8,str[i]);
    }
}

void loop()
{
  for (int i=0; i<sizeof(str)-1; i++)
  {
    Serial.print(memr(addr,i*8));
  }
  Serial.println(" is awesome.");
  delay(500);
}

//Write to i2c SRAM
void memw(int i2c_addr, word address, byte data)
{
  Wire.beginTransmission(i2c_addr);
  Wire.send((byte)lowByte(address));
  Wire.send((byte)highByte(address));
  Wire.send(data);
  Wire.endTransmission();
}

//Read from i2c SRAM
byte memr(int i2c_addr, word address)
{
  Wire.beginTransmission(i2c_addr);
  Wire.send((byte)lowByte(address));
  Wire.send((byte)highByte(address));
  Wire.endTransmission();
  Wire.requestFrom(i2c_addr,1); //only one byte

  if(Wire.available())
  { return Wire.receive(); }
  return B00000000; //FIXME - Report an error here
}



That's it, tutorial complete. Feel free to ask questions or suggestions for improvements.


  • 1
is sizeof() zero based? I wouldn't think so.. I would imagine it returns the size of the object being passed in. so for the byte[] str it would be 15 being returned.

for your loop, i don't think you need the -1 for the sizeof(). If you start at zero and go to less-than 15 (14) that would be 15 elements on a zero based scale. subtracting one from that would make you remove one byte of data from every read and write.

I haven't tested this out, I'm just reporting my observation.

There is actually an extra element at the end of the string '\0', you can read it and print it but it'll come up as a block or something.

I let it write that extra part incase you needed to find the end of the string in ram later. There are undoubtedly better ways to read/write strings to memory, feel free to expand the functions.

correction! i didn't write the \0 to ram, no way to know when the string actually ends.

savings bytes

(Anonymous)
You could save a few bytes of ram by making the addr a #define instead of a global variable. Also, it should only be 1 byte, using an int (2 bytes) is wasting a byte. Otherwise, great post!

  • 1
?

Log in