'EEPROM' persistence issue

I’m using a super simple piece of code to persist my target temperature or at least trying to.

writing:

int setTargetTemp(String command) {
 target = command.toFloat();
 double targetWrite = target;
 EEPROM.put(0,target);
 return 1;
}

reading:

double target = 0;

void setup()
{ 
        Spark.variable("target", &target, DOUBLE);
	double targetRead = 0.0;
	EEPROM.get(0,targetRead);
	target = targetRead;
}

However my values don’t appear to be sticking. I used an intermediate variable in these methods as target is exposed via the Spark.variable interface and I wanted to make sure the compiler wasn’t doing something odd to support that.

For what it is worth I see the same behavior if I write a single byte with the target.

My test.

  1. Call setTarget remotely
  2. Confirm the target is set in ram by reading it back via REST API
  3. Power off device by killing it’s power supply
  4. Power back on.
  5. Read target via REST API again. Bad data. In the case of a byte read it was always 255.

Can I read from EEPROM in setup?
Has anyone else had this issue?

Here you're writing a float, but reading back a double. I'm assuming this is a typo and should have been EEPROM.put(0, targetWrite);

1 Like

If that is actually it I’ll laugh at myself. This is why peer programming exists! I think you are probably right. I would have done the byte conversion test in place of that line and probably copied the error. Will update.

It’s definitely not that with these two functions.

int setTargetTemp(String command) {
	target = command.toFloat();
	uint8_t targetWrite = command.toInt();
	EEPROM.update(1, targetWrite);
	return 1;
}

int readEEPROM(String address){
	return EEPROM.read(address.toInt());
}

This is my output on a terminal using the CLI

C:\Users\Alex>particle function call [device_id] setTarget 17
1 (confirmation only see code)

C:\Users\Alex>particle function call [device_id] readEEPROM 1
17

C:\Users\Alex>particle function call [device_id] readEEPROM 0
255

C:\Users\Alex>particle function call [device_id] readEEPROM 2
255

C:\Users\Alex>particle function call [device_id] readEEPROM 1
17

Power off the device here and then power it back on

C:\Users\Alex>particle function call [device_id] readEEPROM 1
255

C:\Users\Alex>particle function call [device_id] readEEPROM 1
255

C:\Users\Alex>particle function call [device_id] setTarget 1
1 (confirmation only see code)

C:\Users\Alex>particle function call [device_id] readEEPROM 1
1

I’m stumped

you are still mixing data types.

the function EEPROM.write will save a byte data type only.

you want to use EEPROM.get() and EEPROM.put() for datatypes other than byte.

example:

double targetTemp;
double lastTemp;

void setup() 
{
  Serial.begin(9600);
  Particle.function("setTemp", setTargetTemp);
  Particle.variable("targetTemp", &targetTemp, DOUBLE);
  EEPROM.get(0, targetTemp);
  Serial.print("At Startup EEPROM contains: ");
  Serial.println(targetTemp);
  lastTemp = targetTemp;
}

void loop() 
{
  if(lastTemp != targetTemp)
  {
    Serial.print("new target setpoint: ");
    Serial.println(targetTemp, 2);
    Serial.print("EEPROM now contains: ");
    float value;
    EEPROM.get(0, value);
    Serial.println(value);
    lastTemp = targetTemp;
  }
}

int setTargetTemp(String command)
{
  targetTemp = command.toFloat();
  EEPROM.put(0, targetTemp);
  return 1;
}

You should be able to see how this should work…

Your code executed verbatim exhibits the same behavior the data is lost upon power cycling.

Additionally I’m not mixing types in that second example. I’m doing an assignment of an int into a uint8_t but that is acceptable.

I tested the code and it works, meaning values sent using the function() are persistent and survive a reset, and power cycle.

can you post your entire test sketch?

2 Likes

For the implementation of your code I copy pasted it exactly into build.particle.io. I hosted the code for my actual application as a gist for you. https://gist.github.com/Bostwickenator/3aa173292c1e6c999ea4

Additionally I’m building in build.particle.io and compiling with the target set to 0.4.5 which was flashed to my device using the CLI method described here https://github.com/spark/firmware/releases/tag/v0.4.5

I’m not too sure about the actual reason of your problem so far

This very simple sketch works on my Photons (0.4.5 and 0.4.6)

void setup() 
{
    Serial.begin(115200);
    Particle.function("eeprom", updateEEPROM);
}

void loop() 
{
    Serial.println(EEPROM.read(0));
    delay(1000);
}

int updateEEPROM(String val)
{
    int i = val.toInt() % 256;
    uint8_t b = i;
    
    EEPROM.update(0, b);

    return i;
}

