t r o n i x s t u f f

fun and learning with electronics

Discovering Arduino’s internal EEPROM lifespan

Hello readers

Some time ago I published a short tutorial concerning the use of the internal EEPROM  belonging to the Atmel ATmega328 (etc.) microcontroller in our various Arduino boards. Although making use of the EEPROM is certainly useful, it has a theoretical finite lifespan – according to the Atmel data sheet (download .pdf) it is 100,000 write/erase cycles.

One of my twitter followers asked me “is that 100,000 uses per address, or the entire EEPROM?” – a very good question. So in the name of wanton destruction I have devised a simple way to answer the question of EEPROM lifespan. Inspired by the Dangerous Prototypes’ Flash Destroyer, we will write the number 170 (10101010 in binary) to each EEPROM address, then read each EEPROM address to check the stored number. The process is then repeated by writing the number 85 (01010101 in binary) to each address and then checking it again. The two binary numbers were chosen to ensure each bit in an address has an equal number of state changes.

After both of the processes listed above has completed, then the whole lot repeats. The process is halted when an incorrectly stored number is read from the EEPROM – the first failure. At this point the number of cycles, start and end time data are shown on the LCD.

In this example one cycle is 1024 sequential writes then reads. One would consider the entire EEPROM to be unusable after one false read, as it would be almost impossible to keep track of  individual damaged EEPROM addresses. (Then again, a sketch could run a write/read check before attempting to allocate data to the EEPROM…)

If for some reason you would like to run this process yourself, please do not do so using an Arduino Mega, or another board that has a fixed microcontroller. (Unless for some reason you are the paranoid type and need to delete some data permanently). Once again, please note that the purpose of this sketch is to basically destroy your Arduino’s EEPROM. Here is the sketch (download):

/*
 Arduino EEPROM killer
 John Boxall - http://tronixstuff.com - March 2011
 CC by-sa
 Note: This sketch will destroy your Arduino's EEPROM
 Do not use with Arduino boards that have fixed microcontrollers
 Sketch assumes DS1307 already contains current date and time
*/
#include "EEPROM.h"
#include "LiquidCrystal.h"
LiquidCrystal lcd(4,5,6,7,8,9);

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// all these bytes necessary for time and date data
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte sday, smonth, ssecond, sminute, shour;
byte fday, fmonth, fsecond, fminute, fhour;

// to store number of cycles. Should be enough
long cycles=0; // maximum size is 2,147,483,647

int zz=0;

