This is an Arduino library for managing event timing. It provides relatively intuitive tools for creating non-blocking timing events in your code.
This library consists of a collection of classes:
TimeGetter: gets the current time.Timer: counts up as time passes, can be set to a particular value or reset to zero.OnDelay: turns an output value on, a fixed amount of time after an input value has been turned on.OffDelay: turns an output value off, a fixed amount of time after an input value has been turned off.Debounce: is essentially a combination of bothOnDelayandOffDelay; it can be used to debounce digital inputs.SquareWave: generates a square wave with a fixed period and duty cycle.SampleTimer: turns an output value on once per scan/loop at a fixed interval; it can be used for sampling values.Edge: detects the rising and falling edge of an input value.LinearRamp: moves an output value toward an input value at a settable rate.
This library should work on any microcontroller board. It relies on millis() from the Arduino API/Language, but has no other dependencies.
- TimerExample
- OnDelayExample
- OffDelayExample
- DebounceExample
- SquareWaveExample
- SampleTimerExample
- EdgeExample
- LinearRampExample
update()
Updates the time for all classes in this library except
Edgeor instances that use aTimeGetter. This is usually run once at the beginning ofloop().
AutomationTimers.update()#include <AutomationTimers.h> void setup() { // run setup stuff here } void loop() { AutomationTimers.update(); // run other loop stuff here }
getCurrentMillis()
Gets the time in
millis()of the lastupdate().
AutomationTimers.getCurrentMillis()
TimeGetter
AutomationTimers.update()andAutomationTimers.getCurrentMillis()utilize a default instance ofTimeGetter. If you only have one loop and are always working with milliseconds, you do not need to do anything withTimeGetter. However, if you are using an RTOS and have multiple loops in different tasks/threads, and you want to use this library in more than one of them, you will need to utilizeTimeGetter.TimeGetteralso allows you to work with time units other than milliseconds.// This example was written with an ESP32-C3 running FreeRTOS in mind #include <AutomationTimers.h> void taskAFn(void *parameter) { static TimeGetter timeGetter; static SquareWave squareWave(timeGetter, 1, 2); // using timeGetter, on for one second, off for two pinMode(LED_BUILTIN, OUTPUT); while (true) { timeGetter.update(millis() / 1000); // use seconds instead of milliseconds digitalWrite(LED_BUILTIN, squareWave); delay(10); // allow other tasks to run } } void taskBFn(void *parameter) { static TimeGetter timeGetter; // we can use the same name as before because this is in a different scope static OnDelay onDelay(timeGetter, 500); // using timeGetter (local scope), wait 500ms afer input to turn output on pinMode(2, INPUT_PULLUP); // a button should be placed between pin 2 and GND pinMode(3, OUTPUT); // a LED with current limiting resistor should be placed between pin 3 and GND while (true) { timeGetter.update(millis()); // use milliseconds here onDelay.update(!digitalRead(2)); digitalWrite(3, onDelay); delay(10); // allow other tasks to run } } void setup() { xTaskCreate(taskAFn, "taskA", 1024, NULL, 1, NULL); // start task A xTaskCreate(taskBFn, "taskB", 1024, NULL, 2, NULL); // start task B vTaskDelete(NULL); // delete the default (this) task } void loop() { // this should never run }TimeGetter operator
Returns the time according to the last
update()of theTimeGetter.Data type:
unsigned long.update()
Updates the time for all instances of classes in this library that use the specified
TimeGetter. This is usually run once at the beginning of a loop.
timeGetter.update(currentTime)
timeGetter: aTimeGetterobject.currentTime: a time value, usuallymillis(). Allowed data typeunsigned long.#include <AutomationTimers.h> TimeGetter myTimeGetter; void setup() { // run setup stuff here } void loop() { myTimeGetter.update(millis()); // run other loop stuff here }
TimeGettercan be utilized by theTimer,OnDelay,OffDelay,Debounce, andLinearRampclasses.
Timer
A
Timerobject acts like anunsigned longthat always counts up in milliseconds. It can be reset to 0 using thereset()method, or set to a value of your choosing using theset()method.The value of a
Timeris prevented from overflowing; once a timer reaches the highest value anunsigned longcan hold, it will stay there until it is reset, or until it is set to a lower value.#include <AutomationTimers.h> Timer myTimer; void setup() { pinMode(2, INPUT_PULLUP); Serial.begin(9600); } void loop() { // AutomationTimers.update() is what actually updates the timer value. // It should be run once per loop. // It only needs to be run once, even when using multiple Timer objects. AutomationTimers.update(); // If pin 2 is HIGH, the timer will be reset to 0, so the timer only counts up when pin 2 is LOW. if (digitalRead(2)) myTimer.reset(); // This will print the timer value in milliseconds. Serial.println(myTimer); delay(50); }Timer constructor
Creates a
Timerobject.
TimerTimer(timeGetter)
timeGetteraTimeGetterobject.Timer myTimer;Timer operator
Returns the value of the timer in milliseconds.
Data type:
unsigned long.if (myTimer >= 2000) { // do something }reset()
Resets the timer to 0.
if (myTimer >= 2000) { myTimer.reset(); // do something else }set()
Sets the timer to a value of your choosing.
set(setMillis)
setMillis: the value to set the timer to. Allowed data type:unsigned long.if (myTimer >= 2000) { myTimer.set(myTimer - 2000); // do something at a more accurate cadence }
Timeris utilized in theOnDelay,OffDelay,Debounce, andLinearRampclasses.
OnDelay
INPUT: ___/""""""""""""""""""\___ | OUTPUT: ___|_________/""""""""\___ | | |<-DELAY->|OnDelay constructor
Creates an
OnDelayobject.
OnDelay(delay)OnDelay(timeGetter, delay)
delay: the delay to wait before setting the outputtrue. Allowed data type:unsigned long.timeGetter: aTimeGetterobject.OnDelay myOnDelay(1000);OnDelay operator
Returns the value of the output.
Data type:
bool.if (myOnDelay) { // do something }update()
Updates the input of an
OnDelayobject.
myOnDelay.update(input)
myOnDelay: anOnDelayobject.input: Allowed data typebool.The value of the output. Data type:
bool.
Reading the output is optional.
OffDelay
INPUT: ___/""""""""\_____________ | OUTPUT: ___/""""""""|"""""""""\___ | | |<-DELAY->|OffDelay constructor
Creates an
OffDelayobject.
OffDelay(delay)OffDelay(timeGetter, delay)
delay: the delay to wait before setting the outputfalse. Allowed data type:unsigned long.timeGetter: aTimeGetterobject.OffDelay myOffDelay(1000);OffDelay operator
Returns the value of the output.
Data type:
bool.if (myOffDelay == false) { // do something }update()
Updates the input of an
OffDelayobject.
myOffDelay.update(input)
myOffDelay: anOffDelayobject.input: Allowed data typebool.The value of the output. Data type:
bool.
Reading the output is optional.
Debounce
INPUT: ___/""""""""""""""""""\_____________ | | OUTPUT: ___|_________/""""""""|"""""""""\___ | | | | |<-DELAY->| |<-DELAY->|Debounce constructor
Creates a
Debounceobject.
Debounce(delay)Debounce(timeGetter, delay)
delay: the delay to wait before setting the outputtrueand the delay to wait before setting the outputfalse. Allowed data type:unsigned long.timeGetter: aTimeGetterobject.Debounce myDebounce(1000);Debounce operator
Returns the value of the output.
Data type:
bool.if (myDebounce) { // do something }update()
Updates the input of an
Debounceobject.
myDebounce.update(input)
myDebounce: aDebounceobject.input: Allowed data typebool.The value of the output. Data type:
bool.
Reading the output is optional.
SquareWave
Description
Generates a square wave.
OUTPUT: ___/"""""""""""""\______________/""" | | | |<-ON PERIOD->|<-OFF PERIOD->| | | |<-------TOTAL PERIOD------->|
$dutyCycle=\frac{onPeriod}{totalPeriod}$ Methods
SquareWave constructor
Description
Creates an
SquareWaveobject.Syntax
SquareWave(totalPeriod, dutyCycle)SquareWave(onPeriod, offPeriod)SquareWave(timeGetter, totalPeriod, dutyCycle)SquareWave(timeGetter, onPeriod, offPeriod)Parameters
totalPerid: the total period of the square wave. Allowed data type:unsigned long.dutyCycle: the duty cycle of the squate wave. This should be less than1and greater than0. Allowed data type:float.onPerid: the period square wave istrue/HIGH. Allowed data types:intandunsigned long.offPerid: the period square wave isfalse/LOW. Allowed data types:intandunsigned long.timeGetter: aTimeGetterobject.Example
SquareWave myFirstSquareWave(2000, 0.5); // total period, duty cycle SquareWave mySecondSquareWave(1000, 1000); // on time, off timeSquareWave operator
Description
Returns the value of the output.
Returns
Data type:
bool.Example
digitalWrite(LED_BUILTIN, mySquareWave);
SampleTimer
OUTPUT: ___/\__________________/\___ | | |<--SAMPLE PERIOD-->|SampleTimer constructor
Creates an
SampleTimerobject.
SampleTimer(samplePeriod)SampleTimer(timeGetter, samplePeriod)
samplePerid: how often to turn the output on. Allowed data type:unsigned long.timeGetter: aTimeGetterobject.SampleTimer mySampleTimer(5000);
Edge
INPUT: ___/""""""""""\____ RISING: ___/\______________ FALLING: ______________/\___ CHANGE: ___/\_________/\___Edge operator
Returns the value of the input.
Data type:
bool.bool input = myEdge;update()
Updates the input of an
Edgeobject.
myEdge.update(input)
myEdge: anEdgeobject.input: Allowed data typebool.Nothing
rising()
Returns
truewhen a rising edge is detected on the input.
myEdge.rising()
myEdge: anEdgeobject.Data type:
bool.falling()
Returns
truewhen a falling edge is detected on the input.
myEdge.falling()
myEdge: anEdgeobject.Data type:
bool.
LinearRamp
|""""""""""""| INPUT: ____| | _______ | | | |____________| | | | | | | | | | | /"""""""""""\ | OUTPUT: _____/ \ | _____ \ | / \_________/LinearRamp constructor
Creates a
LinearRampobject.
LinearRamp(rate)LinearRamp(timeGetter, rate)
rate: the inital ramp rate. When not using thetimeGetterparameter, this is in units per millisecond. Allowed data type:float.timeGetter: aTimeGetterobject.LinearRamp myRamp(0.1);LinearRamp operator
Returns the value of the output.
Data type:
float.long output = myRamp;update()
Updates the input of a
LinearRampobject.
myRamp.update(input)
myRamp: aLinearRampobject.input: the target value to ramp to. Allowed data typefloat.Returns the value of the output. Data type:
float.
Reading the output is optional.setRate()
sets the ramp rate of a
LinearRampobject. When not using a user definedtimeGetter, this is units per millisecond. Otherwise it is in units per whatever time units the associatedTimeGetteris getting.
myRamp.setRate(rate)
myRamp: aLinearRampobject.rate: the ramp rate. Allowed data type:float.