Easy access to advanced Arduino/AVR timer functions, such as precise timing, pulse generation, and input event capture.
Directly manipulating the timers/counters in Arduino and AVR is tedious and confusing. This library makes that simple by providing a number of convenience methods for accessing the timers. Easily attach interrupts to input capture events, extend the range of timers to 32 bits, or emit precisely timed pulses.
- Abstracts much of the Arduino/AVR timer functionality - no bit-twiddling needed!
- Extend timer ranges to 32 bits - about 268 seconds at 16 MHz with a precision of 1 clock cycle
- Precise pulse generator
- Input capture interrupts, similar to Arduino interrupts
- Tested on Uno, Mega2560. Could easily adapt to other AVR chips
- No dependency on Arduino framework.
- LGPL v3
- alarm - call a function some time in the future
- code-timing - Count the number of clock cycles that a piece of code takes
- pulse-generator - Similar to the classic Blink example, but with precise, jitter-free timing
- blink-timing - Use an input capture unit to time the classic delay-based Blink example
Include the TimerExtensions.h header.
This library provides a number of convenience functions so you don't have to mess with AVR registers. Simply use digitalPinToTimer() to find the timer for a pin, or use timer names (TIMER0, TIMER1, etc.) to identify timers.
setTimerClock(timer, clock)
- set the clock speed of a timer, relative to the CPU clock. Note that a value of None means that the clock is stopped.
setTimerMode(timer, mode, resolution)
- change the timer mode.
getTimerValue(timer)
setTimerValue(timer, ticks)
- get and set timer value. Most useful when the clock is stopped, and in Normal, CTC, or Fast PWM modes.
clockCyclesPerTick(clock)
ticksToClockCycles(ticks, clock)
ticksToMilliseconds(ticks, clock)
ticksToMicroseconds(ticks, clock)
clockCyclesToTicks(clockCycles, clock)
millisecondsToTicks(milliseconds, clock)
microsecondsToTicks(microseconds, clock)
Input capture pins allow you to measure the precise time of an external event. The value of of the timer is stored when the correct edge is detected (RISING or FALLING), and this is done independently of the CPU or interrupts. This can be used to determine the exact time of the event. Best used with normal timing mode.
hasInputCapture(timer)
clearInputCapture(timer)
setInputCaptureEdge(timer, edge)
getInputCapture(timer, clear = true)
- Allow you to poll for whether there is an input capture event.
setInputCaptureNoiseCancellerEnabled(timer, enabled)
getInputCaptureNoiseCancellerEnabled(timer)
- Enable or disable the noise canceller for input capture. Adds a delay of 4 CPU clock cycles to the input capture.
Ex:
configureTimerMode(TIMER1, TimerMode::Normal);
while (!hasInputCapture(TIMER1))
{
uint16_t ticks = getInputCapture(TIMER1);
}
The UNO has one input capture pin on pin 8, which is linked to TIMER1.
The Mega two input capture pins that you can directly access: pin 48 (TIMER5) and 49 (TIMER4). You can indirectly use pin 5 (TIMER3) as an input capture pin, but you need to configure the Analog Comparator to do so. Also note that the pin 5 input capture edges will be inverted. The Mega does not expose the TIMER1 input capture pin.
Analog Comparator Example:
configureTimerMode(TIMER3, TimerMode::Normal);
ACSR |= _BV(ACBG) | _BV(ACIC);
while (!hasInputCapture(TIMER3))
{
uint16_t ticks = getInputCapture(TIMER3);
}
Sometimes you need to reset several timers to the same value so they move in time with each other. These functions allow you to stop all of the timers, configure them, and then start them all at the same time.
Timers generally feed off of a "prescaler" that takes the CPU clock and divides it by a certain amount. These functions work by continually resetting the prescaler that feeds the synchronous timers (most of them) and the prescaler that feeds the asynchronous timer (TIMER2). You can then configure the timers, then start them all at once.
resetSynchronousPrescaler()
resetAsynchronousPrescaler()
setTimerSynchronizationModeEnabled(bool enabled)
stopAllTimersAndSynchronize()
startAllTimers()
- Reset and synchronized timers
stopAllTimersAndSynchronize();
configureTimerMode(TIMER1, TimerMode::Normal);
configureTimerMode(TIMER3, TimerMode::Normal);
setTimerValue(TIMER1, 0);
setTimerValue(TIMER3, 0);
startAllTimers();
// TIMER1 and TIMER3 will now always have the same value
getTimerConfig()
restoreTimerConfig(config)
- save and restore the clock setting and mode of a timer. Useful when switching between PWM and Normal mode on the same timer/pin.
ExtTimer extends the range of Arduino's built-in timers. Use with the Normal timer mode. The built-in timers are accessed through the ExtTimer0 through ExtTimer2 instances for the Arduino Uno, and ExtTimer0 through ExtTimer5 for the Mega
Ex:
// Configure Extended Timer 1 to run at the speed of the clock, and then get the current ticks
ExtTimer1.configure();
ticksExtraRange_t ticks = ExtTimer1.get();
The interrupt interface is similar to the interface in Arduino, except that you attach an interrupt to a timer, and the function you provde needs to take a uint16_t argument that will hold the input capture value.
attachInputCaptureInterrupt(timer, func, edge)
detachInputCaptureInterrupt(uint8_t timer)
TimerAction lets you perform actions at specific times, including calling a callback and setting, clearing, or toggling pins.
Ex:
TimerAction1A.configure(TimerClock::ClkDiv8);
ticksExtraRange_t nowTicks = TimerAction1A.getNow();
ticksExtraRange_t alarmTicks = TimerAction1A.millisecondsToTicks(8000);
TimerAction1A.schedule(alarmTicks, alarm);
PulseGen generates precise, jitter-free pulses on PWM pins. Note that this only when a timer's clock is in Normal mode, and the pin is set for output.
Note that PulseGen does not automatically set the pin mode.
Ex:
ExtTimerPin11.configure(TimerClock::ClkDiv1024);
pinMode(11, OUTPUT);
ticksExtraRange_t nowTicks = ExtTimerPin11.get();
PulseGenPin11.setStart(nowTicks + 50000);
PulseGenPin11.setEnd(nowTicks + 110000);