TimerInterrupt_Generic Library to merge all TimerInterrupt Libraries

TimerInterrupt_Generic Library

How To Install Using Arduino Library Manager

This library enables you to use Interrupt from Hardware Timers on supported Arduino boards such as AVR, ESP8266, ESP32, SAMD, SAM DUE, nRF52, Teensy, etc.

As Hardware Timers are rare, and very precious assets of any board, this library now enables you to use up to 16 different ISR-based timers, while actually consuming only 1 Hardware Timer. Timers’ interval is very long (ulong millisecs). The most important feature is they’re ISR-based timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks.

Why do we need this TimerInterrupt_Generic 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 asoftware 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 on-time or not at all, 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.1.0

  1. Initial Super-Library coding to merge all TimerInterrupt Libraries

Currently Supported Boards

  • ESP8266

  • ESP32

  • AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox etc..

  • Arduino SAMD21 (ZERO, MKR, NANO_33_IOT, etc.).

  • Adafruit SAM21 (Itsy-Bitsy M0, Metro M0, Feather M0, Gemma M0, etc.).

  • Adafruit SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.).

  • Seeeduino SAMD21/SAMD51 boards (SEEED_WIO_TERMINAL, SEEED_FEMTO_M0, SEEED_XIAO_M0, Wio_Lite_MG126, WIO_GPS_BOARD, SEEEDUINO_ZERO, SEEEDUINO_LORAWAN, SEEED_GROVE_UI_WIRELESS, etc.)

  • STM32 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32F1, STM32F3, STM32F4, STM32H7, STM32L0, etc.).

  • STM32F/L/H/G/WB/MP1 (Nucleo-64 L053R8,Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32Fx, STM32H7, STM32Lx, STM32Gx, STM32WB, STM32MP1, etc.) having 64K+ Flash program memory.

  • 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

  • Arduino AVR boards such as :

  • Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc.

  • Sanguino

  • ATmega8, 48, 88, 168, 328

  • ATmega8535, 16, 32, 164, 324, 644, 1284

  • ATmega64, 128

  • ATtiny 84 / 85

  • Arduino SAM DUE.

Examples:

A. ESP32

  1. Argument_None
  2. ISR_RPM_Measure
  3. ISR_Switch
  4. ISR_Timer_4_Switches
  5. ISR_Timer_Complex
  6. ISR_Timer_Switch
  7. ISR_Timer_Switches
  8. RPM_Measure
  9. SwitchDebounce
  10. TimerInterruptTest

B. ESP8266

  1. Argument_None
  2. ISR_RPM_Measure
  3. ISR_Switch
  4. ISR_Timer_4_Switches
  5. ISR_Timer_Complex
  6. ISR_Timer_Switch
  7. ISR_Timer_Switches
  8. RPM_Measure
  9. SwitchDebounce
  10. TimerInterruptTest

C. NRF52

  1. Argument_None
  2. ISR_16_Timers_Array
  3. ISR_RPM_Measure
  4. ISR_Timer_Complex_Ethernet
  5. ISR_Timer_Complex_WiFiNINA
  6. RPM_Measure
  7. SwitchDebounce
  8. TimerInterruptTest
  9. TimerInterruptLEDDemo

D. SAMD

  1. Argument_None
  2. ISR_16_Timers_Array
  3. ISR_RPM_Measure
  4. ISR_Timer_Complex_Ethernet
  5. ISR_Timer_Complex_WiFiNINA
  6. RPM_Measure
  7. SwitchDebounce
  8. TimerInterruptTest
  9. TimerInterruptLEDDemo

E. SAM DUE

  1. Argument_None
  2. ISR_16_Timers_Array
  3. ISR_RPM_Measure
  4. ISR_Timer_Complex_Ethernet
  5. RPM_Measure
  6. SwitchDebounce
  7. TimerInterruptTest
  8. TimerInterruptLEDDemo

E. TEENSY

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

F. AVR

  1. Argument_Complex
  2. Argument_None
  3. Argument_Simple
  4. ISR_RPM_Measure
  5. ISR_Switch
  6. ISR_Timer_Complex
  7. ISR_Timer_Switch
  8. ISR_Timer_Switches
  9. RPM_Measure
  10. SwitchDebounce
  11. TimerDuration
  12. TimerInterruptTest

Debug Termimal Output Samples

  1. The following is the sample terminal output when running example ISR_Timer_Complex_Ethernet on Arduino SAM-DUE using W5100 Ethernet 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.917s !!!. Then in loop(), it's also activated every 3s.

Starting ISR_Timer_Complex_Ethernet on SAM DUE
Version : 1.1.0
CPU Frequency = 84 MHz
Timer Frequency = 84 MHz
Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn
Timer(0), us = 50000.00
ITimer attached to Timer(0)
[5] Getting IP...
[7] MAC: FE-8A-F1-EA-DE-82
_pinCS = 0
W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10
W5100::init: W5100, SSIZE =4096
2s: Delta ms = 2000
2s: Delta ms = 2000
[7728] IP:192.168.2.134
[7728] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on Arduino Due

