8.25.2010

Serial EEPROM Memory

So on my journey to ultimately one day making a killer quadcopter or other autonomous aerial vehicle, I have identified a few key technologies that I need to get a good grasp on that will ultimately be used in any project. Dove-tailing off my previous tinkering with my GPS and with an impending family trip coming up I was hoping to have a working GPS logger ready to capture the path we take on our daily adventures. (Not sure how the wife is gonna feel about me tinkering at night on vacation?!)

So besides getting a full SD card logger ready I thought I might try to use some serial EEPROMs from Microchip. I have had an account with Microchip all the way back to my undergrad days and it is very easy and very quick to get free samples from them, and totally free is my favorite price.

So I went to their website and started searching through their memory product line. I was initially interested in checking out their Flash based product line but that link sent me to another website, SST - Silicon Storage Technology Inc., that wasnt managed through Microchip Sample website. To get samples of their flash products you have to fill out a request form.....that wasnt going to happen. So back to the Microchip website and looking at some Serial EEPROM devices. Since Arduino has I2C and SPI interfaces I started looking for products that interface through those protocols. I eventually settled on the 24XXYYY family of devices that communicate through I2C. Their sizes range from 128 bit all the way up to 8 MBit and up to 8 separate devices can be placed on the same I2C bus to expand your storage capabilities even further. Unfortunately the largest EEPROM, the 24FC1025, had a long lead time of something like 46 weeks (RIDICULOUS!) so I wound up placing an order for the 24FC512 (which will more than accomplish what I am doing.

So after some google and forum searching for Arduino and Serial EEPROM help and reading through the 24FC512's datasheet I figured I had found enough to try and get it working. A few of the more helpful sites are:
Arduino Tutorial
Arduino Forum with links to the Extended Database Library and a 24ACas well as a sample Arduino program for working with the 24FC512

Basically most of my work was done for me. I just needed to ensure I hooked up everything correctly, like the Arduino to EEPROM I2C interface, and not surprisingly it worked exactly like I had hoped.

To use my sketch you must download and place in your Arduino library these two files:
Extended Database Library
AT24C1024 Library

Once you have those you can upload the sketch below, and assuming everything is connected properly you should be good to go.

The Arduino sketch looks like this:


#include "WProgram.h"
#include

// Use the 24XX512 EEPROM as storage
#include //Handles the I2C interface
#include // Should be compatible with 24XX512 series in this instance

// From the 24XX512 datasheet:
//
// The Chip Select bits A2, A1 and A0 can be used to expand the
// contiguous address space for up to 4 Mbit by adding up to eight
// 24XX512 devices on the same bus.
//
// So, each device must be have their address pins wired as listed below to
// create a single, contiguous address space across one or more devices.
//
// Example - 1 device:
// Device connections: A0->GND, A1->GND, A2->GND
// Uncomment only the #define TABLE_SIZE 65536 line below.

// Example - 3 devices:
// Device 1 connections: A0->GND, A1->GND, A2->GND
// Device 2 connections: A0->+5V, A1->GND, A2->GND
// Device 3 connections: A0->GND, A1->+5V, A2->GND
// Uncomment only the #define TABLE_SIZE 196608 line below.
//
// Uncomment the ONE line appropriate for your platform.
//#define TABLE_SIZE 65536 // 1 device: A0->GND, A1->GND, A2->GND
//#define TABLE_SIZE 131072 // 2 devices: A0->+5V, A1->GND, A2->GND
#define TABLE_SIZE 196608 // 3 devices: A0->GND, A1->+5V, A2->GND
//#define TABLE_SIZE 262144 // 4 devices: A0->+5V, A1->+5V, A2->GND
//#define TABLE_SIZE 327680 // 5 devices: A0->GND, A1->GND, A2->+5V
//#define TABLE_SIZE 393216 // 6 devices: A0->+5V, A1->GND, A2->+5V
//#define TABLE_SIZE 458752 // 7 devices: A0->GND, A1->+5V, A2->+5V
//#define TABLE_SIZE 524288 // 8 devices: A0->+5V, A1->+5V, A2->+5V

// default to the smallest - 1 device
#ifndef TABLE_SIZE
#define TABLE_SIZE 65536
#endif

// The number of demo records that should be created. This should be less
// than (TABLE_SIZE - sizeof(EDB_Header)) / sizeof(LogEvent). If it is higher,
// operations will return EDB_OUT_OF_RANGE for all records outside the usable range.
#define RECORDS_TO_CREATE 327

// Arbitrary record definition for this table.
// This should be modified to reflect your record needs.
struct LogEvent {
int Lat;
int Lon;
int UTC_Time;
}
logEvent;

// Create an EDB object with the appropriate write and read handlers
EDB db(&E24C1024::write, &E24C1024::read);

// Run the demo
void setup()
{
Serial.begin(9600);
Serial.println("Extended Database Library + 24XX512 EEPROM Demo");

randomSeed(analogRead(0));

// create a table with starting address 0
Serial.print("Creating table...");
db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
Serial.println("DONE");

recordLimit();
countRecords();
createRecords(RECORDS_TO_CREATE);
countRecords();
selectAll();
countRecords();
deleteAll();
countRecords();
// createRecords(RECORDS_TO_CREATE);
// countRecords();
// selectAll();
// countRecords();
// deleteAll();
// countRecords();
}

void loop()
{
}

void recordLimit()
{
Serial.print("Record Limit: ");
Serial.println(db.limit());
}

void deleteAll()
{
Serial.print("Truncating table...");
db.clear();
Serial.println("DONE");
}

void countRecords()
{
Serial.print("Record Count: ");
Serial.println(db.count());
}

void createRecords(int num_recs)
{
Serial.print("Creating Records...");
for (int recno = 1; recno <= num_recs; recno++)
{
logEvent.Lat = recno;
logEvent.Lon = random(1, 125);
logEvent.UTC_Time = random(126, 250);
EDB_Status result = db.appendRec(EDB_REC logEvent);
if (result != EDB_OK) printError(result);
}
Serial.println("DONE");
}

void selectAll()
{
for (int recno = 1; recno <= db.count(); recno++)
{
EDB_Status result = db.readRec(recno, EDB_REC logEvent);
if (result == EDB_OK)
{
Serial.print("Recno: "); Serial.print(recno);
Serial.print(" LAT: "); Serial.print(logEvent.Lat);
Serial.print(" LON: "); Serial.print(logEvent.Lon);
Serial.print(" TIME: "); Serial.println(logEvent.UTC_Time);
}
else printError(result);
}
}

void printError(EDB_Status err)
{
Serial.print("ERROR: ");
switch (err)
{
case EDB_OUT_OF_RANGE:
Serial.println("Recno out of range");
break;
case EDB_TABLE_FULL:
Serial.println("Table full");
break;
case EDB_OK:
Serial.println("OK");
break;
default:
Serial.println("Unknown Error");
break;
}
}


Hopefully this helps those looking to use Serial EEPROMs in their projects. I leaned very heavily on the work of others but thats usually the best way to get up to speed. Once you have a working knowledge its much easier to dive back in and truly understand the internal workings of the code.

No comments:

Post a Comment