Robware Software by Rob

A basic timer for the Arduino

For one of my Sonoff switches I'm using a timer to ping my PC so it switches everything off with my PC (see code). Originally, for the sake of time (forgive the pun), I ripped code from [url link="]this page[/url]. However, it was a bit more complicated to use that I anticipated and resetting the timer interval didn't always work (I don't know if it ever did, tbh). So I wrote my own, with significantly fewer lines. The only major disadvantage is that you can't register multiple timers under one loop method.

Anyway, here it is:

#ifndef _TIMER_h
#define _TIMER_h

#if defined(ARDUINO) && ARDUINO >= 100
	#include "arduino.h"
#else
	#include "WProgram.h"
#endif
#include <functional>

class Timer
{
 protected:
	 int _interval;
	 std::function<void()> _callback;
	 unsigned long _lastRunTime;
	 bool _enabled;
	 void constructor(int interval, std::function<void()> callback, bool startImmediately);

 public:
	 Timer(int interval, std::function<void()> callback);
	 Timer(int interval, std::function<void()> callback, bool startImmediately);
	 void loop();
	 void start();
	 void stop();
	 bool enabled();
	 void reset(int interval);
};

#endif
#include "Timer.h"

void Timer::constructor(int interval, std::function<void()> callback, bool startImmediately) {
	_interval = interval;
	_callback = callback;
	_enabled = false;
	if (startImmediately)
		start();
}

Timer::Timer(int interval, std::function<void()> callback) {
	constructor(interval, callback, false);
}

Timer::Timer(int interval, std::function<void()> callback, bool startImmediately) {
	constructor(interval, callback, startImmediately);
}

void Timer::loop() {
	if (!_enabled)
		return;

	if (millis() - _lastRunTime >= _interval) {
		_callback();
		_lastRunTime = millis();
	}
}

void Timer::start() {
	_enabled = true;
	_lastRunTime = millis();
}

void Timer::stop() {
	_enabled = false;
}

bool Timer::enabled() {
	return _enabled;
}

void Timer::reset(int interval) {
	stop();
	_interval = interval;
	start();
}

As you can see, there are two constructors; one for the setup and one for the setup as well as defining if it should start immediately. It's got a simple stop and start and you can reset the interval. Just call Timer.loop() in your loop() method to keep it running.

Here's the example code from what I used to develop it:

#include "Timer.h"
#include "Led.h"
#include "Button.h"

void resetTimer();
void toggleTimer();

Led led(13);
auto ledToggle = std::bind(&Led::toggle, &led);
Timer timer(1000, ledToggle, true);
Button button(0, toggleTimer, resetTimer);
bool shortReset = false;

void toggleTimer() {
	if (timer.enabled())
		timer.stop();
	else
		timer.start();
}

void resetTimer() {
	if (shortReset)
		timer.reset(250);
	else
		timer.reset(1000);
	shortReset = !shortReset;
}

void setup() {
}

void loop() {
	timer.loop();
	button.loop();
}
Posted on Saturday the 25th of February 2017