[7732] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080
[7849] Ready (ping: 6ms).
IP = 192.168.2.134
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 10917
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
11s: Delta ms = 11000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
11s: Delta ms = 11000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
  1. The following is the sample terminal output when running example ISR_Timer_Complex_Ethernet on Adafruit NRF52840_FEATHER EXPRESS using W5500 Ethernet 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 4.867s !!!. Then in loop(), it's also activated every 3s.

Starting ISR_Timer_Complex_Ethernet on NRF52840_FEATHER
Version : 1.1.0
NRF52TimerInterrupt: F_CPU (MHz) = 64, Timer = NRF_TIMER2
NRF52TimerInterrupt: _fre = 1000000.00, _count = 50000
Starting  ITimer OK, millis() = 1419
[1419] Getting IP...
[1419] MAC: FE-BE-97-DA-C3-EA
_pinCS = 0
W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10
W5100::init: W5500, SSIZE =4096
[3104] IP:192.168.2.129
[3104] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on ARDUINO_NRF52_ADAFRUIT

[3106] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080
[3218] Ready (ping: 8ms).
IP = 192.168.2.129
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 4867
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
11s: Delta ms = 11000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
11s: Delta ms = 11000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
21s: Delta ms = 21000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
11s: Delta ms = 11000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
2s: Delta ms = 2000
5s: Delta ms = 5000
11s: Delta ms = 11000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000
  1. The following is the sample terminal output when running example ISR_16_Timers_Array on Arduino SAMD21 SAMD_NANO_33_IOT to demonstrate the accuracy of ISR Hardware Timer, especially when system is very busy or blocked. The 16 independent ISR timers are programmed to be activated repetitively after certain intervals, is activated exactly after that programmed interval !!!

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

In this example, 16 independent ISR Timers are used, yet utilized just one Hardware Timer. The Timer Intervals and Function Pointers are stored in arrays to facilitate the code modification.

