on chip eeprom write cycle limitations

I'm working on my first project with an arduino nano

I need to preserve a small amount of data that can be restored after a re boot.

so I'm writing two bytes to the eeprom once every minute, then at boot up, I can read that data back.

I know the eeprom has a write cycle limit of 100,000 cycles, so it won't take long to reach that as I'm doing it now.

First question: As I am only writing 2 bytes, is that only "wearing out" those two bytes of the eeprom or is it "wearing out" the whole lot?

Second question. The main reason I want to save the data once a minute is so that I don't lose the data when it re boots. Now every time you plug in a USB cable, or even just open the serial monitor, it re boots the arduino.

So is there ANY way to create an interrupt of some sort to store my data to eeporm just before it re boots? if so that could do away with my need to store it periodically just in case it's going to be re booted some time soon.

Does the value actually change every minute?

ProDave: First question: As I am only writing 2 bytes, is that only "wearing out" those two bytes of the eeprom

Yes.

or is it "wearing out" the whole lot?

No.

Now every time you plug in a USB cable,

or even just open the serial monitor, it re boots the arduino.

That can be disabled.

So is there ANY way to create an interrupt of some sort to store my data to eeporm just before it re boots?

No. It is possible to give your program a bit of time when the board loses power so the data can be written. But, there is no way to write the data before a reset.

