int or unsigned int is too small for the big numbers. This appears to work:
unsigned long Watch, _micro, time = micros();
unsigned long 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(9600);
SetTimer(3999, 23, 59, 59); // <<<<<<<<<<<<<<<<<<<<<<<<<<<
StartTimer();
}
void loop()
{
CountUpDownTimer(DOWN); // run the timer
// this prevents the time from being constantly shown.
if (TimeHasChanged() ) {
Serial.print(ShowDays());
Serial.print(" days");
Serial.print(" ");
if( ShowHours() < 10 ) Serial.print( '0' ) ;
Serial.print(ShowHours());
Serial.print(":");
if( ShowMinutes() < 10 ) Serial.print( '0' ) ;
Serial.print(ShowMinutes());
Serial.print(":");
if( ShowSeconds() < 10 ) Serial.print( '0' ) ;
Serial.print(ShowSeconds());
Serial.println(" ");
// delay(4000);
// 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 long days, unsigned long hours, unsigned long minutes, unsigned long seconds)
{
if (TimeCheck(days, 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 long days, unsigned long hours, unsigned long minutes, unsigned long seconds)
{
// This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1, 2, 0
unsigned long _H = (seconds / 3600), _S = (seconds / 60), _M = (minutes / 60);
if (_S) minutes += _S;
if (_M) hours += _M;
if (_H) days += _H;
//f Clock = (days * hours * 23 + hours * 3600) + (minutes * 60) + (seconds % 60);
Clock = (days * 24UL * 3600UL) + ( hours * 3600UL) + (minutes * 60UL) + (seconds % 60UL);
R_clock = Clock;
Stop = false;
}
void SetTimer(unsigned long seconds)
{
// StartTimer(seconds / 3600, (seconds / 3600) / 60, seconds % 60);
Clock = seconds;
R_clock = Clock;
Stop = false;
}
unsigned long ShowDays ()
{
return Clock / 86400;
}
unsigned long ShowHours()
{
return (Clock / 3600) % 24 ;
}
unsigned long ShowMinutes()
{
return (Clock / 60) % 60;
}
unsigned long 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 long days, unsigned long hours, unsigned long minutes, unsigned long seconds)
{
return (days == ShowDays() && hours == ShowHours() && minutes == ShowMinutes() && seconds == ShowSeconds());
}