Determine empty location with EEPROM.get() function

During setup I need to check to see if anything is stored at an EEPROM location. I will use put to store a float at a given location in the code. Is there any way to determine if nothing is stored? In this test I get nan in my serial log for the floats:

EEPROM.get(1,storedMin);
EEPROM.get(2,storedMax);
Serial.print("Stored Min Degrees: ");
Serial.println(storedMin);
Serial.print("Stored Max Degrees: ");
Serial.println(storedMax);

I need to check the storedMin and storedMax variables after get to see if there is anything in there. How would I do that?

@IOTrav, where in the code do you put? An invalid float value WILL show as nan (Not-A-Number) so that is a good indication you don’t have values stored (at least for floats)!

Having more of the actual code also allows us to better help you :wink:

Hi @peekay123

I have not stored anything to the memory locations being read with EEPROM.get(). I want to check EEPROM locations at boot up to see if there are any variables stored in given locations. If not then I use my default values. If there are variables stored there then I use them. How can I tell if there is nothing stored at a given EEPROM location?

@IOTrav, one method is to calculate a simple CRC for your stored values. Take a look at this topic for inspiration:

:smiley:

For single values that does not need 255 you can check for 255.
Real EEPROMS contains FF(255) when empty, and the emulated storage in particle seems to copy this behavior.

So for single values

int getEE(int pos, int default)
{
int val = EEPROM.read(pos);
if (val == 255) return default;
return val;
}

For objects and multi-byte variables it becomes a bit harder, but maybe you could check first cell for 255 or use a CRC as @peekay123 suggests.

I am storing and retrieving a float using EEPROM.put() and EEPROM.get(). Do you have a sample for checking if the retrieval address for the float is blank or empty? I am sure that EEPROM.put and .get are using the EEPROM.write and read functions, have not looked into the backend firmware for this. I was hoping there was a simple solution.

@IOTrav, did you look at the link I gave you? As @MORA points out, since your a storing floats, testing for a 255 value does not guarantee the data represents a “cleared” value. Let me think about how to best do this with put and get and get back to you. :grinning:

Thanks @peekay123

Yeah. I looked over the post you shared. I could not find exactly what I’m looking for though. There has to be a way to do this I would think. I like the idea of submitting a default value when calling .get() Not sure why this was not implemented as it is quite common on other platforms I have worked with. If you get your default back then you know the storage location is empty so you can proceed as needed. I saw some talk of CRC but honestly that is a bit over my head I guess :wink:

In terms of EEPROM, any given address can really only store a value between 0 and 255 and since those are valid values to store and read it’s not a great indication of whether it’s “empty”. There are, obviously, certain situations where that is “good enough” (i.e. if your target range is always < 255). That’s obviously that much less useful when your data is wider than one byte, though. That being said, we are talking about “Emulated EEPROM” on the Particle platform, so we’re actually talking about Flash memory. I’m not sure if it has the same issue or if the platform can actually detect “empty” or not based on how EEPROM is emulated. But it’s worth keeping in mind that the hardware may not exactly lend itself to determining that for sure. I’m not sure what “other platforms” you’re referring to, but EEPROM would suffer from that problem on any platform with actual EEPROM.

Memory is never “empty” it always has something in it.

However, with this particular emulation mode, it should be feasible to return a unique indicator that the requested location has never been written to (it might need a new access method beyond the ones that are already implemented.)

In general, if you were dealing with real EEPROM, you would pattern the EEPROM as part of your initial device programming. There’s no great way to do that with the particle emulated EEPROM.

With the current emulated EEPROM (at least on the photon) you get 0xff returned for every byte you read that has never been written, so figure out what that maps onto as a float and with any luck it will either be NaN or at least outside your expected range, and you can handle that situation appropriately.

If all 0xff results in a legal value for you, then we’ll have to revisit this.

1 Like

Just had another thought - since the low-level EEPROM emulation functions are byte-based, it is possible that you might get a partially written float (since a float is a multi-byte value) if you lost power in the middle of the series of byte writes. You may want to use a byte wide sentinel field (which would be atomic) to show that the values are good. It could be a simple flag that you invalidate before writing the floats, then validate after; or you could try something like a CRC over the bytes that comprise the floats. As usual there’s more than one way to do it.

Ok. I’m getting somewhere now. I put together this test script to help better understand how EEPROM.get and EEPROM.put are working.

If you use EEPROM.put and write a float that float will occupy 4 bytes in memory as floats do on a 32 bit architecture. So if I do this:

float testA = 200.50;
EEPROM.put(0, testA);

It will occupy positions 0, 1, 2, and 3 So I must be sure not to try this:

float testB = 500.60;
EEPROM.put(1, testB);

Doing so will overwrite the last 3 bytes of the first stored float at positions 1, 2, and 3. I did not realize that this EEPROM.get and EEPROM.put did not automatically increment to open space in memory.

Knowing this I can proceed easily. Thank you everyone for your support. Also here is the test script that dumps a bunch of prints to the console. This helped me better understand what was going on:

void setup() {

//Clear memory
for(int i = 0; i < 2048; i++){
    EEPROM.write(i,255);
}
Serial.println("Start Empty");
for(int i = 0; i < 2048; i++){
    Serial.print(EEPROM.read(i));
    Serial.print(" ");
    if(i != 0 && i%15 == 0){
        Serial.println();
    }
}

float testA = 200.50;
EEPROM.put(0, testA);
Serial.println();
Serial.println("After Test A");
for(int i = 0; i < 2048; i++){
    Serial.print(EEPROM.read(i));
    Serial.print(" ");
    if(i != 0 && i%15 == 0){
        Serial.println();
    }
}

float testB = 500.60;
EEPROM.put(4, testB);
Serial.println();
Serial.println("After Test B");
for(int i = 0; i < 2048; i++){
    Serial.print(EEPROM.read(i));
    Serial.print(" ");
    if(i != 0 && i%15 == 0){
        Serial.println();
    }
}

float testC = 255.85;
EEPROM.put(8, testC);
Serial.println();
Serial.println("After Test B");
for(int i = 0; i < 2048; i++){
    Serial.print(EEPROM.read(i));
    Serial.print(" ");
    if(i != 0 && i%15 == 0){
        Serial.println();
    }
}
Serial.println();
float a;
float b;
float c;
Serial.println(EEPROM.get(0, a));
Serial.println(EEPROM.get(4, b));
Serial.println(EEPROM.get(8, c));
}

void loop() {
    
}
1 Like