Store long integer in Flash memory

I have a program where my Arduino Duemilanove is counting pulse inputs. If the Arduino has to restart for one reason or another, I lose this counter value. I would like to store the counter value into flash memory, then when the Arduino starts up after losing power or something, it will read the counter value from flash memory and start counting from where it left off. I read the documentation on PROGMEM, but I can’t get it to work.

Below is some simple code I tried just to store and read a long integer in flash. But it returns 65535 instead of 80000. I also tried it with integer (not long), but that doesn’t work. What I really want is to read the value in the setup() section, and write the value in the loop() section.

#include <avr/pgmspace.h>

void setup()
{
  Serial.begin(57600); 
}

void loop()
{
 PROGMEM  prog_int32_t charSet  = 80000;
 long PulseCounter;

 PulseCounter = pgm_read_word_near(charSet);
 Serial.println(PulseCounter);
 delay(2000);
}
PulseCounter = pgm_read_word_near(charSet);

Shouldn't there be an '&' operator in there somewhere?

In addition to the hint by AWOL, I see several problems:

1. To read a 32-bit number from program memory, the function to use is pgm_read_dword_near

2. You can not write to program memory from a function, so putting the initialization inside setup() or loop() or any other function won't work. It has to be initialized outside any functions.

3. The reasoning behind item number 2 is: Program memory is read-only memory. Whatever it contains when the device is programmed stays there.

4. The implication of items number 2 and 3: Your whole idea of saving a count value in program memory from a running program is a non-starter. Maybe EEPROM would be a way to go?

Regards,

Dave

I think you want to use EEPROM for this purpose, not FLASH. You can't really write to FLASH while your program is running, and FLASH is programmed in pages (big groups of bytes) rather than 1-2 bytes at a time.

http://www.ruggedcircuits.com

I think you want to use EEPROM for this purpose, not FLASH.

I tried just to store and read a long integer in flash.

Oh Wow! I missed that biggie! Saw "flash", but assumed "EEPROM".

My apologies.

Thanks. I’ll try EEPROM memory. Now I have to figure out how to convert a long integer into 4 bytes and back again. I searched around for some examples and came up with the following. Would this work?

//This function will write a 4 byte long integer to the eeprom at the specified address
void EEPROMWriteLng(int p_address, long p_value)
{
  byte WriteVal[4];
  WriteVal[0] = ((p_value >> 0) & 0xFF);
  WriteVal[1] = ((p_value >> 8) & 0xFF);
  WriteVal[2] = ((p_value >> 16) & 0xFF);
  WriteVal[3] = ((p_value >> 24) & 0xFF);
  
  for(int i=0; i<=3; i++){
    EEPROM.write(p_address + i, WriteVal[i]);
  }
 
}

//This function will read a 4 byte long integer from the eeprom at the specified address
unsigned long EEPROMReadLng(int p_address)
{
  byte ReadVal[4];
  
  for(int i=0; i<=3; i++){
    ReadVal[i] = EEPROM.read(p_address + i);
  }
  
 return (ReadVal[3] << 24) | (ReadVal[2] << 16) | (ReadVal[1] << 8) | (ReadVal[0]));
  
}

It looks like it would work, but it’s a bit unnecessary as the AVR-LIBC library already includes this functionality as the eeprom_write_dword and eeprom_read_dword functions.

See here:
http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

Have a look at: http://www.arduino.cc/playground/Code/EEPROMWriteAnything

It looks like it would work, but it's a bit unnecessary as the AVR-LIBC library already includes this functionality as the eeprom_write_dword and eeprom_read_dword functions.

See here: http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

I looked at the link you provided, but I can't figure out how to use eeprom_read_dword and eeprom_write_dword. I'm confusued about the parameters to pass. Do I need to use references instead of values? If so, how does that work? I'm a beginner with this stuff.

--Scott

You want something like this (warning: not tested):

#include <avr/eeprom.h>

#define EE_SAVED_ADDRESS  0   // Select address in EEPROM memory space

uint32_t saved_variable;

void setup()
{
  saved_variable = eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS);
}

void loop()
{
  if (whatever_reason_to_save) {
    eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS, saved_variable);
  }
}

AWOL’s suggestion will work too.