And now I’m giving @BulldogLowell’s code a go and see if I can get your results too.


Nope, all fine there too!
After power-cycling I get the correct value back (despite a wrong first feedback from EEPROM.get(0, value); due to double (targetTemp) / float (value) mixture), so I guess it’s something with your test environment.


Now I’ve even tested your own code (but removed all the Dallas and OneWire references) and it works just the same - you see me puzzled where your problem lies?

Maybe add this as your final line in your setTargetTemp(String command)

int setTargetTemp(String command)
{
  ...
  return targetWrite;  // to see what you wrote
}
2 Likes

Firstly thanks to everyone for spending time on this!

I’ll try returning the value that is written for a sanity check but as I’ve tested reading it back from the EEPROM without removing power first and found the values correctly stored I’m not expecting to see any difference there.

I’m powering the board with a Sony USB charger it can thump out 1.5 amps pretty happily. I watched the board while turning off the power to the charger (as I have been doing thus far) and the board continues to run for approximately 500ms and then loses power (LEDs go off) for maybe 100ms then appears to get power again for about 100ms before settling to off. I wonder if this is causing my issue. I previously discounted this expecting if this were the case it would cause a loss of the application code as well (Application and ‘EEPROM’ are both stored in the same Flash right?). Maybe not?

My next test will be dismantling the housing and trying the previous test but remove the power from the board on the USB side not the AC side.

OK! It’s a hardware issue! The power supply is doing something during power off that is killing my EEPROM values. If I pull the power directly from the photon the values do persist

This is a video of the power off https://goo.gl/photos/KNEc3SXkteBtwA4F7

Any ideas particle team?

Could you try dumping the EEPROM memory after it is inaccessible?

Put the device in DFU mode then run

dfu-util -d 2b04:d006 -a 0 -s 0x800C000:0x18000 -U eeprom.bin

Please send the file to me and I’ll investigate.

Thanks,
mat.

Here you go: https://drive.google.com/file/d/0B71SvCyGrFO6c0lhM2FoVnpzMlU/view?usp=sharing

Just for support I’m jumping in to say that I have seen similar behavior but only intermittently so I have been blaming myself as i work on more important issues in my development. I am saving a few temperature reading <91 degrees so I have been just saving the integer byte. Most of the time it survives a reset /flash etc, but sometimes it comes back as 255. enough so that I wrote code to fail safe if the number is too large. I’m pretty sure I haven’t seen it lose the value through a reset or flash but sometimes a power removal will come back with a 255. i never had consistent data to follow the problem so i didn’t pursue it.

1 Like

Hi,

yes this seems to be when my Photon loses its EEPROM value. My colleague did tell me that he always just unplugs the USB, not turning OFF the power source (either laptop or USB power supply). So it seems in our case that its when its unplugged. Ours has been plugged in on a clients site now for some time and so far (fingers crossed :wink: its still OK. Then again it probably hasn’t lost power yet.

Hope this feedback is helpful. I have ONLY seen it on the one device (out of 5 units available).

BR
Graham

I’ve seen a similar issue.
I have some settings stored here, and when a bad read is detected the settings restore to a default. I’ve had some units that reverted back to default settings which must have been after a bad read.

On a side note. I took a look at memory dumps from this region and the individual bytes are stored on 4 byte boundaries?!
Is this some premium feature that particle plans to charge users for in the future? Quadruple your NVM for a small fee :stuck_out_tongue_winking_eye:

If anyone sees their data revert of 0xFF then please perform a memory dump and get that to me!

dfu-util -d 2b04:d006 -a 0 -s 0x800C000:0x18000 -U eeprom.bin

Heh! :smile:

The EEPROM memory on the Core/Photon isn't true eeprom - it's flash memory. This means that bytes can only be changed from 0 to 1 by erasing the entire 16Kbyte sector. That's why the data is encoded so that we can make incremental changes without having to erase the sector.

1 Like

Did you have any luck figuring out what is going on? I’m swapping power supply in the mean time :smile:

Same here, this issue is new to me, it didn’t seem to happen under 0.4.5, but since updating to 0.4.6, it has happened a few times. Haven’t been able to make a dump as my program overwrites eeprom with 0x00’s on an unexpected read.
I’m running mostly on batteries, and it happens on low power. I think it has also happens on bad wifi connection, but not 100% sure.

I’m also getting SOS#5 errors now, which did not happen before.

I have tried fw 0.4.7, 0.4.6 and 0.4.5, but it doesn’t seem to change anything. @mdma, is it even possible to roll back firmware, or does .6 or .7 trigger updates of the bootloader or other parts that don’t roll back properly?