void setup()
{
  lcd.begin(16, 2); // fire up the LCD
  Wire.begin(); // and the I2C bus
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void killEEPROM()
{
  boolean dead=false;
  // record start time
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  sday=dayOfMonth;
  smonth=month;
  ssecond=second;
  sminute=minute;
  shour=hour;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Cycles so far...");
  do // write and read EEPROM addresses until the first failure
  {
    for (int a=0; a<1024; a++)
    {
      EEPROM.write(a, 170); // write binary 10101010 to each EEPROM address
    }
    for (int a=0; a<1024; a++) // check each address
    {
      zz = EEPROM.read(a);
      if (zz!=170)
      {
        dead=true; // uh-oh, an address has died
        cycles-=2; // easy way out to calculate cycles once died
      }
    }
    cycles++;
    lcd.setCursor(0,1);
    lcd.print(cycles);
    for (int a=0; a<1024; a++)
    {
      EEPROM.write(a, 85); // write binary 01010101 to each EEPROM address
    }
    for (int a=0; a<1024; a++) // check each address
    {
      zz = EEPROM.read(a);
      if (zz!=85)
      {
        dead=true; // uh-oh, an address has died
        --cycles; // easy way out to calculate cycles once died
      }
    }
    cycles++;
    lcd.setCursor(0,1);
    lcd.print(cycles); // update the LCD
  }
  while (dead!=true);
  // so now one address write/read has failed, the game's up
  // record end time
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  fday=dayOfMonth;
  fmonth=month;
  fsecond=second;
  fminute=minute;
  fhour=hour;
  // display final statistics (endless loop)
  do
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Start date/time: ");
    lcd.setCursor(1,1);
    lcd.print(sday, DEC);
    lcd.print("/");
    lcd.print(smonth, DEC);
    lcd.print(" ");
    lcd.print(shour, DEC);
    lcd.print(":");
    if (sminute<10)
    {
      lcd.print("0");
    }
    lcd.print(sminute, DEC);
    lcd.print(":");
    if (ssecond<10)
    {
      lcd.print("0");
    }
    lcd.print(ssecond, DEC);
    delay(2000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("End date/time: ");
    lcd.setCursor(1,1);
    lcd.print(fday, DEC);
    lcd.print("/");
    lcd.print(fmonth, DEC);
    lcd.print(" ");
    lcd.print(fhour, DEC);
    lcd.print(":");
    if (fminute<10)
    {
      lcd.print("0");
    }
    lcd.print(fminute, DEC);
    lcd.print(":");
    if (fsecond<10)
    {
      lcd.print("0");
    }
    lcd.print(fsecond, DEC);
    delay(2000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  # of cycles:");
    lcd.setCursor(0,1);
    lcd.print(cycles);
    delay(2000);
  }
  while(1>0);
}

void loop()
{ // nice intro display with countdown
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("EEPROM Destroyer");
  lcd.setCursor(0,1);
  for (int a=99; a>0; --a)
  // gives user 99 seconds to change mind before start
  {
    lcd.setCursor(0,1);
    lcd.print("Starting in ");
    lcd.print(a);
    lcd.print("s ");
    delay(995);
  }
  lcd.clear();
  killEEPROM();
}

If you are unfamiliar with the time-keeping section, please see part one of my Arduino+I2C tutorial. The LCD used was my quickie LCD shield – more information about that here. A quicker, painless option would be a Freetronics 16×2 LCD shield as tested here. Or you could always just send the data to the serial monitor box – however you would need to leave the PC on for a loooooong time… So instead the example sat on top of an AC adaptor (wall wart) behind a couch (sofa)  for a couple of months:

The only catch with running it from AC was the risk of possible power outages. We had one planned outage when our house PV system was installed, so I took a count reading before the mains was turned off, and corrected the sketch before starting it up again after the power cut. Nevertheless, here is a short video – showing the start and the final results of the test:


So there we have it, 1230163 cycles with each cycle writing and reading each individual EEPROM address. If repeating this odd experiment, your result will vary.

Well I hope someone out there found this interesting. Please refrain from sending emails or comments criticising the waste of a microcontroller – this was a one off. Otherwise, to keep up with new activities here at tronixtuff please subscribe to the blog, RSS feed (top-right), twitter or joining our Google Group.

If you have any questions about the processes or details in this article, please ask in our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, there is the odd competition or give-away –  and we can all learn something.

Otherwise, have fun, stay safe, be good to each other – and make something!

May 11, 2011 - Posted by | arduino, hardware hacking, microcontrollers, projects | , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

14 Comments »

  1. It would have been interesting to see how many times you could do it to each address and keep going until all of them are dead, just to see how it all holds up.

    Comment by healthyfatboy | May 11, 2011 | Reply

    • Hmm – tempting. Will consider that soon.
      cheers
      John

      Comment by John Boxall | May 11, 2011 | Reply

  2. [...] wanted to know just how long the EEPROM in an ATMega328 would last, so he whipped up this neat test program to stress the memory. He writes: Some time ago I published a short tutorial concerning the use of [...]

    Pingback by EEPROM Destroyer « adafruit industries blog | May 11, 2011 | Reply

  3. Hi John, cool experiment. See also a similar idea here, where they got 11 million cycles. It would be interesting to run the experiment with different chips to see how much variance there is in manufacturing.

    Comment by Rich Decibels | May 11, 2011 | Reply

    • Yes, the flash destroyer kit gave me the idea for this test. I would like to run the project again at various temperatures, however that will be somewhat difficult without a lab. All I have is a cold garage :)
      cheers
      john

      Comment by John Boxall | May 11, 2011 | Reply

  4. GREAT project!!! Well worth the death of a 328! I was wondering on the 100,000 number as I am writing code on a little remote that keeps some user prefs in EEPROM. Question answered. Thanks for the useful information, my question is answered!

    Comment by Jeremy Saglimbeni | May 11, 2011 | Reply

    • Hello Jeremy
      Thanks for your comment. It was definitely a question that needed to be answered!
      cheers
      john

      Comment by John Boxall | May 11, 2011 | Reply

  5. Cool!

    I am really enjoying your site and learning a lot!

    I guess it was a good idea to send all those criminals to Australia after all. I just don’t understand how you do all these projects upside-down.

    Comment by Ed | May 13, 2011 | Reply

    • Glad you’re enjoying the site.
      Convict transportation ended in 1868.
      have fun
      John

      Comment by John Boxall | May 13, 2011 | Reply

  6. [...] before, but these projects have only tested discrete EEPROM chips. [John] at tronixstuff had a different idea and set out to test the internal EEPROM of an [...]

    Pingback by Destroying an Arduino’s EEPROM - Hack a Day | May 16, 2011 | Reply

  7. Dude, I am mentioning your experiment in my master thesis :-) Your board did not go to waste :-D

    Comment by Shahab | August 2, 2011 | Reply

  8. Bro, your experiment just made my project come out 2 months earlier. Thanks a LOT, from a friend in Brazil.

    Comment by Bruno Alves | March 19, 2012 | Reply

    • Awesome – glad to be of help :)

      Comment by John Boxall | March 19, 2012 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,588 other followers