4

I currently have a for loop that loops 300 times and then moves on.

Instead, I'd like that loop to run for a specific number of minutes, instead.

Here's the current loop, for reference.

for(int i = 1; i<300; i++){
  if (kill() == true){ break; }

  strip.setPixelColor(1, strip.Color(random(100,255),random(100,255),random(100,255)));
  strip.show();

  tone(TONE, notes[random(0,3)]);
  delay(100);
}

Also, I have an RTC that's used elsewhere in the app, so real actual time is available for use if it makes sense to do that...though I'd love to know of a way to do it without an RTC module for future projects.

8

Here is an example that will run for 5 minutes. Note that the loop will begin executing anytime before the time limit is up, including 1 msec before; it can't cut-off something happening at the 5-minute mark, meaning the timing precision will be limited to the duration of the code in the loop.

Update: My first suggestion had a bug related to the 50-some-odd days roll-over period of the millis() clock. This one is more robust:

uint32_t period = 5 * 60000L;       // 5 minutes

for( uint32_t tStart = millis();  (millis()-tStart) < period;  ){
   doStuff();
   moreStuff();
}
  • This is based on "5 minutes from the start of the Arduino" though, right? – Shpigford Mar 25 '16 at 18:05
  • 2
    No, it's based on the time of entry to the loop. The for-loop's first clause calculates the ending time, and the second clause compares the current time at the top of each loop to that time. – JRobert Mar 25 '16 at 18:08
  • Just tested and works wonderfully. Thanks! – Shpigford Mar 25 '16 at 18:14
  • To your update, does tQuit need to be defined somewhere? – Shpigford Mar 25 '16 at 18:21
  • Acch! That what I get for coding on the fly! tQuit is no longer used (the bug was related to tQuit). That should say 'period'. (fixed). Thanks for the catch. – JRobert Mar 25 '16 at 18:33
2

Using this example:

http://playground.arduino.cc/Code/ElapsedMillis

You could try something like:

#include <elapsedMillis.h>

elapsedMillis timeElapsed;
unsigned int interval = 60000; //one minute in ms

while(timeElapsed < interval){
    //do stuff
}

Depending on how accurate you want to be, you might want to opt for a similar method using the RTC.

  • Nice, "These special variable types automatically increase as time elapses." – Arjan Mar 25 '16 at 19:04
2

You can use a variable that is incremented each time you perform the loop, then you need only to change the loop from using a for to a while.

For example:

   int incremented_variable = 0;
   int incremented_value = 100;
   int max_value = 1000;  

   while(incremented_variable < max_value){
   if (kill() == true){ break; }

   strip.setPixelColor(1, strip.Color(random(100,255),random(100,255),random(100,255)));
   strip.show();

   tone(TONE, notes[random(0,3)]);

   delay(100);
   incremented_variable = incremented_variable + incremented_value;
   }

EDIT: I have just read your update on the question.

You can then use a while with a boolean flag that help you to end the loop or if you prefer, you can keep track of the time by calling the method: millis().

  • But how does that equate to actual time? i.e. "This loop has been running for 5 minutes." – Shpigford Mar 25 '16 at 17:07
  • @Shpigford you can manage to control the time changing the incremented_value that now is set to 100 and the max_value that is set to 1000. As an advice run the script only once to see the time it takes to perform only one time than you set those value accordingly. – rebatoma Mar 25 '16 at 17:10

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.