EEPROM External read super long - help plz

guys,
I need to read an external EEPROM 24C128. Also write...

My current code is below as a test... surely, it is faulty and that i need to fix.

#include <Wire.h>

#define DEBUG

#ifdef DEBUG
 #define DEBUG_PRINT(x)     Serial.print (x)
 #define DEBUG_PRINTDEC(x)     Serial.print (x, DEC)
 #define DEBUG_PRINTHEX(x)  Serial.print (x, HEX)
 #define DEBUG_PRINTLN(x)  Serial.println (x)
#else
 #define DEBUG_PRINT(x)
 #define DEBUG_PRINTDEC(x)
 #define DEBUG_PRINTHEX(x)
 #define DEBUG_PRINTLN(x) 
#endif

#define eeprom1 0x50    //Address of 24LC256 eeprom chip
#define WRITE_CNT 5
#define rxBufSize 25
#define txBufSize 35

char dbgStrRS232_rx[rxBufSize];
char command[10];    // Arbitrary Value for command size
char data[15];       // ditto for data size
int byteCount;

unsigned char rdata[32];
unsigned int i;

void setup(void) {
  Wire.begin(); // initialise the connection
  Serial.begin(9600);

  Serial.println(F("Key reader Powered ON"));

  //char somedata[] = "1;15CU01;X254ZB;CXDFVGFRTESDFREWEXSDCVBGF;101018;301218;"; // data to write

  //i2c_eeprom_write_page(eeprom1, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM

  //delay(100); //add a small delay

  //Serial.println("Memory written");

  Serial.println(F("Key reader Ready"));

}
 
void loop(){
  /*
  int addr=0; //first address
  byte b = i2c_eeprom_read_byte(eeprom1, 0); // access the first address from the memory

  while (b!=0){
    Serial.print((char)b); //print content to serial port
    addr++; //increase address
    b = i2c_eeprom_read_byte(eeprom1, addr); //access an address from the memory
  }
  Serial.println(" ");
  */

  SerialParser();

  if (strcmp(command, "0x50") == 0) {
    memset(command, 0, sizeof(command));
    DEBUG_PRINT("New KEY: ");
    char key[30];
    i2c_eeprom_read_buffer(eeprom1, 0, key, sizeof(key) );
    Serial.println(key);
    delay(2000);
  }

  DEBUG_PRINT("New KEY1: ");
    char key[50];
    i2c_eeprom_read_buffer(eeprom1, 0, key, sizeof(key) );
    delay(100);
    Serial.println(key);
    delay(2000);
    
  Serial.flush();
  
}

//Serial parser
void SerialParser(void) {
  //
  //  One command per line.  Eventually, Data may have multiple 
  //   fields separated by ":"
  //  Command Format: "up to 5 Letter command, up to 10 letter data<\n>"
  //                  No checking.
  //
  //  count will  be below Zero on a timeout.
  //  read up to X chars or until EOT - in this case "\n" 
  byteCount = -1;
  byteCount =  Serial.readBytesUntil('\n',dbgStrRS232_rx,rxBufSize);  
  delay(5);
  if (byteCount  > 0) {
      strcpy(command,strtok(dbgStrRS232_rx,","));
                 
      strcpy(data,strtok(NULL,","));             
  }
  memset(dbgStrRS232_rx, 0, sizeof(dbgStrRS232_rx));   // Clear contents of Buffer
  Serial.flush(); 
}

 
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
}

// WARNING: address is a page address, 6-bit end will wrap around
// also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
        Wire.write(data[c]);
    Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
}

// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
        if (Wire.available()) buffer[c] = Wire.read();
}

Now, char somedata[] = "1;15CU01;X254ZB;CXDFVGFRTESDFREWEXSDCVBGF;101018;301218;" is my data that I have to write... But the amazing part is, each semicolon is a specific field and i can just put them not in a single shot, but in blocks... Like :

char a[] = "1";
char b[] = "15CU01";
and so on....

