Help with EEPROMWearLevel

Hi,
I’m trying to code for a single byte to be written/read to a Pro Mini using this library, but am having challenges understanding all of the settings.

Here are some goals for this coding:

  1. use all of the 1024 memory
  2. variable is a boolean class to be write/read to eeprom

I’ve read through the README file and searched elsewhere to understand how each of the setting/commands work, but still having trouble.

Thank you to anyone who’s kind enough to explain some of the questions I have!!!

Here’s my first attempt taken from https://github.com/PRosenb/EEPROMWearLevel
PLEASE SEE MY QUESTIONS IN THE REMARKS FOR EACH LINE


#include <EEPROMWearLevel.h>

#define EEPROM_LAYOUT_VERSION 0 //<---- WHICH VERSION IS APPROPRIATE FOR THE PRO MINI?
#define AMOUNT_OF_INDEXES 1 //<---- IS THIS THE ‘OFFSET’ FOR EACH TIME A NEW WRITE OCCURS? …TO MAKE THE SIZE OF THE VARIABLE? I.E. BOOLEAN = 1 ??

#define INDEX_CONFIGURATION_VAR1 0 //<---- WHILE I’M ONLY USING ONE VARIABLE, WHAT DOES THE “0” & “1” MEAN?
#define INDEX_CONFIGURATION_VAR2 1

void setup() {
Serial.begin(9600);
while (!Serial);

EEPROMwl.begin(EEPROM_LAYOUT_VERSION, AMOUNT_OF_INDEXES);

writeConfiguration();
readConfiguration();
}

void loop() {
}

void writeConfiguration() { //v---- EXAMPLE APPEARS TO SHOW TWO DIFFERENT TECHNIQUES TO WRITE “UPDATE” AND “PUT”. iS THIS CORRECT?

// write a byte
EEPROMwl.update(INDEX_CONFIGURATION_VAR1, 12); //<---- WHAT DOES THE “12” MEAN?

long var2 = 33333;
EEPROMwl.put(INDEX_CONFIGURATION_VAR2, var2);
}

void readConfiguration() { //<---- TWO TECHNIQUES AGAIN?
byte var1 = EEPROMwl.read(INDEX_CONFIGURATION_VAR1);
Serial.print(F("var1: "));
Serial.println(var1);

long var2 = -1;
EEPROMwl.get(INDEX_CONFIGURATION_VAR2, var2);
Serial.print(F("var2: "));
Serial.println(var2);
}

The following notes come from the github page for EEPROMWearLevel:

The text for the EEPROMWearLevel library can be seen at this URL:
https://github.com/PRosenb/EEPROMWearLevel/blob/master/EEPROMWearLevel.h

I'm new to Arduino and don't have much experience with the C language. What follows are my thoughts on how EEPROMWearLevel works. (From now on, I will refer to EEPROMWearLevel as: EWL.) I could be incorrect, and would appreciate comments on errors in my thinking. It took me hours to figure out how the library works.

My intention on using EWL is to store a "count" for a stepper motor address. The count keeps track of where the stepper motor is in controlling an antenna. The higher the number, the lower the frequency of the antenna.
My notes and comments are in bold, the italics are the original text:

Implementation Notes
Control Bytes
EEPROMWearLevel uses single bits to store the current index. Single bits of an EEPROM byte can only be programmed from 1 to 0. If a bit needs to change from 0 to 1, the whole byte must be cleared.
EEPROMWearLevel uses control bytes to store the location of the current index of the data. Every bit stands for one byte of data. A bit as 0 stands for data is in use, 1 for not yet used.

In an EEPROM, changing a bit from 1 to 0 does not count against the 100,000 write limit. However, to change a bit from 0 to 1 means a total 8 bit write and does count against the 100,000 limit. In other words, using zeroes as the "true" state is a "freebie," and reduces the wear and tear of writing to the EEPROM.
EWL takes advantage of this by using zeroes to keep track of where to write the data next, creating an "index" to tell EWL about where it can do it's next write of data.
When EWL is executed for the first time, it determines how much EEPROM space is allotted to it. It does this by looking at the size of the byte(s) that will be needed for each "store." It then sets the very first byte in the EEPROM as the "version." (See below) It then dedicates so many bytes to use for the index counter (idx). How many are calculated based on the data byte size. The largest decimal integer I plan on storing is 4000. EWL alloted 170 bytes for the control bytes (8 bits each) and the rest of the UNO EEPROM of 1023 bytes, for data.
As EWL writes data as a Ring Buffer, it writes zeroes into the control bytes to indicate used addresses. By having all zeroes in these addresses, EWL can just scroll through the EEPROM until it finds the first "1" (one), this tells it that is the next index marker.