Starting ISR_16_Timers_Array on SAMD_NANO_33_IOT
Version : 1.1.0
CPU Frequency = 48 MHz
F_CPU (MHz) = 48, TIMER_HZ = 48
TC_Timer::startTimer _Timer = 0x42002c00, TC3 = 0x42002c00
Starting  ITimer OK, millis() = 1421
1s: Delta ms = 1000, ms = 2421
1s: Delta ms = 1000, ms = 3421
2s: Delta ms = 2000, ms = 3421
1s: Delta ms = 1000, ms = 4421
3s: Delta ms = 3000, ms = 4421
1s: Delta ms = 1000, ms = 5421
2s: Delta ms = 2000, ms = 5421
4s: Delta ms = 4000, ms = 5421
1s: Delta ms = 1000, ms = 6421
5s: Delta ms = 5000, ms = 6421
1s: Delta ms = 1000, ms = 7421
2s: Delta ms = 2000, ms = 7421
3s: Delta ms = 3000, ms = 7421
6s: Delta ms = 6000, ms = 7421
1s: Delta ms = 1000, ms = 8421
7s: Delta ms = 7000, ms = 8421
1s: Delta ms = 1000, ms = 9421
2s: Delta ms = 2000, ms = 9421
4s: Delta ms = 4000, ms = 9421
8s: Delta ms = 8000, ms = 9421
1s: Delta ms = 1000, ms = 10421
3s: Delta ms = 3000, ms = 10421
9s: Delta ms = 9000, ms = 10421
1s: Delta ms = 1000, ms = 11421
2s: Delta ms = 2000, ms = 11421
5s: Delta ms = 5000, ms = 11421
10s: Delta ms = 10000, ms = 11421
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
1s: Delta ms = 1000, ms = 12421
11s: Delta ms = 11000, ms = 12421
1s: Delta ms = 1000, ms = 13421
2s: Delta ms = 2000, ms = 13421
3s: Delta ms = 3000, ms = 13421
4s: Delta ms = 4000, ms = 13421
6s: Delta ms = 6000, ms = 13421
12s: Delta ms = 12000, ms = 13421
1s: Delta ms = 1000, ms = 14421
13s: Delta ms = 13000, ms = 14421
1s: Delta ms = 1000, ms = 15421
2s: Delta ms = 2000, ms = 15421
7s: Delta ms = 7000, ms = 15421
14s: Delta ms = 14000, ms = 15421
1s: Delta ms = 1000, ms = 16421
3s: Delta ms = 3000, ms = 16421
5s: Delta ms = 5000, ms = 16421
15s: Delta ms = 15000, ms = 16421
1s: Delta ms = 1000, ms = 17421
2s: Delta ms = 2000, ms = 17421
4s: Delta ms = 4000, ms = 17421
8s: Delta ms = 8000, ms = 17421
16s: Delta ms = 16000, ms = 17421
1s: Delta ms = 1000, ms = 18421
1s: Delta ms = 1000, ms = 19421
2s: Delta ms = 2000, ms = 19421
3s: Delta ms = 3000, ms = 19421
6s: Delta ms = 6000, ms = 19421
9s: Delta ms = 9000, ms = 19421
1s: Delta ms = 1000, ms = 20421
1s: Delta ms = 1000, ms = 21421
2s: Delta ms = 2000, ms = 21421
4s: Delta ms = 4000, ms = 21421
5s: Delta ms = 5000, ms = 21421
10s: Delta ms = 10000, ms = 21421
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
1s: Delta ms = 1000, ms = 22421
3s: Delta ms = 3000, ms = 22421
7s: Delta ms = 7000, ms = 22421
1s: Delta ms = 1000, ms = 23421
2s: Delta ms = 2000, ms = 23421
11s: Delta ms = 11000, ms = 23421
1s: Delta ms = 1000, ms = 24421
1s: Delta ms = 1000, ms = 25421
2s: Delta ms = 2000, ms = 25421
3s: Delta ms = 3000, ms = 25421
4s: Delta ms = 4000, ms = 25421
6s: Delta ms = 6000, ms = 25421
8s: Delta ms = 8000, ms = 25421
12s: Delta ms = 12000, ms = 25421
1s: Delta ms = 1000, ms = 26421
5s: Delta ms = 5000, ms = 26421
1s: Delta ms = 1000, ms = 27421
2s: Delta ms = 2000, ms = 27421
13s: Delta ms = 13000, ms = 27421
1s: Delta ms = 1000, ms = 28421
3s: Delta ms = 3000, ms = 28421
9s: Delta ms = 9000, ms = 28421
1s: Delta ms = 1000, ms = 29421
2s: Delta ms = 2000, ms = 29421
4s: Delta ms = 4000, ms = 29421
7s: Delta ms = 7000, ms = 29421
14s: Delta ms = 14000, ms = 29421
1s: Delta ms = 1000, ms = 30421
1s: Delta ms = 1000, ms = 31421
2s: Delta ms = 2000, ms = 31421
3s: Delta ms = 3000, ms = 31421
5s: Delta ms = 5000, ms = 31421
6s: Delta ms = 6000, ms = 31421
10s: Delta ms = 10000, ms = 31421
15s: Delta ms = 15000, ms = 31421
simpleTimerDoingSomething2s: Delta programmed ms = 2000, actual = 10000
1s: Delta ms = 1000, ms = 32421
1s: Delta ms = 1000, ms = 33421
2s: Delta ms = 2000, ms = 33421
4s: Delta ms = 4000, ms = 33421
8s: Delta ms = 8000, ms = 33421
16s: Delta ms = 16000, ms = 33421
1s: Delta ms = 1000, ms = 34421
3s: Delta ms = 3000, ms = 34421
11s: Delta ms = 11000, ms = 34421

Releases v1.3.0

  1. Add NRF52_MBED_TimerInterrupt Library to support NRF52840-based board using mbed-RTOS such as Nano-33-BLE.
  2. Add support for UNO, Nano, Mini, Arduino Ethernet, Fio, BT, LilyPad, Pro, Pro Mini, NG, UNO WiFi.

Releases v1.2.0

  1. Add STM32_TimerInterrupt Library

Releases v1.3.1

  1. Add many complex examples.
  2. Add board Version String.
  3. Fix SAMD bug.

Releases v1.5.0

  1. Add support to ATmega4809-based boards such as Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.

Major Releases v1.4.0

  1. Add support to Generic or Sparkfun AVR ATmega_32U4 such as AVR_MAKEYMAKEY, AVR_PROMICRO, etc.
  2. Add support to Generic or Sparkfun AVR ATmega_328(P) such as ARDUINO_REDBOT, ARDUINO_AVR_DIGITAL_SANDBOX, etc.
  3. Add support to Generic or Sparkfun AVR ATmega128RFA1 such as ATMEGA128RFA1_DEV_BOARD, etc.
  4. Add support to Adafruit AVR ATMEGA_32U4 such as AVR_FLORA8, AVR_FEATHER32U4, etc.
  5. Add support to Adafruit AVR ATMEGA_328(P) such as AVR_FEATHER328P, AVR_METRO, etc.
  6. Add support to AVR ATMEGA_16U4, ATMEGA_32U4 such as Leonardo, YUN, ESPLORA, etc.
  7. Add support to Sparkfun SAMD21 boards such as SparkFun_RedBoard_Turbo, SparkFun_Qwiic_Micro, etc.
  8. Add support to Sparkfun SAMD51 boards such as SparkFun_SAMD51_Thing_Plus, SparkFun_SAMD51_MicroMod, etc.
  9. Update examples