Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ Electronics ➜ Microprocessors ➜ Elapsed time class

Elapsed time class

Postings by administrators only.

Refresh page


Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Wed 11 May 2011 02:54 AM (UTC)

Amended on Sun 22 Jan 2012 06:40 PM (UTC) by Nick Gammon

Message
One thing that seems to trip up beginners to the Arduino is the idea of implementing delays without using delay(). Hence the "blink without delay" example sketch. But that sketch is a bit confusing. You have to set up a "start" variable, assign the time to it, check it by doing subtraction rather than addition, and so on. And it gets more confusing if you want two time intervals.

The "elapsed" class below tries to simplify that. The class has a couple of member variables (startus and startms) which remember when you last "reset the timer". Then you simply call intervalMs (for milliseconds) or intervalUs (for microseconds) to see if your required time period is up. When it is, you can do something, like flash a LED. Then you can reset the timer if you want to.

Example snippet:


if (t2.intervalMs () > 200)   // time up?
    {
    digitalWrite(2, !digitalRead (2));   // toggle the LED
    t2.reset ();   // reset the timer
    }  // end if time up



The Arduino library can be downloaded from here:

http://www.gammon.com.au/Arduino/Elapsed.zip (4 Kb)

Unzip the file into your Arduino sketch "libraries" folder.

To use it just:


#include <Elapsed.h>


Example code that flashes two LEDs at different rates:


#include <Elapsed.h>

void setup() 
  {                
  pinMode (2, OUTPUT);     
  pinMode (3, OUTPUT);     
  }  // end of setup

static Elapsed t2, t3;

void loop() {

  if (t2.intervalMs () > 200)
    {
    digitalWrite(2, !digitalRead (2)); 
    t2.reset ();
    }

 if (t3.intervalMs () > 500)
    {
    digitalWrite(3, !digitalRead (3)); 
    t3.reset ();
    }
 
}  // end of loop



The example code flashes two LEDs at different intervals. The variables t2 (for pin 2) and t3 (for pin 3) are used to see if the time is up to toggle the LED state.

Note that the millisecond interval wraps around after about 50 days, and the microsecond interval wraps around after about 70 minutes. The wrap-around itself is handled correctly, but if you need to time an interval longer than 70 minutes you would need to check intervalMs rather than intervalUs.

As with millis() and micros() if you turn off interrupts the times may be out.

Warning: If you try to move the variables inside a function you will probably need to make them static (or they will reset each time the function is entered), like this:


void loop() {
static Elapsed t2, t3;  // must have static here
  // ...
}



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Yair   (3 posts)  Bio
Date Reply #1 on Sun 22 Jan 2012 01:31 PM (UTC)

Amended on Sun 22 Jan 2012 01:46 PM (UTC) by Yair

Message
hey nick, thanks for the many examples.
i *think* there is a typo in the closing code box
it has a void loop() in there.

also i would like to explore ways of dynamicly creating this elapsed timers. what is missing in this code?

void setup(){
}

void loop(){
  for(int i=0;i<10;i++){
    pulse(i);
  }
}

void pulse(int pin){
  if(time[pin].intervalMs() > 100) //how can i dynamicly create time01?
  {
     digitalWrite(pushPin[pin], LOW);
    time[pin].reset();
  }
}
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #2 on Sun 22 Jan 2012 06:43 PM (UTC)
Message
I was illustrating that the timer was inside loop. I've modified the post to make that clearer.

As for dynamically creating timers, you mean an array, like this?


#include <Elapsed.h>

Elapsed time [10];  // array of timers
const byte pushPin [10] =  { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

void setup(){
}

void loop(){
  for(int i=0;i<10;i++){
    pulse(i);
  }
}

void pulse(int pin){
  if(time[pin].intervalMs() > 100) //how can i dynamicly create time01?
  {
     digitalWrite(pushPin[pin], LOW);
    time[pin].reset();
  }
}


I don't see what you really get here that you couldn't just be using a single timer though.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Yair   (3 posts)  Bio
Date Reply #3 on Sun 22 Jan 2012 07:06 PM (UTC)

Amended on Sun 22 Jan 2012 07:16 PM (UTC) by Yair

Message
my understanding was that loop itself is a function, being called every "cycle".
i was sure it a typo as i used function with the 500ms code , without the static inside the loop() and it seems to work.


#include <Elapsed.h>
int goo;
void setup() 
{                
  Serial.begin (115200);   
}  // end of setup

static Elapsed time, time2;

void loop() {

  if (time2.intervalMs () > 500)
  {
    Serial.println ("tick2\n"); 
    H_pulseNod();
    time2.reset ();
  }
}  // end of loop

void H_pulseNod(){

  Serial.print("aaa > ");
  Serial.println(millis());
  if(time.intervalMs() > 1000)
  {  
    goo++;
    Serial.print("goo > ");
    Serial.println(goo);

    time.reset();
  }

}


im currently using tons of methods from your generous examples. especially the Serial state machine, clearly writen and so needed.
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #4 on Sun 22 Jan 2012 09:49 PM (UTC)
Message
What you have is fine. However your two variables time and time2 are not inside the loop(). If they were, you would need "static" or they get reset every time through loop().

Quote:

im currently using tons of methods from your generous examples ... clearly writen and so needed


Thanks! It's nice to get feedback. :)

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Yair   (3 posts)  Bio
Date Reply #5 on Sun 22 Jan 2012 11:09 PM (UTC)
Message
im having difficulties getting my digital pins to run in sequence, like in the chase example (example >control>arrays)
basically im looking for array with no delay. currently im not using array, just trying to get the sequence going. but im missing something.



void HwaveLeft(){  

  if(timerChase.intervalMs() > waveIntrvl && waveState==0){     
    H_pulse(0);
    waveState=1;
  }
  if(timerChase.intervalMs() > waveIntrvl*2 && waveState==1){     
    H_pulse(1);
    waveState=2;
  }
  if(timerChase.intervalMs() > waveIntrvl*4 && waveState==2){     
    H_pulse(2);
    waveState=3;
  }
  if(timerChase.intervalMs() > waveIntrvl*5 && waveState==3){     
    H_pulse(3);
    waveState=0;
    timerChase.reset();  
  }

void H_pulse(int pin){
  if(time[pin].intervalMs() > intrvl_kick && Hstate[pin]==0)
  {
    H_bwd(pin);
    Hstate[pin]=1;
  }
  if(time[pin].intervalMs() > intrvl_kick+intrvlOFF && Hstate[pin]==1) //50
  {
    H_fwd(pin);
    Hstate[pin]=2;
  }

  if(time[pin].intervalMs() > intrvl_kick+intrvlON && Hstate[pin]==2) //15
  {
    H_off(pin);
    Hstate[pin]=0;
    time[pin].reset();
  }
}



btw. feel free to direct me to the arduino forums if you see fit..
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #6 on Mon 23 Jan 2012 01:00 AM (UTC)
Message
Yes, probably a good idea. People are always asking about doing things in sequence there. If you make a post (put the whole sketch there, not just parts of it) and send me a PM on the forum giving the post link, I'll take a look at it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


22,072 views.

Postings by administrators only.

Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.