7

Is there any way to store the values of necessary variables somewhere (may be in a file that gets updated by the program at various events), which can be read back when program starts after rebooting the Arduino board?

I am trying to control my AC appliances using IR remote control. Where I want Arduino to remember what was on and what was off in my room after a power failure.

Using EEPROM looks like a fairly good solution, though it has a limitation of 100,000 writes which is making me try to find another way out.

Using an external EEPROM which doesn't have that limitation or its fairly big, is a really good idea I got from fuenfundachtzig, thanks for this great idea. But I don't know how to implement this in my project. Any resource to gather knowledge on using external EEPROM, will be much appreciated.

Thank you all...

  • If you are only concerned about reboot, and not power cycling, then you can use RAM - you just have to keep any init code from wiping it. Of course if you need to survive power cycling too, then you need the EEPROM. – Chris Stratton May 17 '15 at 22:43
  • Actually I am really concerned about the power cycling. I am trying to control my AC appliances using IR remote control. Where I want Arduino to remember what was on and what was off in my room after a power failure. – Samik Chattopadhyay May 19 '15 at 16:36
6

The internal RAM of the Arduino will be reset when you repower the chip, so if you want to keep your data, you need to store it in EEPROM.

If you are worried about the limited write/erase cycles, you should estimate how often the data would be updated (i.e. written to EEPROM) and how long you plan the lifetime of the device you build. If 100,000 cycles then still is an issue, you have several options:

  • Keep the variables in RAM and only write them to EEPROM say every 5 minutes (100,000 cycles then makes about one year of continuous usage until the EEPROM might fail).
  • Use an external EEPROM (in a socket) that could be easily replaced if needed.
  • If replacing it is not an option, consider using an FRAM instead (advantage vs EEPROM: much more erase/write cycles but also very expensive, so not an option for large amounts of data but certainly for a few variables).

Note, however, that your description sounds like a typical use-case for user settings that you don't want to get lost on reboot. For those the internal EEPROM is the right place: only store them when they're changed and you're golden -- the user won't change them a 100,000 times easily...

  • I usually use for this type of things an external EEPROM; something like an AT24C02 works fine for most projects (it's 256 bytes). I just prefer external memory as it lasts more R/W cycles and because you can change it if it doesn't work anymore. – Stefa168 May 17 '15 at 21:00
  • The ram is not cleared. The global variables are set to zero according to the 'c' standard. The unused ram keeps its value during a reset. – Jot May 1 '17 at 18:25
  • Yes, you are right. I was thinking of a power failure which leads to a loss of the data in RAM (and which makes a reinitialization necessary). – fuenfundachtzig May 1 '17 at 20:04
  • what about to use sdcard reader. is not so much expensive and sdcard will live lot of time. – erm3nda Jun 3 '18 at 14:49
2

Store them in the on-chip EEPROM.

  • The EEPROM memory has a specified life of 100,000 write/erase cycles, so using EEPROM can be a limitation where program automatically writes values in it frequently, though, it reads them quite rare. – Samik Chattopadhyay May 17 '15 at 20:10
2

EEPROM space, as already mentioned, will work if non-volatile is required. However, you have not qualified if it needs to be non-volatile or not. If not then you can use an __attribute__ to define the variable space not to be initialized. As the SRAM on the ATmega's are not cleared by reset or power cycle. The Compiler defaults to initializing them. Where this can be turned off per variable as in the below example:

//non-initialized value
union configUnion{
  uint8_t    byte[6]; // match the below struct...
  struct {
    uint16_t value1;
    uint16_t value2;
    uint16_t chksum;
  } val ;
} config  __attribute__ ((section (".noinit")));

void setup() {
  uint16_t sum; 
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // prints title with ending line break
  Serial.print("Out of Reset -");
  sum = getchksum();
  printValues();

  if (sum != config.val.chksum) {
    config.val.chksum = sum;
    Serial.print("chksum is incorrect setting config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
  }

  config.val.value1++;
  config.val.value2++;
  Serial.print("setup new values - ");
  printValues();
  config.val.chksum = getchksum();
  Serial.print("updating chksum config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

int counter = 0;

void loop() {
  if (counter < 200) {
    Serial.print("after a while - ");
    printValues();
    Serial.println();
    while (true) {
      continue;
    }
  }
  counter++;
}

void printValues() {
  Serial.print(" value1 = 0x"); Serial.print(config.val.value1, HEX);
  Serial.print(", value2 = 0x"); Serial.print(config.val.value2, HEX);
  Serial.print(", sum = 0x"); Serial.print(getchksum(), HEX);
  Serial.print(", chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

uint16_t getchksum() {
  int sum = 0;
  for (int position = 0; position < (sizeof(config) - sizeof(config.val.chksum)); position++) {
    sum = sum + config.byte[position];
  }
  return sum;
}

Output of above code is below. Note that the first output was the result of powering the UNO up with the Reset button depressed and then released after the Monitor window was started. Otherwise the "incorrect setting" print would have been missed, before the monitor window can be started.

Out of Reset - value1 = 0xBFED, value2 = 0xD2F9, sum = 0x377, chksum = 0xF457
chksum is incorrect setting config.val.chksum = 0x377
setup new values -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x377
updating chksum config.val.chksum = 0x379
after a while -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379

Out of Reset - value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379
setup new values -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x379
updating chksum config.val.chksum = 0x37B
after a while -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B

Out of Reset - value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B
setup new values -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37B
updating chksum config.val.chksum = 0x37D
after a while -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37D

With this your variables will persist resets. As long as the power is not lost. Noting the above where you will get random data, to start.

Using either EEPROM or .noinit I would recommend that you checksum your persistent variable space during setup and if incorrect you can initialize or issue a warning.

1

If you really need to update your NVRAM frequently, look into FRAM (Ferroelectric Random Access Memory) which claims a write life of 10^13 cycles (that's ~ 318,000 years if you write once/sec!). They're 8KB, and faster than Flash or EEPROM at 20MHz (SPI).

Adafruit (in the US) sells them on a breakout board for about US$6 in onesies. Or you can buy the bare chips from the usual suppliers for around US$1.30, but not DIP, only SOP8 packages.

0

If you're open to a off-chip solution, it isn't too difficult to buy/build an SD card reader.

  • 1
    Please try to provide a more thorough answer: provide links to such SD card readers, post some sample code on how to read/write variables from it, and mention how it is better than EEPROM. – jfpoilpret May 22 '15 at 4:27
  • Good suggestion. SD is using a regular SPI interface. So all you need is some logic-level-conversion. Beside that you wire them directly to an Arduino. Just solder some wires to a micro-SD to SD adapter. – Gerben May 27 '15 at 15:12
  • +jfpoilpret IMHO SD Card Readers are ubiquitous and shouldn't need examples or citation. The code is dependent on the brand of reader so no point in providing arbitrary code. I did mention how it is better than EEPROM, it isn't too difficult to buy or build. – linhartr22 May 28 '15 at 22:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.