How accurate are delays within loops

I am trying to store a value 40 to EEPROM times a second so the value will be stored every 25ms. If I put a 25ms delay in the loop then it delays 25ms, but takes time to run the rest of the loop so the time will actually be more than 25ms for the loop to run. Does anyone know how long that additional time will be? Is there a function that I can use to test the time? The number of samples a minute is flexible, but I need to know as accurately as possible how long that extra time will be. Thanks

I am trying to store a value 40 to EEPROM times a second so the value will be stored every 25ms. If I put a 25ms delay in the loop then it delays 25ms, but takes time to run the rest of the loop so the time will actually be more than 25ms for the loop to run. Does anyone know how long that additional time will be? Is there a function that I can use to test the time? The number of samples a minute is flexible, but I need to know as accurately as possible how long that extra time will be. Thanks

delay() is pretty accurate, but fairly useless for a variety of other reasons. One of them of course being the problem you are running into. It's rather useless when used in conjunction with the rest of the program to perform overall timing.

Take a look at the Blink without Delay sample. That provides a good method for overall timing.

It will be about as long as it takes for you to completely kill your EEPROM.

Storing a value to EEPROM that frequently is just plain stupid. I'm sorry, but it is.

The EEPROM can only be written to a finite number of times. Approximately 100,000 times. At 40 times per second, that's 100,000/40 = 2500 seconds. That's a little over 41 minutes.

Stop now, before you go any further, and re-think just what you really want to do.

As for calculating how long the loop will take? Well, that depends on two factors:

  1. The number of instructions (and hence the number of clock cycles) the loop compiles into.
  2. The number of times the EEPROM has been written to - it slows down with use as it takes longer and longer to erase the cell before writing to it after a while. The death of an EEPROM cell isn't actually the cell dying per se, but the fact that it takes longer than a threshold timeout to erase.

I am trying to store a value 40 to EEPROM times a second so the value will be stored every 25ms

Are you crazy dude?
You can't store a value on eeprom 40 times in one second.
Did you know the eeprom writes are limited!!!

As others mentioned, you'll kill your EEPROM pretty quickly that way, but to answer your questions...

Ben1234:
Does anyone know how long that additional time will be?

That entirely depends on your code. If the rest of your loop is an assignment statement, a mere nano seconds. If the rest of your loop is a few hundred floating point calculations, then it might take a while.

Is there a function that I can use to test the time?

millis(). You're better off using that than delay() anyway.

Use millis(). Save the value from millis() in a variable (use an unsigned long variable). Then in the main loop, constantly check millis() and compare it against the saved value. When it's 25 more than the saved value, then 25ms have elapsed, so do the next write. The timing should be reasonably accurate, within half a percent or so.

You are aware that according to the datasheet, EEPROM endurance is 100,000 write/erase cycles? At 40 writes per second, that works out to 41 minutes or so. Some folks have tested this and reported significantly higher endurance, but once the datasheet spec is exceeded, I wouldn't bank on it.

And please don't cross-post.

Topics merged.

I'm really fed up having to tell people not to cross-post.

OP, you had two threads asking the same question in different parts of the forum.
Did it not occur to you that other people would answer in one thread and not realise that someone else had answered it in the other?
Don't you realise this wastes their time?
How do you think it makes that person feel?

DO NOT CROSS-POST.

CLEAR ENOUGH?

Ben1234:
I am trying to store a value 40 to EEPROM times a second so the value will be stored every 25ms. If I put a 25ms delay in the loop then it delays 25ms, but takes time to run the rest of the loop so the time will actually be more than 25ms for the loop to run. Does anyone know how long that additional time will be? Is there a function that I can use to test the time? The number of samples a minute is flexible, but I need to know as accurately as possible how long that extra time will be. Thanks

Setting aside the issue of killing the EEPROM, you can avoid the processing delay issue you mention if you code the time comparison correctly:

unsigned long lastTime;
const unsigned long interval = 25; // ms

...

if(millis() - lastTime > interval)
{
    // ... do stuff
    lastTime += interval;
}

The crucial part here is that you update lastTime to record when the event was due, not when your sketch handled it. This means the timing doesn't slip by however long it took your sketch to notice that the interval had elapsed.

if(millis() - lastTime >= interval)

The really crucial part is to get the right comparison.

Here is one of the articles on EEPROM endurance: Wear Leveling | Blinkenlight. Burning out the EEPROM is not a all or nothing issue though. It's more an issue of aging :wink:

I will not cross post in the future.

What exactly does the EEPROM "die" after 100,000 writes? I am only trying to store about 100 points which would theoretically be 2.5 seconds at 40 values per second. Afterwards I would upload them to the computer and wipe the old values. Any suggestions of a better way to do this? It was mentioned to me to instead use an SD card. If that is a good idea do you know of any tutorials or threads that you could point me in the direction of. Thanks.

Ben1234:
I will not cross post in the future.

What exactly does the EEPROM "die" after 100,000 writes? I am only trying to store about 100 points which would theoretically be 2.5 seconds at 40 values per second. Afterwards I would upload them to the computer and wipe the old values. Any suggestions of a better way to do this? It was mentioned to me to instead use an SD card. If that is a good idea do you know of any tutorials or threads that you could point me in the direction of. Thanks.

A great site that tells you all about it:

http://www.lostcircuits.com/mambo//index.php?option=com_content&task=view&id=69&Itemid=1&limit=1&limitstart=3

The important bit from it:

...cycling a NAND flash cell entails extremely high electrical fields that can exceed 10 million volts per cm, which is needed to force the electrons to pass through the oxide layer in either direction. Over time, this causes degradation of the oxide layer by causing atomic bonds to break within the oxide layer proper and also at its interfaces with the floating gate and the substrate. The intermediate result is trapping of electrons at the broken bond sites with the oxide layer acquiring negative electrical charges. As a consequence, the erase process becomes slower whereas the programming becomes faster.

Wear levelling is most commonly used to get around the problem - the more cells there are for you to write to, the more you can write before the whole thing becomes unusable.

The great thing with an SD card over the internal EEPROM is that a) the SD card is replaceable so can be swapped when it begins to die, and b) is considerably bigger than the internal EEPROM, so has many millions more cells for you to play with, so you have many millions times more lifetime from it. Most SD cards include their own wear levelling systems, so you can just forget about it and it does it for you.

There are plenty of tutorials and examples around for using an SD card with the Arduino. Check the Examples within the IDE for a start.

Oh, and one tip - don't write your data points direct to EEPROM/SD/Whatever. Collate them in RAM first, and then write them after the sampling has been done together in one batch.

Ben1234:
I am only trying to store about 100 points which would theoretically be 2.5 seconds at 40 values per second. Afterwards I would upload them to the computer and wipe the old values.

Why can't you store the 100 bytes in SRAM then until you upload it to the computer? The only reason to use EEPROM is if you want the values to persist through the Arduino being reset.

The reason why was because I thought that the Arduino might be turned off before I got it to the computer, but if I have an external battery and run the program and store the values, then plug it into the computer and upload it, that could work. Thanks for the idea!

In that case then if the loop only reads the analog values from the sensor and stores them - no calculations or other process later in the loop -, how close to 25ms per store do you think that I could get using SRAM?

AWOL:
The really crucial part is to get the right comparison.

Yes, that would be better, but in this case I don't think it makes any difference.

Do you think that it is possible to get 25ms loops or not?

25ms is an absolute eternity to a microcontroller. yes, you can get 25ms loops quite happily, and how to do it has already been shown you in an earlier answer.

Thanks for your help everyone!