help needed to store a string array in the EEPROM

Hi Everyone,

I have programmed an RFID reader: I can erase the list of all my authorized cards/tags, add them , validated if a card is authorized or not, etc ... Everything works fine.

my problem, is that as soon as I power off the Nano, everything is lost ! So I figured I could save the authorized list in EEPROM.

IDs read from the RFID tag are 12 bytes long that are transformed into a string for comparison, etc ... I have provision for a max of 50 tags (MyTags[0] to MyTags[49], type = String).

even if the length is 12 bytes long, I want to store the last 10 bytes, as the first ones are always the same: that way, each tag's byte would be store as address xx0 to xx9 (I like when things are aligned ...). So 50 Tags X 10 Bytes = 500 bytes...it would fit in the internal EEPROM !

I am totally lost on how to do that !!!

I need help, to : - on boot, load the list of authorized tag's ID that are allowed (as MyTags[0] to MyTags[49}) - When a button is pressed, re-write the whole list of who's authorized to the EEPROM

eventually, I want to use an external EEPROM (so it can be replaced when written/read too many times) but for now, if someone can help me with the internal one, I can probably figure out the external one !!!

Thanks in advance !

Just write the bytes of each string one at a time to the EEPROM. There is nothing difficult about it. If you have n characters then you have n / 1024 slots in the EEPROM to store the data. Just look at my RFID sequencer project for a code example but I used only four bytes and had it has a number not a string, this made it more efficient.

http://www.thebox.myzen.co.uk/Hardware/RFID_Sequencer.html

I get it that I have to write one byte at a time....

my issue is to take for example:

MyTags[5], which is contain "12345ABCDE" and "fraction" it into 10 bytes, so I can store them in the EEPROM at address 50 to 59...

Yes that’s right.

MyTags[5], which is contain “12345ABCDE”

If you split that into numbers then it is only five bytes.
0x12
0x23
0x45
… and so on.

does it mean that the EEPROM is 16 bits ?

my question is still unanswered: how do I "fraction" my string, to be able to store it ?

No it is 8 bits, a number like 0x12 is just an 8 bit number.

To split up the number it depends on how it is stored, with MyTags[5] assuming it is a char array then just EPROMaddress = MyTag[0] EEPROM address + 1 = MyTag[1] And so on. Only you use the EEPROM write function. Have you looked at the code in that project? There is a function that does this.

Using the right data structure makes this very simple. Rather than using strings, use byte arrays...

byte MyTags[50][10];

then do this...