And these are fixed length values... thus I can also write in a small chunk (as i2 has a limited buffer of 30 bytes max). [My max data will be 25 chars.

so please help me to correct the code for block wise write and read too.

After reading, finally I will concat the whole thing to send via Serial as you can see... But read and write in block... how???

Mishu~

Since you appear unfamiliar with the external eeprom, I would recommend that you get the code working with byte write functions. Don't worry about page or block writes. When writing a byte at a time the page boundaries are not relevant.

The upside is simplicity. The down side is speed.

When you have your code working as intended, you can then evaluate speed issues.

Reading does not involve page boundaries, and your i2c_eeprom_read_buffer() function looks OK.

cattledog:
Reading does not involve page boundaries, and your i2c_eeprom_read_buffer() function looks OK.

to be frank, it works... but with some limitation... means it does not read all (or probably write too).

So about writing, I was looking for a solution which will help me to write in a block... say from ADDR 0 till for 10 bytes... (because my data is fixed length, I can do it easily for each variables...)

Also, page write is not that big issue here for as I will write it for once, and read it for the rest of the life

to be frank, it works... but with some limitation... means it does not read all (or probably write too).

Can you please write a simplified sketch which demonstrates your issue. Do not include code which is commented out. You should separate the eeprom read/write from any key reading/parsing code if possible.

I need to read an external EEPROM 24C128. Also write..

Page size on that eeprom is 64 bytes. Block writes of multiples of 4 bytes with proper memory address management will also avoid page boundaries. Just make sure that any block write does not cross a page boundary. With more complexity, You can also use an external eeprom library like Jack Christensens extEEPROM.h which will handle all the page boundary issues for writes of any length. GitHub - JChristensen/extEEPROM: Arduino library to support external I2C EEPROMs.

Here is some demonstation code I wrote for another thread, which does block writes and reads in 16 byte chunks. It may give you some ideas.

//possible page boundary issue unless all writes at 16 bytes
#include <Wire.h>
#define ADDRESS 0x50 //Address of EEPROM

unsigned int memAddress = 0;//starting eeprom address
int totalBytes = 720;//total byte number multiple of 16
const byte blockLength = 16; //will avoid page boundary in eeprom
const byte numberOfBlocks = totalBytes/blockLength;

//test data visuallyto confirm pattern
byte fileData[][blockLength] =
{
  {0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
};

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

  for (int i = 0; i <= numberOfBlocks - 1; i++)
  {
    writeBytes( ADDRESS, memAddress, fileData[i], blockLength);
    memAddress += blockLength;
  }

  memAddress = 0;//reset address for read

  for (int i = 0; i <= numberOfBlocks - 1; i++)
  {
    readBytes(ADDRESS, memAddress, blockLength);
    memAddress += blockLength;
  }
}

void loop() {}

void writeBytes(int device, unsigned int Address, byte* data, byte len)
{
  Wire.beginTransmission(device);
  Wire.write(Address >> 8 ); //MSB
  Wire.write(Address & 0xFF); // LSB
  Wire.write(data, len);
  Wire.endTransmission();
  delay(5);//small delay for eeprom to save data
}

void readBytes(int device, unsigned int Address, byte len )
{
  byte readBuffer[len];
  Wire.beginTransmission(device); // I2C address
  Wire.write(Address >> 8); // bit shift for high byte of pointer address
  Wire.write(Address & 0xFF); // mask for the low byte
  Wire.endTransmission();
  Wire.requestFrom(device, len);
  Wire.readBytes(readBuffer, len);
  for (byte j = 0; j < 16; j++)
  {
    Serial.print(readBuffer[j], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

cattledog:
GitHub - JChristensen/extEEPROM: Arduino library to support external I2C EEPROMs.

This is not working... the test code compiles but gives error... and eventually it says no matching functions after i copy the codes from the site example. However, I discovered that this one i tried earlier and failed indeed.

I tried http://www.hobbytronics.co.uk/eeprom-page-write this one too and fforgot what happened... but writing seems somehow okey (as said, speed is not a factor as it will be write only once for a life). Reading is a factor as Arduino Wire has a 30byte buffer. Thus an addressing wise approach is far better i think for me... as my max data size will be 25byte. and there will be several data to read and write (each within 25byte length). Each data size is constant. Basically it will keep some pre defined value and pass key.

Trying your code though!!

Nope!! Nothing is practically helping me...

Okey, I need a neat code for the following:

char userData[] = "1;15CX01;X254ZB;";
char serialKey[] = "CXDFVGFRTESDFREWEXSDCVBGF;";
char validity[] = "101018;301218;";

these info needs to be saved in a neat way like in some predefined memory locations. I have a 256kb i2c eeprom and thus space is not a big deal. I even can keep the data in different pages... All I need is a neat workable codes to store them.

The reference and codes from the above did not worked at all... none of them... (But i'm sure wiring is OK) as i have found old junk data once...

aq_mishu:
All I need is a neat workable codes to store them.

Have you tried offering money in the Gigs section?

CtrlAltElite:
Have you tried offering money in the Gigs section?

come on... dont be so harsh!!!

I'm spending 2 nights and yet to finish it, but stuck in here... most sources are not working for some reason...

I followed this and came up with a blank screen.... nothing...

http://www.hobbytronics.co.uk/eeprom-page-write

All I need is a neat workable codes to store them.

Just store them a byte at a time. This is very similar to the function you have in your first posting, except without the unnecessary transfer of the byte to an int and with a small delay for the physical write.

void writeByte(int device, unsigned int add, byte data) 
{
  Wire.beginTransmission(device);
  Wire.write((int)(add >> 8)); // left-part of pointer address
  Wire.write((int)(add & 0xFF)); // and the right
  Wire.write(data);
  Wire.endTransmission();
  delay(5);//small delay for eeprom to save data
}

The reference and codes from the above did not worked at all... none of them... (But i'm sure wiring is OK) as i have found old junk data once...

If the code from post #3 did not produce the pattern of the input data when reading it back, there is something wrong with wiring or setup.

Have you confirmed that the eeprom is seen on the i2c bus by using an i2c scanner program?

Oky,
So I was using an UNO and that was for some reason, giving me a trouble. Changed the board to mega2560 and now it's fully working with the same link I have given... Write is successful in either a full shot, or in different pages, via addr 0, 64, 128 for 3 variables.

Now, reading for 3 variables via 3 run is fine... but when reading in a full single shot, then it is giving trouble. I want to see it like this:

1;15CX01;X254ZB;CXDFVGFRTESDFREWEXSDCVBGF;101018;301218;

But I can't exactly see it via the readEEPROM(eeprom1, 0, readData, sizeof(len)); where len = 57

that comes out as: 1;15CX01;X254ZB;CXDFVGFRTESDFREWFREWEXSDCVBGF;101018;301218;

I'm reading this way:

// read back the data 28 bytes at a time
  int phase = sizeof(readData)/28;
  for (i=0; i<=phase; i++) {
    readEEPROM(eeprom1, (i*28), readData, sizeof(readData));
    Serial.print(readData);
  }
  Serial.println();

EDIT: OK, I found the problem... it should be readEEPROM(eeprom1, (i*28), readData, 28); as I am using 28 bytes per shot!!

Now some additional testing and then I will confirm about this if everything is fine... But till then, thanks for all the help!!

Your code for the pattern helped me to flush the memory indeed for a better test of "WHAT IT GOT REALLY"

OK... Now it is working perfectly!! I will post the whole code for others later soon, so others can use it too...

here is the full code for future ref if someone needs:

#include <Wire.h>         //http://arduino.cc/en/Reference/Wire

#define DEBUG

#ifdef DEBUG
 #define DEBUG_PRINT(x)     Serial.print (x)
 #define DEBUG_PRINTDEC(x)     Serial.print (x, DEC)
 #define DEBUG_PRINTHEX(x)  Serial.print (x, HEX)
 #define DEBUG_PRINTLN(x)  Serial.println (x)
#else
 #define DEBUG_PRINT(x)
 #define DEBUG_PRINTDEC(x)
 #define DEBUG_PRINTHEX(x)
 #define DEBUG_PRINTLN(x) 
#endif

#define eeprom1 0x50    //Address of 24LC256 eeprom chip
#define txBufSize 35

unsigned char rdata[32];
unsigned int i;

char someData[] = "1;15CX01;X254ZB;CXDFVGFRTESDFREWEXSDCVBGF;101018;301218;";
int len = sizeof(someData);
char readData[64]; /estimate size (you need to know it unfortunately... each char is a byte.

void setup(void) {
  Wire.begin(); // initialise the connection
  Serial.begin(9600);

  Serial.println(F("Key reader Powered ON"));

  //writeEEPROM(eeprom1, 0, userData); //If you want to write  data in a page only...
  //writeEEPROM(eeprom1, 64, serialKey); //If you want to write  data in a page only...
  //writeEEPROM(eeprom1, 128, validity); //If you want to write  data in a page only...
  
  writeEEPROM(eeprom1, 0, someData); //For writing all the way, solving page boundary issues...

  delay(100); //add a small delay

  Serial.println("Memory written");

  // read back the data 28 bytes at a time (28 byte as 30byte is a buffer limit for reading
  // reading data doesn't suffer from the page boundary rules
  
  int phase = sizeof(readData)/28;
  for (i=0; i<=phase; i++) {
    readEEPROM(eeprom1, (i*28), readData, 28);
    Serial.print(readData);
  }
  Serial.println();
  Serial.println(F("Key reader Ready"));

}
 
void loop(){

  SerialParser();

  char key[28];
  int phase = sizeof(readData)/28;

  if (strcmp(command, "0x50") == 0) {
    memset(command, 0, sizeof(command));
    DEBUG_PRINT("New KEY: ");
    Serial.print(F("<"));
    for (i=0; i<=phase; i++) {
      readEEPROM(eeprom1, (i*28), readData, 28);
      Serial.print(readData);
    }
    Serial.println(F(">"));
  }

    // Printout will be like <xx;sasdd;xdafssdf;>
    Serial.println();
    delay(2000);
    
  Serial.flush();
  
}


void writeEEPROM(int deviceaddress, unsigned int eeaddress, char* data) 
{
  // Uses Page Write for 24LC256
  // Allows for 64 byte page boundary
  // Splits string into max 16 byte writes
  unsigned char i=0, counter=0;
  unsigned int  address;
  unsigned int  page_space;
  unsigned int  page=0;
  unsigned int  num_writes;
  unsigned int  data_len=0;
  unsigned char first_write_size;
  unsigned char last_write_size;  
  unsigned char write_size;  
  
  // Calculate length of data
  do{ data_len++; } while(data[data_len]);   
   
  // Calculate space available in first page
  page_space = int(((eeaddress/64) + 1)*64)-eeaddress;

  // Calculate first write size
  if (page_space>16){
     first_write_size=page_space-((page_space/16)*16);
     if (first_write_size==0) first_write_size=16;
  }   
  else 
     first_write_size=page_space; 
    
  // calculate size of last write  
  if (data_len>first_write_size) 
     last_write_size = (data_len-first_write_size)%16;   
  
  // Calculate how many writes we need
  if (data_len>first_write_size)
     num_writes = ((data_len-first_write_size)/16)+2;
  else
     num_writes = 1;  
     
  i=0;   
  address=eeaddress;
  for(page=0;page<num_writes;page++) 
  {
     if(page==0) write_size=first_write_size;
     else if(page==(num_writes-1)) write_size=last_write_size;
     else write_size=16;
  
     Wire.beginTransmission(deviceaddress);
     Wire.write((int)((address) >> 8));   // MSB
     Wire.write((int)((address) & 0xFF)); // LSB
     counter=0;
     do{ 
        Wire.write((byte) data[i]);
        i++;
        counter++;
     } while((data[i]) && (counter<write_size));  
     Wire.endTransmission();
     address+=write_size;   // Increment address for next write
     
     delay(6);  // needs 5ms for page write
  }
}
 
void readEEPROM(int deviceaddress, unsigned int eeaddress,  
                 unsigned char* data, unsigned int num_chars) 
{
  unsigned char i=0;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,num_chars);
 
  while(Wire.available()) data[i++] = Wire.read();

}