I2C EEPROM Class on playground

While experimenting with an I2C EEPROM I encountered the problem that the Wire library only wrote in (relative) small chunks to EEPROM so I wrote a simple library to write and read objects of "any" size to an I2C EEPROM. The EEPROM used was a 24LC256 but it should work with other too (not confirmed).

The library and a small example can be found on - Arduino Playground - LibraryForI2CEEPROM - and as allways remarks, comments and improvements are welcome.

Rob

I just want to draw to your attention that the 24LC256 "wraps around" its internal addressing on 64-bytes boundaries. So for example, if you write 4 bytes to address 62, it actually ends up writing to 62, 63, 0 and 1.

So any code that attempts to write "large buffers" needs to address this, otherwise you need to add a warning that not only can it simply not write more than 64 bytes at a time, it has to not cross a 64-byte boundary. So in my example, even writing 3 bytes to address 62 would not work as expected.

I should also point out that your test program writes 102 bytes to the chip, and then reads it back into a 100-byte array - so that is going to overwrite memory somewhere.

In principle the library is a great idea, you just need to handle the wrapping issue.

Hi Nick,

thanks for this insight, I will dive into it and come asap with an updated version. I understand that in my sample code I started at address 0 with chuncks of 16 which is a divider of 64 so it worked by accident.

Do you know if other EEPROMS have similar issues?

wrt the test program, it only reads 40 bytes from memory into the 100 byte buffer, but its a risk youre right.

Updated the code to be 1.0 compatible (Thanks Craig)

See - Arduino Playground - HomePage - for the latest version,

As always comments and improvements are welcome,

Today I updated the I2CEEPROM class to version 1.0.04 See - Arduino Playground - HomePage - ,
or - Arduino/libraries/I2C_EEPROM at master · RobTillaart/Arduino · GitHub -

I fixed some bugs and refactored the code. Most important the 1.0.04 version is on average substantial faster than the 1.0.00 version. This is done by optimizing internal buffer sizes to maximize the use of the TWI buffer, and by replacing the hardcoded 5 millisecs write latency after every write by a polling mechanism before a read or a write. The advantage is that the code will only wait for as long as needed and that will be less than 5 millis() quite often. This part can be simplified even further to get a smaller footprint, and to get the readByte() performance to previous level again but that is under test right now.

The performance numbers: (from the test sketch, UNO, IDE 1.5.4) - just as indication

400 KHZ I2C
reference 1.0.00

TEST: timing writeByte() 5164
TEST: timing writeBlock(50) 22120
TEST: timing readByte() 212
TEST: timing readBlock(50) 2476
total: 29972

1.0.04

TEST: timing writeByte() 220
TEST: timing writeBlock(50) 8600
TEST: timing readByte() 3768 // due to previous write!!
TEST: timing readBlock(50) 2252
total: 14460

(delay(5) added between tests to simulate other code)
TEST: timing writeByte() 212
TEST: timing writeBlock(50) 5996
TEST: timing readByte() 264
TEST: timing readBlock(50) 2248
total: 8720

100 KHZ I2C
reference 1.0.00

TEST: timing writeByte() 5452
TEST: timing writeBlock(50) 26348
TEST: timing readByte() 572
TEST: timing readBlock(50) 7020
total: 39402

optimized delay = 1.0.04

TEST: timing writeByte() 576
TEST: timing writeBlock(50) 12948
TEST: timing readByte() 4148
TEST: timing readBlock(50) 6360
total: 24032

(delay 5 added inbetween tests)
TEST: timing writeByte() 588
TEST: timing writeBlock(50) 10016
TEST: timing readByte() 712
TEST: timing readBlock(50) 6340
total: 17656

As always comments and remarks are welcome,

Today I updated the I2CEEPROM class to version 1.0.05 on GITHUB

  • 1.0.05
  • improved waitEEReady() -> on average far lower write latency than 1.0.00 reference.
  • added determineSize -> behind #ifdef to keep base lib small
  • improved comments
  • corrected return type readBlock()
  • updated test sketch

The determineSize() worked well for a 24LC256 (32KB) and a 24LC512 (64KB).
It is a non destructive test, that copies a number of memories and writes patterns to these locations to see address folding.

performance figures - note readByte() is on par with 1.0.00 version again.

reference 1.0.00
------------------
TEST: timing writeByte()     5164
TEST: timing writeBlock(50)  22120
TEST: timing readByte()      212
TEST: timing readBlock(50)   2476
total: 29972

 - 1.0.05
--------------------------------------
TEST: timing writeByte()	164
TEST: timing writeBlock(50)	8480
TEST: timing readByte()		3788  // delayed due to the previous write
TEST: timing readBlock(50)	2208
total: 14640 = 49%

(delay(5) between calls)
TEST: timing writeByte()	168
TEST: timing writeBlock(50)	5960
TEST: timing readByte()		216  // on par again
TEST: timing readBlock(50)	2140
total: 8484 = 28%
reference 1.0.00
-----------------
TEST: timing writeByte()     5452
TEST: timing writeBlock(50)  26348
TEST: timing readByte()      572
TEST: timing readBlock(50)   7020
total: 39402

- 1.0.05
--------------------------------------
TEST: timing writeByte()	444
TEST: timing writeBlock(50)	12832
TEST: timing readByte()		4160   // delayed due to the previous write
TEST: timing readBlock(50)	6096
total: 23530 = 60%

TEST: timing writeByte()	452
TEST: timing writeBlock(50)	9888
TEST: timing readByte()		576
TEST: timing readBlock(50)	6084
total: 17000 = 43%

[did not upgrade the playground yet]

updated the playground to 1.0.05 - Arduino Playground - HomePage -

updated the playground to 1.1.00 on github

Note: the playground is not updated yet (still 1.0.05) - Arduino Playground - HomePage -

updated the version to 1.2.01 on github

The playground is still on 1.0.05

  • support for Due (thanks to Tyler F.)
  • support for smaller and larger (thanks to Tyler F.)
  • refactoring

hi sir ,
i have written a program for ardiuno with eeprom 24lc512. but i am not getting an output.
please go through this.
thanks
yogesh

#include <Wire.h>

unsigned char rdata[32];

#define ADDRESS 0x50 
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  delay(15);
  unsigned int i;
  int len;
  char str_data[]={"Hello-1234567890\n"};
  len=strlen(str_data);
  //Serial.println (strlen (str_data));
  Serial.println(len);
  
  eepromWrite(ADDRESS,i*len,str_data);
  delay(5);
  Serial.println("DATA READ");
  for(i=0;i<10;i++) {
  eepromRead(ADDRESS,(i*28),rdata,28);
  Serial.write(rdata,28);
  }
  
}

void loop() {

}
void eepromWrite(byte highAddress , byte lowAddress, char* data)
{
  unsigned char counter=0, i=0;
  Wire.beginTransmission(ADDRESS);
  Wire.write(highAddress);
  Wire.write(lowAddress);
  counter=0;
  do{ 
        Wire.write((byte) data[i]);
        i++;
        counter++;
       // Serial.print(counter);
        //Serial.print(i);
     } while((counter<16)); 
  Wire.endTransmission();
}

byte eepromRead(byte highAddress , byte lowAddress, unsigned char* data,unsigned int num_chars)
{
   unsigned char i=0;
  Wire.beginTransmission(ADDRESS);
  Wire.write(highAddress);
  Wire.write(lowAddress);
  Wire.endTransmission();

  Wire.requestFrom(ADDRESS,num_chars);
  while(!Wire.available()) data[i++] = Wire.read();
  {
    
  }
  
  
}