10
\$\begingroup\$

I am designing a device that automatically adjusts it's physical position as temperature changes. If the device it shut off or power is disconnected the device needs to remember it's last temperature and position. I have the ability to store these values in EEPROM but the problem is the position and temperature could be changing very rapidly. If I were to write the temp and pos to EEPROM after every time they changed that would (1) slow down the firmware a bit, and (2) likely kill the EEPROM after a year or two. So as I see it my options are as follows...

1) use a capacitor/battery to keep the device powered for a short time after power is lost so that I can write the values to EEPROM at that time only. I don't like this because the board is kinda power hungry and this would require a big cap. And I don't have a ton of free space. And I don't want the added cost of a battery and battery holder / or a big cap.

2) use F-RAM instead of EEPROM so that I can write to it trillions of times without wearing it out. I don't like this option because FRAM is quite a bit more expensive than EEPROM and this is for a production product (not just one).

3) Only write the position and temperature every 5 minutes or so. That way I always have a fairly recent position/temp recorded but I am not writing every second so my program is not slowed down and the EEPROM won't die as fast. This seems like my best option.

Does anyone else have any suggestions that I'm not thinking of?

\$\endgroup\$
3
  • 5
    \$\begingroup\$ Just a question. If the device automatically adjusts it's physical position, why do you need to remember the last temperature? When you power on the device again, it will not update the temperature and adjust its position? \$\endgroup\$ Commented Feb 28, 2011 at 14:24
  • 1
    \$\begingroup\$ I agree with Daniel. What if you power down and the ambient temperature changes drastically? Upon powerup, if you used the last saved temp/position, you'd be in the wrong spot anyway, and the device would end up moving regardless. Is there another requirement that isn't listed in your question? \$\endgroup\$
    – Dave
    Commented Feb 28, 2011 at 15:18
  • \$\begingroup\$ What's the EEPROM spec -- how many write cycles? \$\endgroup\$
    – Jason S
    Commented May 6, 2012 at 13:32

5 Answers 5

10
\$\begingroup\$

What you need is a technique called wear leveling. It doesn't write your data every time at the same location in the EEPROM, but uses some algorithm to use different locations. I've read about complex wear leveling algorithms, but I wouldn't know why the following simple method wouldn't work.

Add to your data a 24-bit counter, so that your data block is for instance 8 bytes long. Pages on a 24AA64 are 32 bytes long, so a 64kb EEPROM holds 256 pages. From the datasheet:

"When doing a write of less than 32 bytes the data in the rest of the page is refreshed along with the data bytes being written. This will force the entire page to endure a write cycle, for this reason endurance is specified per page."

so it doesn't make sense to use data blocks smaller than a 32 bytes page.

Look at the counter of the first page. If it's zero you used the maximum number of write cycles for that page, so you move on to the next page and check that counter. Repeat until you find a counter > zero. That's the page you're currently using. Microchip's EEPROMs have a 1 million cycles endurance, which you can increase to 256 million with the given example of maximum 32 bytes per block in a 64kb EEPROM. That should be enough to outlast your product: 40 years if you write once every 5 seconds(!).

You'll want to initialize your EEPROM on first use. How do you know when that is. Use the last page to write a unique signature upon initialization. Check at each power-up if the signature is there. If it isn't the device has to be initialized. You can preset the counter in each page with 0xF4240 (for 1 million) or clear everything to 0xFF and write the 0xF4240 when you first use the page.
Initializing an EEPROM is needed because sometimes a certain pattern is written to it in the production/test process.

edit
The wear leveling should solve your problems, but I still want to comment on the capacitor solution. You say the board is rather power-hungry, but maybe you can isolate the microcontroller/EEPROM's power from the rest of the board with a diode. So you'll probably need only a few mA when main power is gone. The 24AA64 writes a page in less than 5ms, then at 10mA and an allowable voltage drop of 100mV you'll need

\$ C = \dfrac{I \cdot t}{\Delta V} = \dfrac{10mA \cdot 5ms}{100mV} = 500\mu F \$

Easy with a small supercap.

further reading
datasheet 24AA64
EEPROM Endurance Tutorial

