Often you need some task done in a specific interval. My timer class is just made for this situation. You can set a callback which is called in the interval, or just check if its time for the task. There is a also start
and stop
method, to start and stop the timer.
class Timer { public: /// The callback. /// typedef void (*Callback)(const unsigned long); public: /// Create a new timer with the given delay. /// Timer() : _callback(0), _start(0), _delay(200), _enabled(false) { }
The typedef
Callback
declares the type for the callback. It is a method which takes a unsigned long, with the current time as argument. The constructor just creates a stopped timer without callback.
/// Start the timer. /// void start(const unsigned long delay, const unsigned long currentTime) { _delay = delay; _start = currentTime; _enabled = true; }
You can start the timer by calling start()
with a given delay and the current time. It is assumed you use this timer with the loop pattern I described here.
The meaning of the delay depends on the value you use for the loop. If you are working will milliseconds, the delay is in milliseconds if you are using another unit, the delay has this unit.
The start method just stores the delay and the start time and sets the _enabled
flag.
/// Stop the timer. /// void stop() { _enabled = false; }
The stop()
method stops the timer. It just has to set the _enabled
flag to false
.
/// Check the timer. /// /// @return true if the timer "fires" /// bool check(const unsigned long currentTime) { if (!_enabled) { return false; } const unsigned long delta = currentTime - _start; if (delta >= _delay) { _start = currentTime; if (_callback) { _callback(currentTime); } return true; } return false; }
You have to call the check()
method in the loop
with the current time of the loop. The check will return true
if the event should happen, after the given delay and if a callback it set, this callback is called.
The method first checks if the timer is enabled. If this is the case, the delta between the current time and the start time is calculated. If this delta is greater than the set delay, the current time is used as new start time, the callback is called and the method returns true
. Otherwise the method just exists with false
.
/// Set a function to call if the timer fires. /// void setCallback(Callback callback) { _callback = callback; } private: Callback _callback; ///< The callback to call if the timer "fires". bool _enabled; ///< If the timer is enabled or not. unsigned long _start; ///< The start of the timer. unsigned long _delay; ///< The delay for the next event. };
With the last method you can set a callback and there are all the variables for the class.
Example Usage
You can use this class as shown below.
#include "Timer.h" bool ledState = false; Timer myTimer; void onTimer(const unsigned long currentTime); setup() { pinMode(13, OUTPUT); myTimer.setCallback(&onTimer); myTimer.start(1000, millis()); } loop() { const unsigned long currentTime = millis(); myTimer.check(currentTime); } void onTimer(const unsigned long currentTime) { ledState = !ledState; digitalWrite(13, (ledState ? HIGH : LOW)); }
Another example without callback:
#include "Timer.h" bool ledState = false; Timer myTimer; setup() { pinMode(13, OUTPUT); myTimer.start(1000, millis()); } loop() { const unsigned long currentTime = millis(); if (myTimer.check(currentTime)) { ledState = !ledState; digitalWrite(13, (ledState ? HIGH : LOW)); } }
Continue with: Measure Elapsing Time