void writeTags(byte *data, int length) {
  for (int i=0;i

Mike: I have looked at your RFID sequencer, and don't take it wrong, but for a beginner like I am, it is overwhelming !!!

I thought that every element extracted from a string, would be considered as an ASCII character, therefore taking the full 8 bits ...

David: I will read about Byte array, and make some tries ! Might be my solution !

Thanks to both of you ....

jouellet: I thought that every element extracted from a string, would be considered as an ASCII character, therefore taking the full 8 bits ...

It's only an ASCII character if you decide it's an ASCII character. A byte (unsigned, so we don't have to worry about negative numbers), is simply a small unit of memory that will hold the numbers 0 through 255, or in another base, 0x00 through 0xff. A string consisting of two ASCII numbers can definitely be held in a single byte, making it far better for storage in an EEPROM.

The Arduino is fast enough to do the conversion, both for making a string into a series of bytes for storage, and for making it into a string of bytes for comparison, without you sensing a slow operation

t is overwhelming

OK The relevant functions are:-

unsigned long tokenInVar(){
  unsigned long number = 0;
       for(int i=0; i<8; i++) number = (number << 4) | convertFromHex(int(token[i]));
   return(number);
}

unsigned long convertFromHex(int ascii){ 
  if(ascii > 0x39) ascii -= 7; // adjust for hex letters upper or lower case
  return(ascii & 0xf);
}

To convert a token in a string into a long int, note this gives you 4 bytes or 32 bits, good for most RFID tokens. If you want more then use a long long, that gives you 64 bit numbers. Once in number form they are compared just like you compare any other number. The token is in and array of chr token or C string ( note this is not String ) Then to store use:- ``` void saveToken(int point){ // saves the token in EEprom memory at point    EEPROM.write(point, (tokensOnBoard[0] >> 24) & 0xff);    EEPROM.write(point+1, (tokensOnBoard[0] >> 16) & 0xff);    EEPROM.write(point+2, (tokensOnBoard[0] >> 8) & 0xff);    EEPROM.write(point+3, tokensOnBoard[0] & 0xff);    EEPROM.write(point+4,value[6]);    EEPROM.write(point+5,value[7]);    EEPROM.write(point+6,value[8]); } ``` This stores the token as 4 bytes plus three other values that my program needed to store, you might not need this. They were the MIDI channel, note number and velocity associated with each token. The EEPROM is split up into slots of 7 bytes each and that function takes in a pointer to that slot or EEPROM address called point. Note how the big number is split up into bytes using the >> shift right operator and the bitwise AND operator & to mask off parts of the word just leaving a byte. Another function you will have to implement is one to find the next free slot in the EEPROM when storing a new token. ``` int findFreeEntry(){   int i = 0;   boolean found = false;   while( found == false && i < 1000){     if( EEPROM.read(i) == 0xff && EEPROM.read(i+1) == 0xff && EEPROM.read(i+2) == 0xff && EEPROM.read(i+3) == 0xff ) found = true;     if(!found) i +=7;    }      if(found) return i; else return -1; } ``` Also this searches the EEPROM for a match to a given token:- ``` * int matchToken(unsigned long token){   int i = 0;   boolean found = false;   while( found == false && i < 1000){     if( EEPROM.read(i) == ((token >> 24)& 0xff) &&  EEPROM.read(i+1) == ((token >> 16)& 0xff)             &&  EEPROM.read(i+2) == ((token >> 8)& 0xff) &&  EEPROM.read(i+3) == (token & 0xff) ){               found = true;           }           if(!found) i +=7; // move on to the start of the next entry   }   if(found) return i; else return -1; }* ```

lar3ry: A string consisting of two ASCII numbers can definitely be held in a single byte, making it far better for storage in an EEPROM.

That's a little confusing. In C, as string is a null-terminated character array - only an empty string could be held in a single byte. The ASCII digit '1' has the value 49 (0x31), and would therefor fill a byte.

AWOL:

lar3ry: A string consisting of two ASCII numbers can definitely be held in a single byte, making it far better for storage in an EEPROM.

That's a little confusing. In C, as string is a null-terminated character array - only an empty string could be held in a single byte. The ASCII digit '1' has the value 49 (0x31), and would therefor fill a byte.

In the context of the thread, you can store "12" in a single byte by making it 12, whih is clearly able to be crammed into a byte.

Pardon the late reply. I am catching up on unread replies.

for a beginner like I am, it is overwhelming !!!

Like you, I do not have a lot of experience with writing code, and have difficulty understanding some advanced concepts.

Here is some simple code reading and writing 2d character arrays into the internal eeprom. It may not be efficient, it may not be concise, and it is not generic since it leverages off your 10 byte data. On the other hand, it doesn't use [u]S[/u]trings, or pointers. It may get criticism from the more advance folks on the board, but it puts your id data in and pulls it out, and it may help get you get started in the right direction.

#include 

char my2dArray[5][11]= // [11] required for null character termination of string literals
{
  "123456ABCD",
  "234561BCDA",
  "345612CDAB",
  "456123DABC",
  "561234ABCD"
};

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

  int address;

  Serial.println ("Writing data.....");

  for(int j=0; j<5; j++){

    Serial.println();

    for(int i=0; i<10; i++){

      Serial.print(my2dArray[j][i]);
      EEPROM.write(address= i+(j*10), my2dArray[j][i]);
    }
  }
  Serial.println();
  Serial.println();
  Serial.println ("Reading data.....");

  for(int j=0; j<5; j++){

    Serial.println();

    for(int i=0; i<10; i++){

      char value= EEPROM.read(address= i+(j*10));
      Serial.print(value);

    }
  }
}

void loop(){
}

Hello.

Code from cattledog is not correct.

here is correct code:

#include 

char my2dArray[5][11]= // [11] required for null character termination of string literals
{
 "123456ABCD",
 "234561BCDA",
 "345612CDAB",
 "456123DABC",
 "561234ABCD"
};

void setup(){
 Serial.begin(115200);
EEPROM.begin(512);
 int address;
 Serial.println();
 Serial.println ("Writing data.....");
 Serial.print (F("Free memory = "));
 Serial.println (ESP.getFreeHeap());
 for(int j=0; j<5; j++){

   Serial.println();

   for(int i=0; i<10; i++){

     Serial.print(my2dArray[j][i]);
     EEPROM.write(address= i+(j*10), my2dArray[j][i]);
    
   }
  EEPROM.commit();
 }
 
 delay(100);
 Serial.println();
 Serial.println();
 Serial.println ("Reading data.....");

 for(int j=0; j<5; j++){

   Serial.println();

   for(int i=0; i<10; i++){

     char value= char(EEPROM.read(address= i+(j*10)));
     Serial.print(value);
   }
 }
Serial.println ("");
Serial.println ("Done.");
  Serial.print (F("Free memory = "));
 Serial.println (ESP.getFreeHeap());
}

void loop(){
}