Hi,
I've developed a simple library to fire timed events.
Resolution is 1ms.
A more complete solution is to use Time + TimeAlarm libraries, which also have clock features, but are bigger than this lib (compiled code size).
Here's the code:
SimpleTimer.h:
/*
* SimpleTimer.h
*
*/
#ifndef SIMPLETIMER_H
#define SIMPLETIMER_H
#include <WProgram.h>
typedef void (*timer_callback)(void);
class SimpleTimer {
public:
// maximum number of timers
const static int MAX_TIMERS = 10;
// setTimer() constants
const static int RUN_FOREVER = 0;
const static int RUN_ONCE = 1;
// constructor
SimpleTimer();
// this function must be called inside loop()
void run();
// call function f every d milliseconds
int setInterval(long d, timer_callback f);
// call function f once after d milliseconds
int setTimeout(long d, timer_callback f);
// call function f every d milliseconds for n times
int setTimer(long d, timer_callback f, int n);
// destroy the specified timer
void deleteTimer(int numTimer);
// returns true if the specified timer is enabled
boolean isEnabled(int numTimer);
// enables the specified timer
void enable(int numTimer);
// disables the specified timer
void disable(int numTimer);
// enables or disables the specified timer
// based on its current state
void toggle(int numTimer);
// returns the number of used timers
int getNumTimers();
private:
// value returned by the millis() function
// in the previous run() call
long prev_millis[MAX_TIMERS];
// pointers to the callback functions
timer_callback callbacks[MAX_TIMERS];
// delay values
long delays[MAX_TIMERS];
// number of runs to be executed for each timer
int maxNumRuns[MAX_TIMERS];
// number of executed runs for each timer
int numRuns[MAX_TIMERS];
// which timers are enabled
boolean enabled[MAX_TIMERS];
// actual number of timers in use
int numTimers;
};
#endif
SimpleTimer.cpp:
#include "SimpleTimer.h"
SimpleTimer::SimpleTimer() {
long current_millis = millis();
for (int i = 0; i < MAX_TIMERS; i++) {
enabled[i] = false;
callbacks[i] = 0;
prev_millis[i] = current_millis;
}
numTimers = 0;
}
void SimpleTimer::run() {
int i;
long current_millis;
// get current time
current_millis = millis();
for (i = 0; i < MAX_TIMERS; i++) {
// only process active timers
if (callbacks[i]) {
// is it time to process this timer ?
if (current_millis - prev_millis[i] >= delays[i]) {
// update time
prev_millis[i] = current_millis;
// check if the timer callback has to be executed
if (enabled[i]) {
// "run forever" timers must always be executed
if (maxNumRuns[i] == RUN_FOREVER) {
(*callbacks[i])();
}
// other timers get executed the specified number of times
else if (numRuns[i] < maxNumRuns[i]) {
(*callbacks[i])();
numRuns[i]++;
// after the last run, delete the timer
// to save some cycles
if (numRuns[i] >= maxNumRuns[i]) {
deleteTimer(i);
}
}
}
}
}
}
}
int SimpleTimer::setTimer(long d, timer_callback f, int n) {
if (numTimers >= MAX_TIMERS) {
return -1;
}
delays[numTimers] = d;
callbacks[numTimers] = f;
maxNumRuns[numTimers] = n;
enabled[numTimers] = true;
numTimers++;
return (numTimers - 1);
}
int SimpleTimer::setInterval(long d, timer_callback f) {
return setTimer(d, f, RUN_FOREVER);
}
int SimpleTimer::setTimeout(long d, timer_callback f) {
return setTimer(d, f, RUN_ONCE);
}
void SimpleTimer::deleteTimer(int numTimer) {
if (numTimer >= MAX_TIMERS) {
return;
}
// nothing to disable if no timers are in use
if (numTimers == 0) {
return;
}
callbacks[numTimer] = 0;
enabled[numTimer] = false;
delays[numTimer] = 0;
// update number of timers
numTimers--;
}
boolean SimpleTimer::isEnabled(int numTimer) {
if (numTimer >= MAX_TIMERS) {
return false;
}
return enabled[numTimer];
}
void SimpleTimer::enable(int numTimer) {
if (numTimer >= MAX_TIMERS) {
return;
}
enabled[numTimer] = true;
}
void SimpleTimer::disable(int numTimer) {
if (numTimer >= MAX_TIMERS) {
return;
}
enabled[numTimer] = false;
}
void SimpleTimer::toggle(int numTimer) {
if (numTimer >= MAX_TIMERS) {
return;
}
enabled[numTimer] = !enabled[numTimer];
}
int SimpleTimer::getNumTimers() {
return numTimers;
}
Example sketch (modified version of Time+TimeAlarm example):
/*
* SimpleTimerAlarmExample.pde
*
* A timer is called every 15 seconds
* Another timer is called once only after 10 seconds
* A third timer is called 10 times.
*
*/
#include <SimpleTimer.h>
SimpleTimer timer;
void setup()
{
Serial.begin(9600);
Serial.println("SimpleTimer Example");
Serial.println("One timer is triggered every 15 seconds");
Serial.println("Another timer is set to trigger only once after 10 seconds");
Serial.println("Another timer is set to trigger 10 times");
Serial.println();
timer.setInterval(15000, RepeatTask); // timer for every 15 seconds
timer.setTimeout(10000, OnceOnlyTask); // called once after 10 seconds
timer.setInterval(1000, digitalClockDisplay);
timer.setTimer(1200, tenTimesTask, 10);
}
void RepeatTask()
{
Serial.println("15 second timer");
}
void OnceOnlyTask()
{
Serial.println("This timer only triggers once");
}
void tenTimesTask() {
static int k = 0;
k++;
Serial.print("called ");
Serial.print(k);
Serial.println(" / 10 times.");
}
void loop()
{
timer.run();
}
void digitalClockDisplay()
{
int h,m,s;
s = millis() / 1000;
m = s / 60;
h = s / 3600;
s = s - m * 60;
m = m - h * 60;
Serial.print(h);
printDigits(m);
printDigits(s);
Serial.println();
}
void printDigits(int digits)
{
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}