Saving parameters to flash

Hi all. I am working on a project in which I would like to able to remember a certain mode and brightness (LED controller) when the arduino power is cycled.

The mode will be changed frequently, I guess I will have to write the current mode and brightness to flash each time it gets changed - just in case of a power down. is this OK to do?

I guess I will have to write the current mode and brightness to flash each time it gets changed

I guess you won't. Flash memory is read-only. EEPROM might be usable, but not EVERY time mode and brightness change. Why not just start a given cycle over?

Because of the limited wear cycles of EEPROM its best to only remember settings at explicit user
request, or to institute a quite large delay before updating EEPROM (no more than once an hour?)
so as to prevent premature EEPROM failure.

If you want to extend the life of EEPROM you could assign a buffer in EEPROM, each entry
being updated round-robin style (with a sequence number), sharing the wear over many
entries. At reset you read all the entries to determine the one with the highest/latest sequence
number.

Sorry I meant the eeprom :slight_smile:

PaulS:

I guess I will have to write the current mode and brightness to flash each time it gets changed

I guess you won't. Flash memory is read-only. EEPROM might be usable, but not EVERY time mode and brightness change. Why not just start a given cycle over?

Not sure I follow you Paul - somehow I would like to work out where the code was when it was powered off?

MarkT:
Because of the limited wear cycles of EEPROM its best to only remember settings at explicit user
request, or to institute a quite large delay before updating EEPROM (no more than once an hour?)
so as to prevent premature EEPROM failure.

If you want to extend the life of EEPROM you could assign a buffer in EEPROM, each entry
being updated round-robin style (with a sequence number), sharing the wear over many
entries. At reset you read all the entries to determine the one with the highest/latest sequence
number.

Thanks for the info, that sounds mighty complicated for me though :~ is there somewhere I could read up on it or a tutorial that you are aware of?

How many writes on average are we talking before the eeprom becomes damaged?

Thanks all

somehow I would like to work out where the code was when it was powered off?

Why? Were it my device, I might expect the same fading/blinking/whatever mode to be restarted after a power cycle. I would not expect that the fading/blinking/whatever cycle would resume where it left off.

PaulS:

somehow I would like to work out where the code was when it was powered off?

Why? Were it my device, I might expect the same fading/blinking/whatever mode to be restarted after a power cycle. I would not expect that the fading/blinking/whatever cycle would resume where it left off.

That is true and exactly what I would like to achieve but I'm not sure how I could record when the mode has been changed without wearing out the internal eeprom. I think on a average day it would get written to around 20-40 times at a rough guess?

Thanks

I think on a average day it would get written to around 20-40 times at a rough guess?

So, divide the number of times that you can write to EEPROM (100,000 minimum) to determine how many days it will last (2,500+).

Thanks, I don't think that sounds too bad. Would that be improved by using the technique that MarkT explained?
I am just looking at some stuff in the arduino reference, I think I can understand the writing method but not sure about the reading - does the following code display the data from every byte in turn? How could you pull the data from unspecified bytes - if you write to a different one each time?

Hope that makes some sense!

does the following code display the data from every byte in turn?

No. Of course, the fact that there is no code would explain that...

How could you pull the data from unspecified bytes - if you write to a different one each time?

You can't. The technique described means that you need to keep track of where to read from, too.

Here's an example of using two EEPROM memory rings to store two variables called Mode and AHr. Bytes 0 and 1 are used to store the current address of the two rings, so the MCU remembers where you are between re-starts. Those two bytes are written with a new address once every time the Arduino is started, but in my application that's no more than a few times (e.g. 10 times) a day. Mode and Ahr get stored in their current addresses every time they change, and that's many times a day (e.g. 220 times a day), but in each new session a different address around the ring is used for this. With a 20 byte ring, this works out to about 25 years of reliable EEPROM storage.

... defined constants
// modes as cycled by ModeSwitch
#define Drive1 1
#define Drive2 2
#define Drive3 3
#define Seat 4
#define Lights 5

... globals:
byte Mode = Drive1;
byte ModeAddress; // address in EEPROM where last Mode stored
byte AHr = 0; // half AmpHours
byte AHrAddress; // address in EEPROM where AHr is stored

... in Setup ()
  EEPROM_RING (); // set up, maintain and read ring memory to store Mode and AmpHrs

... the EEPROM_RING function that's called:
// set up ring memory for Mode
  ModeAddress = EEPROM.read (0); // address where Mode value was last stored
//  Mode EEPROM memory ring runs from address 20 through 39
  if ((ModeAddress < 20) || (ModeAddress > 39)){
    Serial.println (F("A Mode value has not yet been stored"));
    ModeAddress = 20;
  }
  else {
    Mode = EEPROM.read (ModeAddress);
    Serial.print (F("Stored Mode = "));
    Serial.print (Mode);
    Serial.print (F(" in byte "));
    Serial.print (ModeAddress);
    ModeAddress = ModeAddress + 1;
//  Mode EEPROM memory ring runs from address 20 through 39
    if (ModeAddress > 39){
      ModeAddress = 20;
    }
  }
  EEPROM.write (0, ModeAddress); // address where Mode will be stored
  EEPROM.write (ModeAddress, Mode); // re-stored in new address
  Serial.print (F("   Mode will now be stored in byte "));
  Serial.println (ModeAddress);
// set up ring memory for AmpHours
  AHrAddress = EEPROM.read (1); // address where AHr value was last stored
//  AHr EEPROM memory ring runs from address 40 through 59
  if ((AHrAddress < 40) || (AHrAddress > 59)){
    Serial.println (F("An AHr value has not yet been stored"));
    AHrAddress = 40;
  }
  else {
    AHr = EEPROM.read (AHrAddress);
    Serial.print (F("Stored AHr = "));
    Serial.print (AHr);
    Serial.print (F(" in byte "));
    Serial.print (AHrAddress);
    AHrAddress = AHrAddress + 1;
//  AHr EEPROM memory ring runs from address 40 through 59
    if (AHrAddress > 59){
      AHrAddress = 40;
    }
  }
  EEPROM.write (1, AHrAddress); // address where AHr will be stored
  EEPROM.write (AHrAddress, AHr); // re-stored in new address
  Serial.print (F("   AHr will now be stored in byte "));
  Serial.println (AHrAddress);
  int StartingVolts = READ_VOLTS ();
  if (StartingVolts > RechargeVolts){
    AHr = 0;
    EEPROM.write (AHrAddress, AHr);
    Serial.println (F("Battery has been recharged; AHr reset to 0"));
  }
} // end of EEPROM_RING

Ciao,
Lenny