EEPROM Wear-levelling and time stamps

I have an application where I want to log the time stamp of the last occasion on which an event occurred and then recover that in case of reset / power-down / serial terminal opening etc etc.

The application is a clock that has already run for 60 years. That is the sort of time-scale I am trying to plan for.

It has occurred to me that because time-stamp data (from the Time Library) is monotonically increasing it is relatively easy to wear-level.

My initial idea was to store bytes 3, 2, 1 at locations 0, 1, 2 in the eeprom, and then store byte 0 at the location pointed to by byte 1.
When the Arduino boots it can read the 3 MSBs from a set location, and then find the LSB immediately without needing to search.

Assuming a 1Hz sample and exactly 100,000 writes, this increases the lifetime of the EEPROM from 27 hours to 10 months. As my actual update rate is 30 seconds a simple calculation seems to indicate that I should get 24 years life with this simple algorithm.

However, the fact that the data is sampled every 30 seconds changes things in a more comlicated way than it first seems, I think. If were increasing a counter every 30 seconds, it would be that simple. But this is timestamp data…

Byte 0 updates every 30 seconds, but byte 1 still updates (approximately) every 256 seconds. So the actual life (again assuming exactly 100,000 writes) of Byte 1 is unchanged by the reduced sample rate, and is still 10 months. (as an extreme example a 256 second update rate would write byte 1 every 256 seconds, but would never write byte 0)

So, in my specific application I think I can safely leave bytes 3 and 2 in locations 0 and 1. Whatever I do they last 200 years.
Updating byte 1 every 256 seconds gives me an estimated life of 10 months, but if I save it to one of 256 addresses pointed to by byte 3 that stretches to 207 years.
Doing the same to Byte 0 using byte 1 (+ an offset so they don’t collide) gives that byte a life of 24 years. Good, but more would be better. There is room to double this by using a 9 bit address, for a start.

Perhaps it is worth looking at algorithms other than simple bit-addressing. I have 1022 bytes available. The wear-ratio between Byte 0 and Byte 1 is 8.5 to 1, so if I give 108 bytes to Byte 1 and 914 bytes to byte 0 then they both end up with an estimated life of 87 years.

Does anyone see any flaws in this logic? This does all assume byte-level erase, but the Internet said that was what the EEPROM has.

I then started wondering if there were more optimal encoding schemes for eeprom. If it is an erase that costs, and that sets all bits to 1, but clearing a bit to 0 is free, then an encoding like

0 = 11111111
1 = 11111110
2 = 11111100
3 = 11111000

might be optimal for an increment-1 counter. But would have to be tailored specifically for an increment-30 or increment 256mod30 counter. Perhaps I will settle for the 87 year estimate…

Hmmm...

say you have 1024 bytes in EEPROM, and you have to update your timestamp exacty once per second. Let's also say that you manage to do each update with a single EEPROM write, to any of these bytes at random (can't get more level-wear than that). So you have 100,000 guaranteed write cycles * 1024 bytes, which is 102,400,000. That's ~3.25 years, so if I'm not mistaken, that's probably your absolute guaranteed limit.