In the EWL Library there are some beginning definitions that one implements when starting EWL. There are three possible scenarios. The first one defines LayoutVersion and amountOfIndexes. The second scenario adds, eepromLengthToUse. This additional parameter defines how much of the EEPROM is dedicated to EWLl and how much is partitioned out for other uses.
The library call of interest for the Ring Buffer is as follows:
void begin(const byte layoutVersion, const int amountOfIndexes, const int eepromLengthToUse);
layoutVersion: This parameter appears to be nothing more than a toggle instance. As long as it stays the same, EWL will just keep incrementing (indexing) up through the EEPROM and writing new addresses. If layoutVersion is changed, then it essentially resets EWL back to starting over.
I'll post an example at the end of this that shows what happens every time EWL does a write cycle. This should make this section clearer. In the creator's example, EWL is writing data that is a long integer and uses four byte blocks for three sets of digits (111,222, and 333) so it ends up using 12 bytes in total). Notice in the example at the end that "333" doesn't fit in a single byte (larger than 255) so it breaks it into 0000077 and 0000001. The Ring Buffer in the designer's example is only 32 bytes long.
EEPROM layout

Test Example

Using the example sketch supplied by the EWL creator, I ran the sketch for successive times. Before running it, I ran a "clear all addresses" routine to set the entire EEPROM to all zeroes.
The sketch stores three values: 111, 222, and 333. I modifed the program slightly to print out some information at the end of the run. It shows the datalength (in this case, 4 bytes). Next it shows the data that is read back from the chosen addresses, which, of course, should match what was intended to be stored. The print format shows the byte count/binary#/decimal#.
Notice that in the first run, the control bytes are 1:00000000/0 2:00001111/15. What is important to notice here is there are 12 zeroes before the first "1", indicating that the next data will be written at address 13. In the second run, 1:00000000/0 2:00000000/0 3:00000000/0 4:11111111/255 there are 24 zeroes before a one at position 25, and the first data written, the "111" (decimal) is showing up at address 25. Note that there is still a "111, "222" and "333, where the first run wrote them, but they are now stale data and no longer valid data. Eventually, the sketch will start overwriting them with sufficient incremental writing as the buffer comes around.
Setting the serial prints to show just the first 50 addresses data, the four runs show the version byte staying the same, the index bytes traversing the EEPROM and the data results. Here is the first run:[/b]

1st Run:
(Ver) (CTRL byte #1) (CTRL byte #2) (data...)
0:00000100/4 1:00000000/0 2:00001111/15 3:11111111/255 4:11111111/255 5:11111111/255 6:11111111/255 7:11111111/255 8:11111111/255 9:11111111/255
10:11111111/255 11:11111111/255 12:11111111/255 13:01101111/111 14:00000000/0 15:00000000/0 16:00000000/0 17:11011110/222 18:00000000/0 19:00000000/0
20:00000000/0 21:01001101/77 22:00000001/1 23:00000000/0

dataLength: 4

0: 111
1: 222
2: 333
3: 0
4: 0

The first run print clearly shows a few things. First, the Version is stored in the first byte. The next two bytes have the control bits, in this case, all of the zeroes prior to the: 1111. Now for the rest of the runs...

2nd Run
0:00000100/4 1:00000000/0 2:00000000/0 3:00000000/0 4:11111111/255 5:11111111/255 6:11111111/255 7:11111111/255 8:11111111/255 9:11111111/255
10:11111111/255 11:11111111/255 12:11111111/255 13:01101111/111 14:00000000/0 15:00000000/0 16:00000000/0 17:11011110/222 18:00000000/0 19:00000000/0
20:00000000/0 21:01001101/77 22:00000001/1 23:00000000/0 24:00000000/0 25:01101111/111
dataLength: 4

0: 111
1: 222
2: 333
3: 111
4: 222
5: 333
6: 0
7: 0

3rd Run:

0:00000100/4 1:00000000/0 2:00000000/0 3:00000000/0 4:00000000/0 5:00001111/15 6:11111111/255 7:11111111/255 8:11111111/255 9:11111111/255
10:11111111/255 11:11111111/255 12:11111111/255 13:01101111/111 14:00000000/0 15:00000000/0 16:00000000/0 17:11011110/222 18:00000000/0 19:00000000/0
20:00000000/0 21:01001101/77 22:00000001/1 23:00000000/0 24:00000000/0 25:01101111/111
dataLength: 4

0: 111
1: 222
2: 333
3: 111
4: 222
5: 333
6: 111
7: 222
8: 333
9: 0
10: 0

4th Run
0:00000100/4 1:00000000/0 2:00000000/0 3:00000000/0 4:00000000/0 5:00000000/0 6:00000000/0 7:11111111/255 8:11111111/255 9:11111111/255
10:11111111/255 11:11111111/255 12:11111111/255 13:01101111/111 14:00000000/0 15:00000000/0 16:00000000/0 17:11011110/222 18:00000000/0 19:00000000/0
20:00000000/0 21:01001101/77 22:00000001/1 23:00000000/0 24:00000000/0 25:01101111/111
dataLength: 4

0: 111
1: 222
2: 333
3: 111
4: 222
5: 333
6: 111
7: 222
8: 333
9: 111
10: 222
11: 333

Conclusion
The size of the data being written to the EEPROM will determine how many bytes are used for each write. Up to half of the total EEPROM size can be stored at a time, but then that would mean only one data could be stored before it would run out of space. The library has a check for EEPROM size and will adjust accordingly.
For my purposes EEPROMWearLevel will work well. I'm only writing data a few times a day, on average, so I can expect long life on my EEPROM, probably longer than my life!
Comments, ideas and suggestions are welcome.

Dennis, ham radio call letter: K1YPP

Consider using FRAM,

check my lib here - FRAM library published - Libraries - Arduino Forum