Teensy_TimerInterrupt Library

Teensy_TimerInterrupt Library

How To Install Using Arduino Library Manager

This library enables you to use Interrupt from Hardware Timers on an Teensy-based board, such as Teensy 4.x, 3.x, LC, Teensy++ 2.0 or Teensy 2.0. As Hardware Timers are rare, and very precious assets of any board, this library now enable you to use up to 16 ISR-based Timers, while consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs).

You'd certainly experienced that if using other Hardware Timer Libraries, such as TimerOne or TimerThree, the interval is short, in milliseconds range.

For example, Teensy 4.x, with super-high clock frequency of 600MHz and Timer1 and Timer3 clock of 150MHz, the maximum interval / frequency is only 55922.3467 us / 17.881939 Hz. This Teensy_TimerInterrupt Library will provide you up to 16 super-long (ulong millisecs) ISR Timers for each used Timer1 or Timer3.

For Teensy 4.x, this library will be expanded to use other available hardware timers, such as FTM, GPT, QUAD, PIT, in addition to current Timer1 and Timer3.

Why do we need this Teensy_TimerInterrupt Library

Imagine you have a system with a mission-critical function, measuring water level and control the sump pump or doing something much more important. You normally use a software timer to poll, or even place the function in loop(). But what if another function is blocking the loop() or setup().

So your function might not be executed, or delayed, and the result would be disastrous.

You'd prefer to have your function called, no matter what happening with other functions (busy loop, bug, etc.).

The correct choice is to use a Hardware Timer with Interrupt to call your function.

These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.

Functions using normal software timers, relying on loop() and calling millis(), won't work if the loop() or setup() is blocked by certain operation. For example, certain function is blocking while it's connecting to WiFi or some services.

The catch is your function is now part of an ISR (Interrupt Service Routine), must be lean and mean, and follow certain rules. More to read on:

HOWTO Attach Interrupt

Important Notes:

  1. Inside the ISR function, delay() won’t work and the value returned by millis() will not increment. Serial data received while in the ISR function may be lost. You should declare as volatile any variables that you modify within the attached function.

  2. Typically global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile.

Releases v1.0.0

  1. Permit up to 16 super-long-time, super-accurate ISR-based timers to avoid being blocked
  2. Using cpp code besides Impl.h code to use if Multiple-Definition linker error.

Supported Boards

  1. Teensy boards such as :
  • Teensy 4.1, 4.0
    ** - Teensy 3.6, 3.5, 3.2/3.1, 3.0**
    ** - Teensy LC**
    ** - Teensy++ 2.0 and Teensy 2.0**

Examples:

  1. Argument_None
  2. ISR_RPM_Measure
  3. ISR_Timer_Complex
  4. RPM_Measure
  5. SwitchDebounce
  6. TimerInterruptTest
  7. TimerInterruptLEDDemo

Debug Termimal Output Samples

  1. The following is the sample terminal output when running example ISR_Timer_Complex on Teensy 4.1 board to demonstrate the accuracy of ISR Hardware Timer, especially when system is very busy. The ISR timer is programmed for 2s, is activated exactly after 2.000s !!!

While software timer, programmed for 2s, is activated after 10.000s in loop() !!!.

Starting ISR_Timer_Complex on Teensy 4.0/4.1
Version : 1.0.0
CPU Frequency = 600 MHz
TEENSY_TIMER_1, F_BUS_ACTUAL (MHz) = 150, request interval = 1000, actual interval (us) = 999
Prescale = 2, _timerCount = 18750
Starting  ITimer OK, millis() = 852
2s: Delta ms = 2000
2s: Delta ms = 2000
2s: Delta ms = 2000
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
2s: Delta ms = 2000
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
11s: Delta ms = 11000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
2s: Delta ms = 2000
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
11s: Delta ms = 11000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
2s: Delta ms = 2000
  1. The following is the sample terminal output when running exampleTimerInterruptTest on Teensy 4.1 board to demonstrate the accuracy and how to start/stop Hardware Timers.
Starting TimerInterruptTest on Teensy 4.0/4.1
Version : 1.0.0
CPU Frequency = 600 MHz
TEENSY_TIMER_1, F_BUS_ACTUAL (MHz) = 150, request interval = 50000, actual interval (us) = 49998
Prescale = 7, _timerCount = 29296
Starting  ITimer0 OK, millis() = 1375
ITimer0: millis() = 1375
ITimer0: millis() = 1425
ITimer0: millis() = 1475
...
ITimer0: millis() = 4875
ITimer0: millis() = 4925
ITimer0: millis() = 4975
Stop ITimer0, millis() = 5001
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
Start ITimer0, millis() = 10002
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
TeensyTimerInterrupt:resumeTimer TEENSY_TIMER_1
ITimer0: millis() = 10002
ITimer0: millis() = 10002
ITimer0: millis() = 10052
...
ITimer0: millis() = 14901
ITimer0: millis() = 14951
ITimer0: millis() = 15001
Stop ITimer0, millis() = 15003
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
Start ITimer0, millis() = 20004
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
TeensyTimerInterrupt:resumeTimer TEENSY_TIMER_1
ITimer0: millis() = 20004
ITimer0: millis() = 20004
ITimer0: millis() = 20054
...
ITimer0: millis() = 24903
ITimer0: millis() = 24953
ITimer0: millis() = 25003
Stop ITimer0, millis() = 25005
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
Start ITimer0, millis() = 30006
TeensyTimerInterrupt:stopTimer TEENSY_TIMER_1
TeensyTimerInterrupt:resumeTimer TEENSY_TIMER_1
ITimer0: millis() = 30006