Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

Simple HMS Count Up/Down Timer

Creator: Andrew Mascolo
Date: 11/7/2014

DOWNLOAD LIBRARY
As the name implies, this is a Hour, Minute and Second timer. You can set the time as either direct HMS or just in seconds (See SetTimer() ). The SetTimer function also prevents overflow, meaning if seconds or minutes is greater than 59, the difference is taken and the result is added to either minutes or hours.

Update:

11/12/2014: Added count up feature. See examples in the downloadable library.

Example:
SetTimer(1, 0, 70) -> 1H, 1M, 10S
or
SetTimer(3665) -> 1H, 1M, 5S

Functions:

CountUpDownTimer() : The timer itself (This is the constructor in the library) (UP/DOWN)
Timer() : (This is the actual timer in the library)
TimeHasChanged() : This returns true if the time has changed (in seconds)
SetTimer() : Input the time to count from, Format: H,M,S or just seconds ie. 3600 = 1 hour
StartTimer() : Start the timer sequence
StopTimer() : Stops the Timer completely
StopTimerAt() : Stops the timer at a specific time, Format: H,M,S
PauseTimer() : Pauses the timer until told to resume
ResumeTimer() : Resume timer from where it was paused at
ResetTimer() : This starts the timer over from the initial setTime
TimeCheck() : Returns true if the time is equal to particular time
ShowMicroSeconds() : Returns the current Microseconds
ShowMilliSeconds() : Returns the current Milliseconds
ShowSeconds() : Returns the current Seconds
ShowMinutes() : Returns the current Minutes
ShowHours() : Returns the current Hours


Sketch

unsigned long Watch, _micro, time = micros();
unsigned int Clock = 0, R_clock;
boolean Reset = false, Stop = false, Paused = false, _type;
volatile boolean timeFlag = false;

#define DOWN 0
#define UP 1

void setup()
{
  Serial.begin(115200);
  SetTimer(0,0,10); // 10 seconds
  StartTimer();
}

void loop()
{
  CountUpDownTimer(DOWN); // run the timer

  // this prevents the time from being constantly shown.
  if (TimeHasChanged() ) 
  {
    Serial.print(ShowHours());
    Serial.print(":");
    Serial.print(ShowMinutes());
    Serial.print(":");
    Serial.print(ShowSeconds());
    Serial.print(":");
    Serial.print(ShowMilliSeconds());
    Serial.print(":");
    Serial.println(ShowMicroSeconds());
    // This DOES NOT format the time to 0:0x when seconds is less than 10.
    // if you need to format the time to standard format, use the sprintf() function.
  }
}

boolean CountUpDownTimer(boolean Type)
{
  _type = Type;
  static unsigned long duration = 1000000; // 1 second
  timeFlag = false;

  if (!Stop && !Paused) // if not Stopped or Paused, run timer
  {
    // check the time difference and see if 1 second has elapsed
    if ((_micro = micros()) - time > duration ) 
    {
      _type == UP? Clock++ : Clock--;
      timeFlag = true;

      if (_type == DOWN && Clock == 0) // check to see if the clock is 0
        Stop = true; // If so, stop the timer

     // check to see if micros() has rolled over, if not,
     // then increment "time" by duration
      _micro < time ? time = _micro : time += duration; 
    }
  }
  return !Stop; // return the state of the timer
}

void ResetTimer()
{
  if(_type) 
    Clock = 0;
  else
    SetTimer(R_clock);

  Stop = false;
}

void StartTimer()
{
  Watch = micros(); // get the initial microseconds at the start of the timer
  Stop = false;
  Paused = false;
  if(_type == UP) 
    Clock = 0;
}

void StopTimer()
{
  Stop = true;
}

void StopTimerAt(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
  if (TimeCheck(hours, minutes, seconds) )
    Stop = true;
}

void PauseTimer()
{
  Paused = true;
}

void ResumeTimer() // You can resume the timer if you ever stop it.
{
  Paused = false;
}

void SetTimer(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
  // This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1, 2, 0
  unsigned int _S = (seconds / 60), _M = (minutes / 60);
  if(_S) minutes += _S;
  if(_M) hours += _M;

  Clock = (hours * 3600) + (minutes * 60) + (seconds % 60);
  R_clock = Clock;
  Stop = false;
}

void SetTimer(unsigned int seconds)
{
 // StartTimer(seconds / 3600, (seconds / 3600) / 60, seconds % 60);
 Clock = seconds;
 R_clock = Clock;
 Stop = false;
}

int ShowHours()
{
  return Clock / 3600;
}

int ShowMinutes()
{
  return (Clock / 60) % 60;
}

int ShowSeconds()
{
  return Clock % 60;
}

unsigned long ShowMilliSeconds()
{
  return (_micro - Watch)/ 1000.0;
}

unsigned long ShowMicroSeconds()
{
  return _micro - Watch;
}

boolean TimeHasChanged()
{
  return timeFlag;
}

// output true if timer equals requested time
boolean TimeCheck(unsigned int hours, unsigned int minutes, unsigned int seconds) 
{
  return (hours == ShowHours() && minutes == ShowMinutes() && seconds == ShowSeconds());
}


Output:

H:M:S:Mil:Mic
0:0:9:999:999916
0:0:8:1999:1999912
0:0:7:2999:2999916
0:0:6:3999:3999912
0:0:5:4999:4999912
0:0:4:5999:5999920
0:0:3:6999:6999920
0:0:2:7999:7999916
0:0:1:8999:8999916
0:0:0:9999:9999912