5

In my current project I need to store the current elapsed time in hours to retrieve it in case of power loss. Since I am using a Arduino Nano I would ideally like to use the built in EEPROM without additional hardware.

The written values and their order will always be:

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 0 -> ....

If I write that on EEPROM per 0->0 full cycle the last bit will change 7 times and the other bits are pretty much idle. That's why I thought of distributing the changes more evenly by using instead the sequence

0 -> 1 -> 3 -> 7 -> 15 -> 31 -> 63 -> 0 -> ....

This would change every bit only once during a full 0->0 cycle. Does this improve EEPROM life expectancy or is the life expectancy linked to updating full bytes rather than individual bits?

edit: Since the question was closed for being off-topic, I altered the introduction a little bit. I am sorry if some of the comments are no longer fully valid. Since I don't fully understand why the question was closed (especially since there is EEPROM-tag), I would be grateful for a tip where on stackexchange the question would be best suited.

maxmilgram
  • 151
  • 3
  • 4
    Good question! You may consider adding zeros instead of ones (255 → 254 → 252 → 248 → 240 → 224 → 192 → 255), as for an EEPROM, a pure “write” operation only turns ones into zeros. On AVR, you could also try to use the “write only” mode of the EEPROM (see the datasheet) instead of the “Erase and Write in one operation” mode, which is the one used by the Arduino EEPROM library. – Edgar Bonet Mar 25 '22 at 09:27
  • Thank you for your comment. If I understand it correctly if i go from 00000001 to 00000011 what will actually happen is 00000001->11111111->00000011. So in order for my strategy to even have the hope to make sense I need to work with zeros instead of ones? – maxmilgram Mar 25 '22 at 09:40
  • 2
    That's my understanding, but I am far from being an expert in EPPROM. I am eager to see the answers you get. ;-) – Edgar Bonet Mar 25 '22 at 09:49
  • The more [practical solution](https://arduino.stackexchange.com/questions/72365/newbie-using-brown-out-detector-on-arduino-due-for-saving-variables-to-eeprom/72370#72370) is to store data to EEPROM only when you really need it - when power goes out. – gbg Mar 25 '22 at 10:59
  • If this is a contrived question (i.e. home work) then you just have to look for clever answer like you and Edgar have found. BTW a 1MB EEPROM, if you flip 1 bit of 8 every second for every byte, should last you over 90 days. If this is real life don't forget about the bigger (practical) picture. As gbg points out. I had a friend at ---- years ago working on a chip. You write to RAM and before the power completely gave out the chip would dump the RAM into EEPROM. Problem solved (if that chip exists). – st2000 Mar 25 '22 at 12:42
  • Thanks for the additional comments. The question is from a real project so all solutions are on the table. Personally I would prefer a solution without additional hardware. If it is really possible to break down the aging to the flipping of individual bits the chip should last for 50+ years, which is more than sufficient. However to me it is not fully clear as of yet if flipping of individual bits is really a thing altogether and especially with respect to aging. – maxmilgram Mar 25 '22 at 13:07
  • Guessing, it is the number of changes that makes the difference. A real story, we accidentally wrote the time to EEPROM and only discovered it when boards started to fail in the field ... all at nearly the same time. Naturally, we had to recall and repair the boards. So, if you really have a zero tolerance, I would suggest you add a way of checking if the EEPROM continues to work as expected. Perhaps w/something more clever than majority vote where you repeat the above describe approach 3 times over cutting the EEPROM life by 1/3 but gaining a way to verify it is still working. – st2000 Mar 25 '22 at 14:30
  • This is a trick we use for the EEPROM emulation of the chipKIT core for PIC32. However in that situation since it's emulating EEPROM with flash memory you have to manually perform a sector erase, so writing a byte over the top of an existing byte only if the difference between the two bytes is some bits being cleared (erased is 0xFF) work well. – Majenko Mar 25 '22 at 19:18
  • 1
    Because EEPROMS are (always) written byte-wise, I pretty much doubt this will change anything in the life expectancy. – tofro Mar 25 '22 at 22:42

2 Answers2

2

On your next design consider using FRAM, it is non volatile and supports almost unlimited (10 - 14th) read write cycles. The library I use or EEPROM supports the update function where it reads the memory first and does not write to it if it is to remain unchanged.

Gil
  • 1,591
  • 7
  • 16
1

It is possible to write to ATmega EEPROM address without clearing its previous value. The write mode is set with the EEPMx bits in the EECR register.

The avr-libc eeprom.h write functions only use the erase and write mode and the Arduino EEPROM library only uses avr-libc eeprom.h write function.

I modified the EEPROM_write example function from the datasheet to write without erase.

#include <EEPROM.h>

void setup() {

  Serial.begin(115200);

  int address = 0;

  EEPROM.write(address, 0b11111111);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11111110);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11111101);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11101111);
  Serial.println(EEPROM.read(address), BIN);

}

void loop() {

}

void EEPROM_write_no_erase(unsigned int uiAddress, unsigned char ucData) {
  /* Wait for completion of previous write */
  while (EECR & (1 << EEPE))
    ;
  /* Set up address and Data Registers */
  EEAR = uiAddress;
  EEDR = ucData;
  /* Write only */
  EECR |= (1 << EEPM1);
  EECR &= ~(1 << EEPM0);
  /* Write logical one to EEMPE */
  EECR |= (1 << EEMPE);
  /* Start eeprom write by setting EEPE */
  EECR |= (1 << EEPE);
}

the output is as expected:

11111111
11111110
11111100
11101100

I don't know if use of this feature improves the lifetime of the ATmega EEPROM.

Juraj
  • 17,050
  • 4
  • 27
  • 43
  • 1
    It would be safer to set `EEMPE` and `EEPE` with interrupts disabled, as recommended by the datasheet. – Edgar Bonet Mar 27 '22 at 18:43
  • @EdgarBonet this code is from the datasheet. I guess it expects the function to be called with interrupts disabled if a conflict is possible – Juraj Mar 27 '22 at 19:36