EEPROM or PROMEM ?

We have some application where will have to store about 20-30 words , each in the size of 7 chars, in some memory between resets .

If an EEPROM write is per 1 byte, then 210 writes will be made each time we want to save these words.

If a user do that say 3 times a day on average, we have got 600 writes . (right till here ? )

For 100k writes, it wouldn’t take much to burn it out , 2-3 months .

Should we use PROGRAM instead ? whats the major disadvantages ? would it be more appropriate ?

Thank you.

(deleted)

what does it means ? would this one count as 1 write ?

EEPROM.put(headdress,"some 7 chars" );

Also, I don't get this thing. It seems that PROGRAM is better in any aspect ,

  1. much faster
  2. almost unlimited (even 10% of program memory would give you 3.2K . X3 eerpom
  3. 10k writes.

Why in first place Arduino went with EEPROM and not PROGmem ?

Because PROGMEM has even more limited erase/write cycles and can only be written a page at a time by instructions running in the boot section.
Just a thought.

You can write every location in memory 100,000 times.

EEPROM.put(headdress,"some 7 chars" );

So you can do that 100,000 times.

If you're worried, get a FRAM breakout board; e.g. Adafruit I2C Non-Volatile FRAM Breakout - 256Kbit / 32KByte : ID 1895 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits

AWOL:
Because PROGMEM has even more limited erase/write cycles and can only be written a page at a time by instructions running in the boot section.
Just a thought.

This. For all intents and purposes you can't write to progmem from your running application. So that's kind of a non-starter. You're stuck using EEPROM.

ooo I get it, so PROGMEM is anyway at compile time only.

Thank AWOL also .

So 100k is good if its per location and we will use that .

(I could not find anywhere the reading speed from EEPROM but I hope its less the 0.5ms )

gil22:
ooo I get it, so PROGMEM is anyway at compile time only.

Actually, just FYI, there’s a modified Optiboot bootloader that allows you to do it from the application: https://github.com/majekw/optiboot. But EEPROM is probably the best option for this.

gil22:
(I could not find anywhere the reading speed from EEPROM but I hope its less the 0.5ms )

Write a little test sketch that reads e.g. 1000 times 7 bytes and time it using millis().

Regarding words of 7 characters. Is that always exactly 7? If not, does 7 cater for a terminating '\0' or does that make it 8 characters? Just something to be aware of.

@sterretje thanks , we average it for 7 it could even be something else.

So we have to null terminate it, should we use the null terminator to separate between words for example ?

for( index < eeprom length)
save char
if( null terminator)
break

You need a means to differentiate the different words. I you can define a maximum size, life is easy (simply write the full array (regardless if there are 2 or 10 or 50 or ... characters in there)). If not, you run the risk that if a user changes e.g. the first word from e.g. "Hi" to "Hello", you will overwrite the second word partially.

Reading with a fix size will also be easy; just read N bytes (the '\0' somewhere in there after the reading will make it a proper C string). Else it will also be more of a nightmare if you store variable length as you more than likely have to read char-bychar till you get the '\0' (there are other ways, but that implies writing a table of contents into eeprom and some more things that one actually does not want to think about).

Conclusion: use fixed size that can hold the biggest word plus '\0'.

Using this test sketch:

volatile byte c;

const unsigned long ITERATIONS = 10000;

void setup() {
Serial.begin (115200);
Serial.println ("Starting");

unsigned long start, finish, counter;


char * p = (char *) 0x100;

start = micros ();
for (counter = 0; counter < ITERATIONS; counter++)
  c = *p;
finish = micros ();
Serial.print (finish - start);
Serial.println (" us taken to read from RAM");

start = micros ();
for (counter = 0; counter < ITERATIONS; counter++)
  c = eeprom_read_byte (0);
finish = micros ();
Serial.print (finish - start);
Serial.println (" us taken to read from EEPROM");
}

void loop() {}

I get:

Starting
6968 us taken to read from RAM
19708 us taken to read from EEPROM

Dividing by the iterations (10000) I therefore get:

  • 697 ns for RAM
  • 1971 ns for EEPROM

However some of that would be loop overhead, since reading a byte from RAM would take 2 clock cycles, so the rest can be ignored. So the overhead is 697 - 125 = 572 ns. Thus it takes 1399 ns to read from EEPROM (roughly).

Regarding your concern over writing cycles, you aren’t using the full memory space of the EEPROM, so most of that capacity is going to waste. There is a method to extend the life of an EEPROM by rotating the location you write to each time you write.

Electronics manufacturers publish what are called application notes. A lot of times they will be specifically about ways to use their own specific products, but you can also find ones that have broad applicability. I have one from Atmel that I downloaded a long time ago that is useful for this task, AVR101: High Endurance EEPROM Storage.

Introduction
Having a system that regularly writes parameters to the EEPROM can wear out the
EEPROM, since it is only guaranteed to endure 100 k erase/write cycles. Writing the
parameters to a circular buffer in EEPROM where each of the elements in the buffer
can endure 100 k erase/write cycles can circumvent this. However, if the system is
exposed to RESET conditions, such as power failures, the system needs to be able to
identify the correct position in the circular buffer again. This document describes how
to make safe high endurance parameter storage in EEPROM.

With this method, on an UNO, you can easily increase your EEPROM’s lifespan by at least 4x by rotating through the rest of your memory. If that isn’t enough of a life for you, get an external EEPROM that might be built to handle more rewrites and also have larger capacity, giving you more space to rotate around in.

AVR101 - High Endurance EEPROM Storage.pdf (47.3 KB)

... or a small SD card

AWOL:
... or a small SD card

That's probably overkill for 210 bytes, but they do have wear leveling in them already.

Thanks all . @sterretje not a nightmare at all ! :slight_smile:

I ended up ( for anyone who is interested) creating an int array that will holds in each index the total chars up till that word in the EEPROM. (words divided by '$')

so for example:

int sturcutre=[3,7,19];

means the second word starts at 3 and end at 7 , so I can simply get second word by an index:

int start = sturcutre[1];
int end = sturcutre[2];
int len = sturcutre[2]-sturcutre[1];

Then simply readEEProm from address start to address end .

At boot I create once this structure and thats it.

Thanks again.

And now the user needs / wants to store a new word that does not fit in the boundaries 3..7 :smiley: