Simple way to increase EEPROM writing cycles

Good evening everyone,
I am continuing my Arduino dishwasher project
I need to save a struct to memory every time the cycle is paused or power is missing. I already know how to handle these states, but I am worried about the EEPROM's limited amount of read/write cycles. Is there a simple way (and no, the libraries I looked are very complex for me to understand) so that I can write this struct in a different position every time I write it to EEPROM? Thanks

Use FRAM external.

Example:
Adafruit I2C Non-Volatile FRAM Breakout - 256Kbit / 32KByte : ID 1895 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits

Each byte can be read/written 10,000,000,000,000 times so you don't have to worry too much about wear leveling.

1 Like

How often is the content written to the EEPROM?

With one write cycle per day, the EEPROM has a life span of approx. 270 years.

@paulpaulson now say how long FRAM would hold up…

a7

Yes.

How big is the struct? How big is the EEPROM? The starting address is completely in your control.

Which ones were those?

Have you done the math to know whether this is really an issue?

I.e. how often you plan to update the EEPROM vs the number of actual write cycles to EEPROM to calculate how long it would be before the part wears out.

Also, If the code uses put() or update() then the wear can be reduced.

The EEPROM library put() method calls update() which checks to see if the value is different from what is already stored in EEPROM before writing.

So if the contents of the data isn't changing very much then the number of actual writes to EEPROM is reduced.

--- bill

You can also help to spread the write activity over more eeprom cells using the following technique.
Logically divide the eeprom up into a number areas, each area will contain a version of the struct that you write to it. The struct also contains a (uint32_t) serial number in addition to the user data.
At system start , the eeprom is scanned for the highest and the lowest serial numbers. The position in the eeprom holding the struct with the lowest serial number is noted because this will be reused during the current session. The struct with the highest serial number is copied into ram and the serial number incremented. This will be written to the eeprom during the current session. The idea is that at each system start a new area in the eeprom is defined for writing to. This rolls over as required.

2 Likes

Okay, however I admit, I am curious to know how you will write to EEPROM when the power is removed.

1 Like

To add to the method that 6v6gt's mentioned, you can also calculate a CRC for the struct before it is written to EEPROM. Then you write the struct to EEPROM and also write the struct's CRC value in the next memory location.

When the power is lost unexpectedly, and you reboot the Arduino, you scan for the latest copy of the struct that was written in EEPROM (using the method that 6v6gt mentioned). You also pick up the CRC value that was attached to this struct.

When you find the latest copy of the struct in EEPROM, you recalculate the CRC value of this struct, and you check if this recalculated CRC value is equal to the CRC value that was attached to the struct in the EEPROM.

If the recalculated CRC value is equal to the CRC written in the EEPROM, then this very likely means that the data has not been corrupted, and you restore program with these value's.

If the 2 CRC values do not match however, then you find the second latest struct that was written to the EEPROM, in the preceding memory location. If this struct passes the CRC check, then you use restore the program with this struct, and so on.

Such a process is commonly used to prevent corrupted EEPROM data from being deemed as valid. This is especially important in your case, as there's a slight chance that one of the write's to EEPROM will get interrupted when the power goes out.

That looks like a good idea. Certainly I would modify my suggestion in the future to make the write operation a two stage action to limit the possibility of getting corrupt data. Stage 1: write everything with a zeroed serial number. Stage 2: write just the serial number. But adding some sort of check digit is an even more robust approach. Especially so in designs which attempt to detect a power failure and then, on any remaining capacitor power, attempt to save the system state to eeprom.

Sorry for not answering before, I was busy with a bunch of stuff
Anyways, I'll try to be as clear as possible
For those wondering how I managed to save data on power failure: I simply used a large capacitor powering the Arduino only (diode and capacitor) from 5.7V (LM7805 + diode to ground) and the Arduino secret voltmeter code. I check the voltage 20 times a second with a timer (MsTimer2), if the voltage goes under 4.25V I assume a power failure and save data to EEPROM. It works very reliably
Anyways, to restore a cycle to the point it was left off after pausing or shutting power down I have created this struct:

struct saveDataStruct {
  bool thereIsDataToRestore;
  byte cycleNumber;
  byte cycleState;
  byte macroState;
  int amountOfWater;
  long elapsedTimeBeforeSaving;
  bool drainPumpState;
  bool fillSolenoidState;
  bool washingPumpState;
  bool detDispenserState;
  bool heaterState;
  bool regenSolenoidState;
};

struct saveDataStruct myStruct;

where the first variable is set to 1 on occurrence of a power failure, pause or power off without canceling the cycle. The reason is that if the machine is powered on but the previous cycle was completed it doesn't need to restore anything

Now I need to understand how to retrieve data from EEPROM and write the struct to it, before being able to implement a safety feature for the EEPROM. Could anyone help me out? Do I need to create a secondary struct and do

EEPROM.get(0,myStruct2);

or can I simply use myStruct?

I can't comment on how effective such a method would be, because I simply don't know. However, you may consider a different approach of using an external open-drain voltage supervisor, like this:

This can also be done using the ATMEGA328P analog input comparator.

I'm going to try @GigaNerdTheReckoning's diode/capacitor technique.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.