[Edit: Oh, ok, if you update just every 30 seconds, that's 97.5 years, but I don't think you can actually do with just one write - at least two for each update, probably, so you're down to 48.75 years tops]

For a 60-year solution, I'd look at some chip with FRAM or at least a more reliable EEPROM.

igendel:
[Edit: Oh, ok, if you update just every 30 seconds, that's 97.5 years, but I don't think you can actually do with just one write - at least two for each update, probably, so you're down to 48.75 years tops]

What am I missing? Why does it take two writes to update a timestamp?

Is the eeprom library clever enough to not write again if the value doesn't change? (or does a no-change write not consume life?)

andyough:
What am I missing? Why does it take two writes to update a timestamp?

Is the eeprom library clever enough to not write again if the value doesn't change? (or does a no-change write not consume life?)

I'm assuming the timestamp is some sort of absolute time (i.e. with a fixed reference point), so it's always changing.

You only need one write if you're writing to the exact same place over and over again, but then you cause serious wear on that spot. To be able to both store information on a wider area and know, after a power-down, where the most updated info was stored, you need more than one write. Intuitively I'd say it's two writes (on average?), but I'll be happy to see a smarter solution :slight_smile:

Here's my thoughts. I like the idea of using the data in registers 0 and 1 as pointers to the addresses of the other two bytes. It can keeps things pretty simple and still get the longevity you desire.

Converting a recent unix time stamp (1417807746) to 32 bit binary gives byte 3 (MSB) as 01010100 = 89 and byte 2 as 10000001= 129.

Using byte 3 as a pointer for byte 1 from address 89 to 255 will not give the 207 years you would get if you used all 255 addresses, but it is still over 100 years.

I believe that the pointer for byte 0 can be the two lowest bits of byte 3 and all of byte 2 for a 10 bit number which will cover up to register 1023, so you should have 1023-256 = 767 available address. If I'm calculating correctly, writing every 30 seconds, 100K times, to each of 767 addresses gives about 73 years.

There are two additional factors. The 10 bit pointer from the current time stamp will be starting at address 129, so you will need to add 127 in order to start at address 256. Furthermore, byte 2 updates every 18 hours so there are only 2160 of the 100,000 writes before it indexes, but the 10 bit index will keep looping from 0 to 1023. You will need to test for the rollover and on the second and subsequent loops the correction factor to start at address 256 will not be the 127 of the first loop but 256.

With this scheme, you have some unused address from 2-88, but I'm sure you'll find a way to use them.

That’s a good point that the 2xLSB of byte 3 are currently 00 and won’t “wrap” during the expected lifespan of the system.

I don’t particularly want to have to handle the wrap (especially I don’t want to store the wrap status) so I might compromise and go for a 256 byte block for Byte1 and a 512 byte block for Byte0. That is 48 years.

I can put a spare pre-programmed Nano in the box to finish out the century :slight_smile:

Although thinking some more, perhaps we tend to get too hung-up on bitmasking and binary?
considering bytes 3 and 2 as an int16 called V

V % 108 and V % 914 seem like they ought to work, even though they currently start in the middle of their range?

Maybe I misunderstood the whole idea, but if you use a higher byte as a pointer to a lower byte, you still have to update both each time, so how does that prevent excessive wear of the higher byte?

That is, assuming you are indeed writing a timestamp and not just implementing a counter, how would you know you have to change the location of byte 0 unless you write something to byte 1 each time as well?

EDIT:

Ok, I understand now what you're trying to do - byte 0 does not change location each time but is written to the same spot as long as the higher byte, taken from the clock, doesn't change. Interesting, I need to think about it some more :slight_smile:

Interesting idea about using the 16 bit unsigned integer V in the top two bytes of the time stamp.

The top two bytes of the current time stamp number is 01010100 10000001 or decimal 21633. It will go to 65535 in roughly 44,000 counts. Each increment is appoximately 18 hrs so its good for 90 years. At 120 writes per hour there are 2160 in 18 hrs. Since you want to limit that to 100K writes you get 46x18 (or 833 hrs) at each address.

I think it would work if the address for byte 0 is the integer of V/46 with correction to start at address 256. You'll get 73 years out of the 767 available addresses.

The scheme for byte 1 to be in the address of the value of byte 3 looks good.

Sorry for flooding this... my initial limitation still holds; if you update something once every s seconds, on an n byte address space with 100,000 writes per address, you simply can't do better than sn100,000, which for s = 30 equals 97.5 years. The actual figure will be worse because you can't have a completely uniform write distribution (you need reference points)

Now, that may still be enough for the specific application; my mistake was thinking in terms of writing random numbers, but time is sequential. The only question is whether you consider ~75 years to be on a different scale than the 60 mentioned in the beginning of this thread.

A clock that has already run for 60 years ? What kind of clock is that ? Mechanical ? Electronic ?

The official Arduino boards have good quality components, but I think it will not run for 60 years. The voltage regulator will get warm causing mechanical stress. Capacitors can fail for no reason. There might be solder creap that causes a shortcut. 60 years is a long time. A radio of 1950 might still work after repairing and replacing components, but it won't work turned on from 1950 up to now.

A 1950's radio has tubes, a large mechanical variable capacitor with wires to a knob, no pcb board, very unsafe transformer and so on. That same impression is how an Arduino board will be to us in 60 years.

Just imagine how archaic an Arduino will be in 20 years, never mind 60.