#Arduino Timer Library
ReadMe file for version 2.0
https://github.com/JChristensen/Timer
This library was originally developed by Dr. Simon Monk to avoid problems that arise when you start trying to do much inside the loop()
function. It can change pin values or run a callback function. See Dr. Monk's original page here).
The library does not interfere with the built-in timers, it just uses millis()
in a basic type of scheduler to decide when something needs doing.
##Examples
The Arduino delay()
function is both a blessing and a curse. It's great for showing beginners how to make an LED flash. But as soon as you get more complex and start slowing down your loop()
function you will run into problems.
A classic example is turning a relay on for 10 minutes. The delay()
way looks like this:
int pin = 13;
void setup()
{
pinMode(13, OUTPUT);
digitalWrite(pin, HIGH);
delay(10 * 60 * 1000);
digitalWrite(pin, LOW);
}
void loop()
{
}
The disadvantage of the delay()
approach is that nothing else can go on while the delay()
is happening. You cannot update a display, or check for key presses for example.
The Timer library version looks like this:
#include "Timer.h"
Timer t;
int pin = 13;
void setup()
{
pinMode(pin, OUTPUT);
t.pulse(pin, 10 * 60 * 1000, HIGH); // 10 minutes
}
void loop()
{
t.update();
}
The pulse()
method takes arguments of a pin to change, the period to change it for and its initial state.
The call to t.update()
takes a matter of microseconds to run, and when the appropriate period of time has passed, it will change the state of the pin.
Let's look at another example that uses two timer events. One to flash an LED and another that reads analog input 0 and displays its value on the Serial Monitor.
#include "Timer.h"
Timer t;
int pin = 13;
void setup()
{
Serial.begin(9600);
pinMode(pin, OUTPUT);
t.oscillate(pin, 100, LOW);
t.every(1000, takeReading, (void*)0);
}
void loop()
{
t.update();
}
void takeReading(void *context)
{
Serial.println(analogRead(0));
}
The first thing to notice is that we are using a callback function called takeReading()
. We connect it to the Timer using the every()
method, which in this case, will call the function every second.
We have also attached another event to the timer using the method oscillate()
. This will cause the LED to toggle state every 100 milliseconds.
Each of the events has an integer ID associated with it, so that you can stop an event, as we do in the example below, which will write to the serial monitor every 2 seconds, flash the LED and after 5 seconds, stop the LED flashing fast, and flash it 5 times slowly.
#include "Timer.h"
Timer t;
int ledEvent;
void setup()
{
Serial.begin(9600);
int tickEvent = t.every(2000, doSomething, (void*)0);
Serial.print("2 second tick started id=");
Serial.println(tickEvent);
pinMode(13, OUTPUT);
ledEvent = t.oscillate(13, 50, HIGH);
Serial.print("LED event started id=");
Serial.println(ledEvent);
int afterEvent = t.after(10000, doAfter, (void*)0);
Serial.print("After event started id=");
Serial.println(afterEvent);
}
void loop()
{
t.update();
}
void doSomething(void *context)
{
Serial.print("2 second tick: millis()=");
Serial.println(millis());
}
void doAfter(void *context)
{
Serial.println("stop the led event");
t.stop(ledEvent);
t.oscillate(13, 500, HIGH, 5);
}
By default the timer supports 10 events, but you can also specify a different number when instantiating the timer.
Note that the callback functions have a "context" parameter. The context value is specified when the event is created and it will be sent to callback function when the timer fires. The context is a void pointer, so it can be cast to any other data type. Its use is optional, if you don't need it, just code (void*)0
as in the above examples, but be sure that the callback function definitions have it in their argument list, i.e. (void *context)
.
##Installation
As with all libraries, unzip the file into the libraries folder in your Arduino sketchbook directory, which will be something like My Documents\Arduino\sketchbook on Windows, Documents/Arduino/sketchbook on Mac etc. If this is the first library you have installed, you will need to create a directory there called libraries.
The Timer library is compatible with both Arduino 1.0+ and earlier versions.
##Reference
###Timer();
#####Description
Creates a new instance of a timer. The maximum number of timers this instance can handle is 10. The internal event array consumes 0xBE bytes of SRAM in the .bss section.
#####Syntax
Timer t;
#####Returns
A Timer instance
###Timer(byte numberOfEvents);
#####Description
Creates a new instance of a timer. The internal event array for the timers is allocated dynamically from the heap using malloc. Each additional event will consume 0x13 bytes of SRAM.
#####Syntax
Timer t(numberOfEvents);
#####Returns
A Timer instance
###every();
#####Description
Runs the callback function every period milliseconds. Optionally stops after repeatCount times.
#####Syntax
t.every(period, callback, context);
t.every(period, callback, repeatCount, context);
#####Parameters
period: How often to run the callback function, in milliseconds (unsigned long)
callback: The name of the callback function which is called when the timer event fires (function pointer)
repeatCount: The number of times to run the callback function (int, optional)
context: Context value to be passed to the callback function (void pointer)
#####Returns
The ID of the Timer event (int8_t or char)
###after();
#####Description
Run the callback function once, after period milliseconds.
#####Syntax
t.after(period, callback, context);
#####Parameters
period: How long to wait before running the callback function, in milliseconds (unsigned long)
callback: The name of the callback function which is called when the timer event fires (function pointer)
context: Context value to be passed to the callback function (void pointer)
#####Returns
The ID of the Timer event (int8_t or char)
###oscillate();
#####Description
Toggle the state of the digital output pin every period milliseconds. The pin's starting value is specified by startingValue, which should be HIGH or LOW. Optionally stops after repeatCount times.
#####Syntax
t.oscillate(pin, period, startingValue);
t.oscillate(pin, period, startingValue, repeatCount);
#####Parameters
pin: The number of the pin to oscillate (uint8_t or byte)
period: How often to toggle the pin, in milliseconds (unsigned long)
startingValue: HIGH or LOW, the state at which the pin will start (uint8_t or byte)
repeatCount: Optional number of toggles to stop after (int)
#####Returns
The ID of the Timer event (int8_t or char)
###pulse();
#####Description
Generates a pulse of !startingValue, occuring period after the call to this method and lasting for period. The pin will be left in !startingValue state.
#####Syntax
t.pulse(pin, period, startingValue);
#####Parameters
pin: The number of the pin to pulse (uint8_t or byte)
period: The pulse period in milliseconds (unsigned long)
startingValue: HIGH or LOW, the state at which the pin will start (uint8_t or byte)
#####Returns
The ID of the Timer event (int8_t or char)
###pulseImmediate();
#####Description
Generates a pulse of startingValue, which begins immediately and lasts for period. The pin will be left in the !startingValue state.
#####Syntax
t.pulseImmediate(pin, period, pulseValue);
#####Parameters
pin: The number of the pin to pulse (uint8_t or byte)
period: The pulse period in milliseconds (unsigned long)
startingValue: HIGH or LOW, the state at which the pulse will start (uint8_t or byte)
#####Returns
The ID of the Timer event (int8_t or char)
###stop();
#####Description
Stops the given timer event.
#####Syntax
t.stop(timerID);
#####Parameters
timerID: The number of the timer event to be stopped, as returned previously by one of the other functions, e.g. every()
, after()
, oscillate()
, etc.
#####Returns
If a valid timerID is given, returns TIMER_NOT_AN_EVENT to indicate that the timer was successfully stopped. By default, the library supports up to 10 events per timer; the valid range is therefore 0-9. If a value outside this range is given, that same value is returned.
###update();
#####Description
Must be called from loop()
. This will service all the events associated with the timer.
#####Syntax
t.update();
#####Parameters
None.
#####Returns
None.
##Revision History
####1.0 by Simon Monk
- Library as downloaded 02Feb2012 22:55 UTC from http://srmonk.blogspot.com/2012/01/arduino-timer-library.html
####1.1 by Jack Christensen Changed data types of variables and functions:
- event types and indexes changed from int to int8_t.
- periods and durations changed from long to unsigned long.
- update() and stop() functions typed as void, since they return nothing.
- pin numbers and pin values changed from int to uint8_t, this agrees with digitalWrite().
- added return values to Timer::pulse() and Timer::oscillate(uint8_t, unsigned long, uint8_t).
- changed test in Event::update() to use subtraction to avoid rollover issues.
- Updated keywords.txt file to include all functions.
####1.2 by Damian Philipp
- Added a range check to Timer::stop() to avoid memory corruption.
- Added constants to <Timer.h>:
- NO_TIMER_AVAILABLE: Signals that while an event was to be queued, no free timer could be found.
- TIMER_NOT_AN_EVENT: Can be used to flag a variable that might contain a timer ID as not containing a timer ID
- Replaced a bunch of magic numbers in Timer.cpp with the above constants
- Added several comments
- Added Timer::pulseImmediate(). pulseImmediate sets the pin to the specified value for the given duration. After the duration, the pin is set to !value.
####1.3 by Jack Christensen
- Added "blink2" example illustrating flashing two LEDs at different rates.
- 19Oct2013: This is the last v1.x release. It will continue to be available on GitHub as a branch named v1.3. Future development will continue with Sandy Walsh's v2.0 which can pass context (timer ID, etc.) to the callback functions.
####2.0 by Sandy Walsh
- Added a "context" parameter to callbacks. You can pass in the context when the event is created and it will be sent back to callback when called. If you don't have any context data you want to pass in (let's say you're using separate callbacks for each timer), you can just pass in 0 and ignore it in the callback.
####2.1 by Thomas Mohaupt
- Changed the stop() method to return TIMER_NOT_AN_EVENT when it is given a valid timer event ID. Given an invalid (out of bounds) ID, it simply returns the same ID that it was given.
- Converted the ReadMe file to Markdown, added examples, reference, etc. from Dr. Monk's site. [jc].
- Minor cosmetic editing, tabs to spaces [jc].