Pages: [1]   Go Down
Author Topic: Efficiently carry out an action ever x seconds.  (Read 606 times)
0 Members and 1 Guest are viewing this topic.
London, UK
Offline Offline
Full Member
***
Karma: 4
Posts: 189
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I need to carry out a WDT reset every 5 seconds but I want to put in a delay of 10 minutes.
I am unsure of how to use the millis function as I think that is what I need to accomplish it.
I am sure that millis would be better instead of:
Code:
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();

for 10 minutes.

Thanks
Logged

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2916
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Take a look at the IDE "File > Examples > 2.Digital > BlinkWithoutDelay"
sketch.

millis() BTW uses a long varible that takes something like 49.5 days before it
rollsover to zero.

« Last Edit: September 06, 2012, 05:33:15 pm by oric_dan(333) » Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The cheap and nasty hack would be to replace your ten minute delay with a loop that delays for five seconds and then calls the watchdog, and exit the loop when the ten minutes has elapsed. This avoids any major restructuring to your code.

A far better and more general approach IMO is to restructure your code so that instead of executing the actions and delays in a single pass through loop(), it checks whether any action needs to be taken each time loop() runs. So in pseudocode, your logic in loop() becomes:

If watchdog interval has elapsed since the last watchdog reset
    reset the watchdog
endif

If waiting and ten minutes has elapsed
   do whatever needs to be done next
endif

and so on.
 
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why use delay at all?
Code:
for (unsigned long starttime = millis(); millis() - starttime < 60UL*10; ) {
  wdt_reset();
}

EDIT: or this
Code:
for (unsigned long starttime = millis(); millis() - starttime < 60UL*10; wdt_reset());
« Last Edit: September 08, 2012, 11:10:21 pm by WizenedEE » Logged

London, UK
Offline Offline
Full Member
***
Karma: 4
Posts: 189
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks guys,
Went with this in the end.

Code:
unsigned long currentMillis = millis();
                       while((currentMillis - previousMillis < interval))
                       {
                              // save the last time you reset the watchdog
                              previousMillis = currentMillis;   
                              wdt_reset();
                       }
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It doesn't matter in this case, but if there was more going on in that loop and you wanted to maintain an accurate interval rather than allow the intervals to drift slightly, you'd want to do the increment like this, instead:
Thanks guys,
Went with this in the end.

Code:
                       unsigned long currentMillis = millis();
                       while((currentMillis - previousMillis < interval))
                       {
                              // save the last time you reset the watchdog
                              previousMillis = currentMillis;   
                              wdt_reset();
                       }

Firstly, that won't work because you aren't updating currentMillis inside the loop. Just call millis() directly instead of using that variable and it will work OK.

Secondly, it doesn't matter in this case but if there was more going on in that loop and you wanted your intervals to be maintained accurately then you would be better to update previousMillis like this:

Code:
previousMillis += interval;

The reason is that the result of millis() may be greater than (previousMillis + interval) by the time your sketch executes this code since the processor isn't infinitely fast. In effect, you are scheduling the next event based on the time this event was due, not the time your sketch handled it.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

London, UK
Offline Offline
Full Member
***
Karma: 4
Posts: 189
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh ok so from what I understood I need to do this?

Code:
unsigned long currentMillis = millis();
                       while((currentMillis - previousMillis < interval))
                       {
                              // save the last time you reset the watchdog
                              previousMillis += interval;   
                              wdt_reset();
                       }
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 67
Posts: 3674
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I need to carry out a WDT reset every 5 seconds

Why do you need to do this?
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh ok so from what I understood I need to do this?

No, you need to call millis() within the loop. I suggest you simply get rid of currentMillis completely and replace any reference with a call to millis().
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: [1]   Go Up
Jump to: