I'm working on some software using an Uno (ATmega328P). I have a stage byte that can be 1 of 5 values (0-4) in my code and it will increase by 1 every 2.5 hours. If I lose power I need to ensure that on wake up the stage is the same as it was at the time of power loss, so each time the stage is updated I save it to EEPROM.
To ensure the EEPROM lasts as long as possible I want to write some code that uses more than a single byte which I continually erase and write to. I was wondering if there is any library to do this or if my idea below would work?
I currently don't need to use the EEPROM for anything else so to extend the EEPROM life I was going to section of 1 quarter of it (0-255 bytes) for saving this value. Each time I change the stage I will write 3 bytes to EEPROM which will be:
- An index byte (used to shift addresses I write to).
- A stage byte (the stage I need to store).
- A count byte (the amount of times I have wrote the stage at the current index).
To begin with the index will be written to byte 0 in the EEPROM, the stage to byte 1 and the count to byte 2.
My plan is to allow the stage to be written to byte 1 250 times, then clear the count and shift the index to 3. This will in turn move the bytes that the stage and count are being written to to 4 and 5. I will do this until the index reaches the end of the 255 bytes and then return the index to 0. So in total I should be able to shift 85 times.
Each byte has 100,000 erase/write cycles so this means I can pass through bytes 0-255 400 times, writing the stage 250 times each pass. So instead of having 100K writes I would have about 8.5 million writes.
This is my first idea and I realize there is also some waste in the way I do it. I haven't worked with EEPROM much and I was just hoping for some advice as I'm sure I could be going at this completely wrong.
3 Answers 3
You can load spread by saving the current value ORred 0x80 or 0x00.
When writing you write to the next memory location and when it wraps you take the other value to OR with.
The values in the eeprom will be
[{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value},{0x00|value},{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value}]
or
[{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value},{0x80|value},{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value}]
Then you read the first and last byte and if the upper bit is equal you take the last value.
If they are not equal you binary search until to the position changes, the most recent value will be the one right before the change.
There are many ways of achieving what you want. The method I would use would be to use pairs of bytes, but split up differently.
For each 16 bits I would have 13 for a counter, and 3 for a value. The counter, being 13 bits, can count from 0 - 2^13-1, or 0 - 8191. The 3 value bits can store 0 - 2^3-1, or 0 - 7, which is fine for your 0-4 value.
The size of the counter is important, since it is more than double the number of 16-bit pairs in the EEPROM. Assuming a 1kB EEPROM that's 512 16-bit values, so you want more than 1024 values available in your counter (if you wanted to change the split to store a larger number...).
The algorithm is simple:
- Read through the EEPROM looking at the next counter value. If the count increases by more than 1 the last value read is the current one.
- If the count goes from 8191 to 0 then keep going, you have just looped is all.
- Increase the counter by 1 and write to the EEPROM addresses where the count jumped by more than 1.
For example, if you have:
78 1
79 2
80 3
8191 7
8191 7
8191 7
you know that the space after 80 hasn't been used (0xFFFF is split as 0x1FFF and 0x7) so you write "81 4" to it.
Another:
8190 2
8191 3
0 4
1 0
2 1
7283 3
7284 4
7285 0
The jump from 8191 to 0 is just a wrap around and can be considered sequential. However the jump from 2 to 7283 isn't sequential, so you can overwrite entry 7283 with "3 2".
When you write, if you are going past the end of the EEPROM's memory space, you just loop back round to the start again.
This gives you 512 * 100,000 writes, or 51.2m writes.
-
This is excellent and I will 100% use this idea on another project I am working on that uses a larger EEPROM. I will only use 2 bytes as suggested, drop my count sticking with just the stage and index and move the index after every EEPROM write. As I am only planning to use 256 bytes I would not need such a large index to cover them all as 1 byte will do. Again thank you for this it is appreciated and will be used. Using my basic idea I had 28 years, the idea I posted on here would have given me 2425 years and now with using the byte pairs I will get up to 3652 years so I'm well covered.user1649972– user16499722018年01月18日 11:18:56 +00:00Commented Jan 18, 2018 at 11:18
Also, check that the values you want to write are actually changing. No point in erasing and writing a value that is already there. And you save 3.3 ms by not having to do the write.
-
Hi Edgar, thank you for the reply. The value will 100% change each time I try to write, the change in value is what prompts the write to EEPROM. Great advice tho, thanks againuser1649972– user16499722018年02月09日 11:37:26 +00:00Commented Feb 9, 2018 at 11:37
index
byte.