\$\endgroup\$
2
  • \$\begingroup\$ The endurance of the EEPROM is given per page (at least for 24AA64 and other EEPROMs that I've used). The 24AA64 specifies a 32-byte page, so the count should be per page and not per block. \$\endgroup\$
    – Saad
    Commented May 6, 2012 at 14:14
  • \$\begingroup\$ @Saad - Correct. Fixed in my answer. \$\endgroup\$
    – stevenvh
    Commented May 6, 2012 at 14:27
4
\$\begingroup\$

1) Once you've started the write process, you only need to power the MCU/EEPROM and make sure the control lines don't glitch - I2C probably preferable to SPI for this. Only need a few mA for a few milliseconds so shoudn't be a big cap,and you could put the MCU to sleep once the write is initiated. 3) you can probably apply some intelligence, e.g. a holdoff - once written it always holds a certain time beore another write can happen. Or wait til value is stable for a while before writing.
You can also increase endurance by spreading the data over a number of locations. Microchip have some tools & appnotes to calculate endurance for their eeproms, which may be useful.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ Microchip App note on endurance: ww1.microchip.com/downloads/en/AppNotes/01019A.pdf From the Appnote, you can also increase the endurance by about 2x by decreasing the operating voltage from 5v to 3.5v. \$\endgroup\$
    – vandee
    Commented Feb 28, 2011 at 14:57
  • 1
    \$\begingroup\$ If you use your first method, make sure that writing to the nonvolatile memory is the highest priority in your system once it starts, ie. that interrupts can't cause your values to change mid write or the micro to start some other processing which makes you run out of time. It is most important that you do not write corrupt values as you power down. Additionally, a CRC on the values would help you confirm that corruption did not occur, but you'd have to decide what to do if it did, such as using defaults. \$\endgroup\$
    – Martin
    Commented Feb 28, 2011 at 17:49
3
\$\begingroup\$

I would suggest using a block-oriented flash device, and use one byte from each block as a mode flag. Maintain as an invariant that almost all of the mode flags will be programmed; there will be only one block where the mode flag isn't programmed but the previous block's (wrapping if necessary) is. That block will be the one with the most recent data. When that block fills up, erase the following block (note that the block being erased could hold any combination of data during the erase cycle, and the invariant would still hold), then once the erase is done program the mode flag on what used to be the last block.

It will be necessary to protect the supply to the flash well enough to ensure that any attempt to program a byte will either succeed or fail its entirety, but it won't matter if an erase cycle is interrupted leaving a block full of arbitrary data, since the next attempt to write a data entry will re-erase that block.

If your data are 16 bits, a 64Kx8 chip will hold over 32,000 entries. Writing one entry per second would fill the chip about 2.7 times. Even a chip with an endurance of "only" 10K erase cycles would last over 10 years. Use of a larger chip, or one with 100K endurance, would increase the useful life proportionally.

\$\endgroup\$
2
\$\begingroup\$

1) Possibly the simplest option, although it might require hardware changes. I've achieved this before without PBC modifications by just increasing the decoupling caps and interrupting on the brown-out.

2) As you've pointed out, the issue with FRAM is the price!

3) Depending on the volatility of your temperature and position data, you'll increase the endurance by only writing if the value has changed. You might be sampling the temperature once every second, but if it only changes every 5 minutes, the problem is solved.

\$\endgroup\$
1
\$\begingroup\$

Here's how I solved this problem in my project:

Reserve 1 sector of flash to hold a bitmask of unused slots and a number of slots for the value.

The bitmask I used was 16 bytes long, so I had 128 slots to put values.

The bitmask is initialized to all ones, which in flash terms is the erased state.

When you want to write a new value, read in the bitmask and find the first bit that is a one. This is the slot number where you will write the value. Change that bit to a zero to mark it as used and write the bitmask back to flash without first erasing it. Next, write the value to the slot after the bitmask also without erasing the flash.

This way, you extend the flash write cycles by 128 times by writing the new bitmask with only a change from a one to a zero.

If the entire bitmask is 0, then erase the flash sector and start fresh.

\$\endgroup\$
5
  • 3
    \$\begingroup\$ I might disappoint you, but when you flash a bit, entire sector is overwritten. Your solution will make 'bitmask' sector dead really soon. \$\endgroup\$ Commented Feb 28, 2011 at 16:50
  • 1
    \$\begingroup\$ If you don't erase the flash, you don't use up one of the 10K erase cycles for the sector. If you have the value 0x7F and you write the value 0x3F, the result will be 0x3F. This keeps the bitmask up-to-date, but does not erase the flash. The erase only happens once the entire bitmask is 0. \$\endgroup\$ Commented Feb 28, 2011 at 17:03
  • \$\begingroup\$ If I'm wrong, let's discuss. I don't want bad answers here and I really don't want a bad design in my project. \$\endgroup\$ Commented Feb 28, 2011 at 17:04
  • \$\begingroup\$ I think Robert is right. On my microcontroller, you can only write 4 bytes at a time, but the required bits are set to zero. The only way to get them back to 1's is to blank the 1k block. Its only the erase cycles that wear the flash... \$\endgroup\$
    – Tim
    Commented Feb 28, 2011 at 20:43
  • 1
    \$\begingroup\$ It may be different for each type of memory and maybe even the memory vendor. I've seen EEPROMs must erase the page then re-write it for every write. I've seen flash memory you can write bits that are still 1's without erasing the page. \$\endgroup\$
    – mjh2007
    Commented Mar 1, 2011 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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