[quote author=Coding Badly link=topic=103529.msg776690#msg776690 date=1335670833] No. It is possible to give your program a bit of time when the board loses power so the data can be written. But, there is no way to write the data before a reset. [/quote]

eh maybe if you make your own setup or do some hacking on the board, direct reset to a digital input, write crap, then output a low on another pin tied to the reset pin, but out of the box, no

then output a low on another pin tied to the reset pin

That will not reset it correctly because the output pins go tristate before the minimum reset pulse has been achieved. You need at least an R/C on the pin to stretch the pulse, better yet a monostable.

Some clarification to my post...

Detect power loss (I've also seen circuits for low-voltage detection)... http://ruggedcircuits.com/html/circuit__26.html

Provide power long enough to write to EEPROM... http://ruggedcircuits.com/html/circuit__13.html

As for dealing with RESET, the solutions are: 1. Change the fuses so it's disabled (bad idea); 2. Don't do it (cut the trace and don't touch the reset button).

I need to preserve a small amount of data that can be restored after a re boot. so I'm writing two bytes to the eeprom once every minute, then at boot up, I can read that data back.

So why not just restore that data in void setup? At worst, you will be 1 minute off. To save on write cycles, only write the data if if changed. (100,000) / (24 hours/day) / (60 minutes/hour) = 69 days of writes to 1 address to potentially wear it out. If every write is to the next address, that will stretch it out to the # of EEPROM address * 69 days, so 69,000+ days = 189 years. In setup, read all the EEPROM until you hit 255, that will tell you where to get the next address from. Every time you're ready to write, write the new data to (address+1) and reset the current address to 255. Or something like that.

Thanks for the answers.

What I am doing is recording the On time of a particular output. So the value only increments when the load is turned on. The program keeps track of seconds, but I only write full minutes to the eeprom.

So to clarify, I am only writing once a minute and only when the load is turned on, so the on time is actually incrementing.

Now that I have clarification that I'm only "wearing out" the bytes I'm actually using, then I will leave it as it is. If ever I get close to the limit (100,000 minutes of actual on time) then I'll just alter the sketch to write to the next two bytes instead.

The automatic save on re boot idea was only something to look into if it was the whole eeprom getting "used up"

@Crossroads

If every write is to the next address, that will stretch it out

That is a good idea but you need to know which address was the last one used, => that means that except the 2 bytes data you need a unsigned long minute counter to prefix the value, then you can do an EEPROM search for the highest timestamp and the bytes follow that one are the latest config.

The idea to only write when data has changed is a must!

Unfortunately not in the EEPROM lib yet... => should be something like this.

void EEPROMClass::write(int address, uint8_t value)
{
    if (value == eeprom_read_byte((unsigned char *) address)) return;  // this line added
    eeprom_write_byte((unsigned char *) address, value);
}

but you need to know which address was the last one used

Yes

that means that except the 2 bytes data you need a unsigned long minute counter to prefix the value, then you can do an EEPROM search for the highest timestamp and the bytes follow that one are the latest config.

No. All you need to do is to blank out the number with 0xff or 00. You then only need to search through the EEPROM for the first non blank value to know where to write.

All you need to do is to blank out the number with 0xff or 00.

Better solution as it need less writes on average,

there is a chance that the blank out pattern is the same as the actual data, in that case you should use the blank out pattern of course.

If you want to learn about wear leveling have a look at this experiment: http://blog.blinkenlight.net/experiments/counting-resets/wear-leveling/

Grumpy_Mike:

but you need to know which address was the last one used

Yes

that means that except the 2 bytes data you need a unsigned long minute counter to prefix the value, then you can do an EEPROM search for the highest timestamp and the bytes follow that one are the latest config.

No.
All you need to do is to blank out the number with 0xff or 00. You then only need to search through the EEPROM for the first non blank value to know where to write.

Actually it’s simpler than that:

All I am storing is the total time in minutes that a particular load has been on. I store that as two consecutive eeprom bytes (high byte and low byte of the integer I am storing)

So each time I write a value, it will be a higher value than the last one.

So if I write the next value to the next pair of eeprom bytes each time, then ALL I have to do at boot up is read through the eeprom to find the highest pair.

No need for extra writes or keeping an index.

then ALL I have to do at boot up is read through the eeprom to find the highest pair.

Yes but erased EEPROM defaults to 0xff so that will be the highest value, so search for that value and take the previous two bytes. When it comes to writing and there is no more room left start from the beginning again and write 0xff to the rest of the memory.

Do you have 1 extra i/o pin if so have you considered having a push button that you can use as a save button all you need to do is something like this also the arduino has an internal pullup resistor so you do not need an external one (see http://arduino.cc/en/Tutorial/DigitalPins for more information) Here is an idea of what your program could do.

#define save_button (insert i/o pin here)
#define led_pin (insert led i/o pin here)
void setup()
{
pinMode(save_button, INPUT);
pinMode(led_pin, OUTPUT);
digitalWrite(save_button, HIGH);       // turn on the internal pullup resistors
}
void loop()
{
if (digitalRead() == HIGH)
{
   //insert code here for saving
  //after it is done light up led so we know it is safe to turn off
  digitalWrite(led_pin,HIGH)
}
}

Thanks for that.

That's a neat trick, turning the "Input" on with a write, to enable the pull up resistor. I didn't know that.

Anyway, what I have done is to write data no more than once a minute to the eeprom.

I have implemented a software clock as well so I can log data from day to day. I need to store the clock data as well once a minute, so that too will survive a reboot.

So the clock data is written 1440 times per day. Output data less than that, only stored once a minute while the output is actually on.

I write the data as follows:

2 bytes = yesterdays total next 2 bytes = todays total next 2 bytes for writing the software clock data Then two bytes of "FF"

When the day rolls over, I increment the index counter by 2.

So that leaves yesterdays data preserved, now being "the day before yesterday's" data.

Todays data is preserved now as yesterdays data.

And I write todays data on top of what was previously used to store the clock data.

Always write two bytes of FF after that, so on the second time around (in over a year's time) it will still ensure there are two FF's to find at boot up.

At boot up, I search for the first consecutive 2 bytes containing FF and that sets my index counter. It's necessary to look for two FF's, as one can appear on it's own as a valid value, but the range of values I am storing will never equate to FFFF

This neatly spreads the eeprom write cycles over the entire chip, as well as giving me a daily data record should I wish, for no extra effort.

So in this scheme, each pair of bytes will get 3 days of writing to, before being left alone. So an absolute maximum of 4320 writes (more than likely much less than that)

And it will be a little over 500 days before it rolls around to start over writing the same bytes again.

So I reckon that's 11574 days minimum before I get to 100,000 writes, or about 31 years.

I think that will do.

Glad you learned something!