Go Down

Topic: Countdown library (Read 768 times) previous topic - next topic

robtillaart

Oct 29, 2015, 02:21 pm Last Edit: Oct 29, 2015, 02:40 pm by robtillaart
Often projects need to count down to a certain event, e.g. a surprise, new year or a birthday.

For this I made a simple CountDown class  (you may recognize parts of the StopWatch class).

Code: (snippet from countdown.h) [Select]
class CountDown
{
public:
    enum State { RUNNING, STOPPED };
    enum Resolution { MILLIS, MICROS, SECONDS };

    explicit CountDown(const enum Resolution res = MILLIS);
    void setResolution(const enum Resolution res = MILLIS);

    void start(uint32_t ticks);
    // void start(uint16_t h, uint8_t m, uint8_t s);
    void stop();
    unsigned long remaining();
    bool isRunning() const             { return _state == CountDown::RUNNING; };
    enum Resolution resolution() const { return _res; };

private:
  ....
};


The complete code - https://github.com/RobTillaart/Arduino/tree/master/libraries/CountDown -

demo application that counts down 5 seconds to 1 and then stops.
Code: [Select]
//
//    FILE: countdown_demo.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: demo
//    DATE: 2015-10-28
//     URL: http://forum.arduino.cc/index.php?topic=356253
//
// Released to the public domain
//

#include "CountDown.h"

CountDown CD(CountDown::SECONDS);

void setup()
{
    Serial.begin(115200);
    Serial.print("Start ");
    Serial.println(__FILE__);

    CD.start(5);

    while (CD.remaining() > 0 && CD.isRunning() )
    {
        Serial.println(CD.remaining() );
        if (CD.remaining() < 2) CD.stop();
    }
    Serial.println(CD.remaining());
    Serial.println("done...");
}

void loop()
{
}


Todo:
+ more tests especially the setResolution() call
+ refactor, rethink the interface
+ add continue() for after stop() ?
+ add start(hours, minutes, seconds)

as always remarks and comments are welcome
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

HazardsMind

#1
Oct 29, 2015, 04:59 pm Last Edit: Oct 29, 2015, 05:00 pm by HazardsMind
Need any help or tips? My CountUpDownTimer library may be "simple" but it could help you with yours.
It's in my github account. Link is in my footer.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

@Hazardsmind
quick look, complete different approach which is fun.

1) I do not understand the why of the modulo 60 for seconds

https://github.com/AndrewMascolo/CountUpDownTimer/blob/master/CountUpDownTimer.h


line 103  Clock = (hours * 3600) + (minutes * 60) + (seconds % 60);

I am allowed to call SetTimer(6750, 540, 120);
but only the seconds are restricted to 0..59
why then is it a unsigned long ?

2) your timeCheck() does check for equallity, but if the time between checking is several seconds it could have passed already?


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

HazardsMind

#4
Oct 29, 2015, 05:48 pm Last Edit: Oct 29, 2015, 05:55 pm by HazardsMind
The setTimer function really only looks at the minutes and seconds. It takes into consideration or at least tries to adjust for improper input.

So your values (6750, 540, 120); will be converted to the standard range.
Quote
unsigned int _S = (seconds / 60), _M = (minutes / 60);
if(_S) minutes += _S;
if(_M) hours += _M;
Seconds: 120 % 60 = 0 but 120/60 = 2, which gets carried over and added to the minutes.
Minutes 540 /60 = 9 which goes into hours.

So the total time is (6759h, 2m, 0s)

However the total clock time in seconds is (6759*3600 + 2*60 + 0) = 24332520 (total seconds)

It's unsigned long because there is always that one person who wants to break it with (1h, 10m, 3351351351s)

Quote
2) your timeCheck() does check for equallity, but if the time between checking is several seconds it could have passed already?
I never really thought to check for if the time had already passed. Ill add it in. Good spot.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

odometer

What about some kind of print or toString method?


Also, I see a problem here:
Code: [Select]
static unsigned long seconds() { return millis() / 1000; };
because it will stay within the range 0 ~ 4294967 (count the digits), and once it reaches the high end of the range, it will jump back to 0.
Perhaps better to use something like:
Code: [Select]

static unsigned long seconds() {
  static unsigned long count = 0UL;
  static unsigned long offset = 0UL; 
  unsigned long excess = micros() - offset; 
  if (excess >= 1000000UL) {
    excess /= 1000000UL; // convert to whole seconds
    offset += (excess * 1000000UL);
    count += excess;
  }
  return count;
}


robtillaart

In an effort to dust off some older libs a new version of my countdown lib saw daylight.

version 0.1.2
+ add days to start(days, hours, minutes, seconds)
+ cont() ==> continue countdown
+ update + add examples

As always remarks and comments are welcome

Regards,
Rob

@Odometer
just reread your comment on the seconds(), it still makes sense (thanks)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up