PDA

View Full Version : I2CEEPROMAnything



jimmayhugh
12-29-2013, 05:41 PM
I use EEPROMAnything (http://playground.arduino.cc/Code/EEPROMWriteAnything) to store my array of chip, action and PID structures in my TeensyPi and TeensyNet project. The limiting factor has always been the 2K of EEPROM on the Teensy 3.x boards, so I decided to use an external I2C EEPROM, the 24LC512 (http://ww1.microchip.com/downloads/en/DeviceDoc/21754M.pdf), to increase my capacity.

Following is I2CEEPROMAnything.h, which will replace EEPROMAnything.h in my code. This code supports up to 8 24LC512 chips, for a total of 4M of storage. It also supports 128-byte page writes for structures larger than 128 bytes.

To write to the EEPROM call:


eeWrite(uint16_t ee, const T& value, uint8_t device)

where "ee" is the address in the EEPROM where you want to start saving data, "value" is a pointer to the start of the data you want to save, and "device" is the I2C address of the EEPROM (0x50 to 0x57 for the 24LC512).

To read from the EEPROM call:


eeRead(uint16_t ee, T& value, uint8_t device)

where "ee" is the address in the EEPROM where you want to start reading data, "value" is a pointer to the start of the RAM area you want the data to go, and "device" is the I2C address of the EEPROM (0x50 to 0x57 for the 24LC512).

Here's the I2CEEPROMAnything.h file, it can be saved as a library file in your sketchbook.



/********************

I2CEEPROMAnything.h

Version 0.0.1
Last Modified 12/28/2013
By Jim Mayhugh

Based on code from http://playground.arduino.cc/Code/EEPROMWriteAnything

Use external EEPROM (24LC512) for structure storage, and uses Teensy 3.X board.

****NOTE****
This code has been tested on the Teensy 3.x boards from http://www.pjrc.com .
In order to take full advantage of the capabilities of the Teensy 3.x, the following
must be placed in the Teensyduino Wire.h file:

#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define BUFFER_LENGTH 130
#else
#define BUFFER_LENGTH 32
#endif

replacing
#define BUFFER_LENGTH 32
****NOTE****

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

This software uses multiple libraries that are subject to additional
licenses as defined by the author of that software. It is the user's
and developer's responsibility to determine and adhere to any additional
requirements that may arise.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


*********************/

#include <WProgram.h>

template <class T> int eeWrite(uint16_t ee, const T& value, uint8_t device)
{
const byte* p = (const byte*)(const void*)&value;
int32_t i, totalSent = 0, leftToSend, sendNext;
const uint8_t maxBufferSize = 128; // on-chip page buffer of 24LC512
uint8_t sent = 0;
leftToSend = sizeof(value);
do
{
if(leftToSend >= maxBufferSize)
{
sendNext = maxBufferSize;
}else{
sendNext = leftToSend;
}
Wire.beginTransmission(device);
Wire.send((int)(ee >> 8)); // MSB
Wire.send((int)(ee & 0xFF)); // LSB
for (i = 0; i < sendNext; i++)
{
Wire.write(*p++);
}
Wire.endTransmission();
delay(50);
leftToSend = leftToSend - sendNext;
ee = ee + maxBufferSize;
totalSent = totalSent + sendNext;
}while(leftToSend > 0);
Wire.endTransmission();
delay(50);
return totalSent;
}

template <class T> int eeRead(uint16_t ee, T& value, uint8_t device)
{
byte* p = (byte*)(void*)&value;
uint32_t i, totalRead, leftToRead, readNext;
const uint8_t maxBufferSize = 128;
uint8_t received;
leftToRead = sizeof(value);
do
{
if(leftToRead >= maxBufferSize)
{
readNext = maxBufferSize;
}else{
readNext = leftToRead;
}
Wire.beginTransmission(device);
Wire.send((int)(ee >> 8)); // MSB
Wire.send((int)(ee & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(device, readNext);
for (i = 0; i < readNext; i++)
{
if(Wire.available())
{
*p++ = Wire.read();
}
}
leftToRead = leftToRead - readNext;
ee = ee + maxBufferSize;
totalRead = totalRead + readNext;
}while(leftToRead > 0);
return totalRead;
}


I have done some testing and am reasonably sure that it works as advertised, but as always suggestions to improve the code are welcome.

I hope someone finds this useful.

Headroom
12-29-2013, 09:01 PM
While I have no immediate need it's very good to know that this exists. Libraries like these are tremendously useful. For me that's the one thing that really stands between very quickly moving from a concept to a functioning prototype. Thanks for posting!

Also very nice chip. There is a variant that allows up to 1MHz I2C bus speed, which complements the Teensy3.x nicely.

jimmayhugh
12-30-2013, 11:52 AM
There is a variant that allows up to 1MHz I2C bus speed, which complements the Teensy3.x nicely.


Yeah, I bumped my I2C speed up to 400KHz with no ill effects.