2

I am building a circuit that has a button, which when pressed, should increment a counter. I want to store this counter so that when I power off my circuit, it can be read when I power it back on. However, I am worried about the lifetime of the EEPROM - apparently it is only rated to handle 100k writes.

I am using an Adafruit Trinket Pro. Should I cycle my writes through different addresses so as not to write to a single cell over and over? What other strategies are there? I don't expect to be pressing the button many times in a short period of time - maybe at most one press per minute.

Is there some other external storage option I should look at? I really don't want my little project to die randomly one day because I've exceeded ~100k button presses!

  • Welcome to Arduino Stack Exchange. Please take the tour at arduino.stackexchange.com/Tour to get the most out of this site. – SDsolar Aug 24 '17 at 2:32
  • There is an excellent application note on this subject. Please see AVR101 atmel.com/images/doc2526.pdf – Mikael Patel Aug 24 '17 at 3:22
  • Why not have a second button you push before powering off and have that trigger the write to EEPROM? I have a sketch that modifies data once a second and need to be able to switch off without losing data, and this is how I am handling it. – KC Tucker Aug 24 '17 at 5:12
  • 2
    Or have a storage cap and a circuit to trigger storing the counter into the eeprom on power loss suing the cap as a temp powersource. – ratchet freak Aug 24 '17 at 10:17
2

If possible use a combination of wear-leveling like algorithm (as pointed out by Mikael Patel) and an power-down driven interrupt, to save onto EEPROM only when needed. At reset, load the last keypress count into a variable in RAM. Increment that variable in RAM on keypress, and save it to EEPROM only when a power down occurs (i.e. the interrupt is triggered). Optionally, when power down occurs, make sure to save the variable only if the new counter actually differs from the old value (i.e. if there actually were keypresses).

To implement the power-down driven interrupt use the built-in comparator to monitor a Vin (use a resistor divider!) against the internal Vref, and use the analog comparator interrupt to save the value. Remember to put enough capacitance between +5V and gnd, to make sure your arduino has enough time to save the state.

Alternatively, if you can afford errors (which might accumulate over time, and lead to a huge underestimation), save the value to EEPROM only every n keypresses.

1

maybe at most one press per minute.

That's great! You can just make some sort of timer to save every 2 or 3 minutes automatically. You said at most, so that should work. Here is example of code that can allow you to do so!

int cycleCnt = 0;    //Counter to count cycles
int cnt = EEPROM.read(0);         //Your press counter
bool currentlyCounting = false;   //Boolean to store if we are counting now or not
bool pressedBefore = false;

void loop() {
  if (digitalRead(button_pin) == HIGH) {    //You are holding the button
    if (!pressedBefore) {                   //And you didn't press it before
      //Here you do something you need with button
      currentlyCounting = true;       //After you pressed the button, we are starting to count time
      cycleCnt = 0;                        //and reset current counter (which would save us EEPROM writes!)
      cnt++;

      pressedBefore = true;                 //Mark button to be pressed so you don't do same code more then one time
    }
  }
  else pressedBefore = false;               //Mark, that you've unpressed the button

  delay(50);      //Delay in 50 mil won't affect speed of your button press, but it will allow us to count time
  if (currentlyCounting) cycleCnt++;          //Count cycles (every 50 mil)

  if (cycleCnt == 20 * 120) { //20 - amount of loop cycles to wait for one second. 120 - seconds in 2 minutes
    cycleCnt = 0;
    EEPROM.write(0, cnt);
    currentlyCounting = false;
  }
}

This might help you as well!

In case I misunderstood you and you meant "1 minute is the highest delay time beetween presses" then you should save automatically every half of minute or so

0

Cycling through the EEPROM is possible.

Is that button capable to last more than 100k presses ?

A button press every minute ? Really ? Is that during working hours ? That would take about year to get near the 100k writes (5 days per week, 8 hours per day, every minute).

If you want to count more than 100k key presses, then you probably store it in a 32-bit integer. That is 4 bytes. That means that when the Arduino is turned off while in the middle of writing that number to the EEPROM, that number is corrupted and lost forever.

With 1k EEPROM, you have 256 positions for the 32-bit integer. That means you can handle 25 million key presses.

My suggestion would be to store each new value of the 32-bit integer to the next location (circular). At startup you need code that interprets the numbers to find the last one and ignores a bad one and can handle a new Arduino with cleared EEPROM and even an Arduino that was used by you to develop the code. That means you need a command to clear the EEPROM.

0

Use brown out detection. Keep the count in ram until the mcu is losing power - only then save it to eeprom. Read the datasheet on bor.

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.