SAMD_TimerInterrupt Library

SAMD_TimerInterrupt Library

How To Install Using Arduino Library Manager

This library enables you to use Interrupt from Hardware Timers on an SAMD-based board. It 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 SAMD_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 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, 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

  • 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.)

Examples:

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

Debug Termimal Output Samples

  1. The following is the sample terminal output when running example ISR_Timer_Complex_WiFiNINA on SAMD_NANO_33_IOT using Built-in WiFiNINA 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 7.937s !!!. Then in loop(), it’s also activated every 3s.

Starting ISR_Timer_Complex_WiFiNINA on SAMD_NANO_33_IOT
Version : 1.0.0
F_CPU (MHz) = 48, TIMER_HZ = 48
TC_Timer::startTimer _Timer = 0x42002c00, TC3 = 0x42002c00
Starting  ITimer OK, millis() = 810
Start Blynk
[1571] WiFiNINA Firmware Version: 1.4.1
[1572] Con2:HueNet1
2s: Delta ms = 2000
[5439] ConW OK
[5439] IP:192.168.2.98
[5439] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on NANO_33_IOT

[5440] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080
[5673] Ready (ping: 6ms).
IP = 192.168.2.98
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 7937
2s: Delta ms = 2000
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3004
2s: Delta ms = 2000
5s: Delta ms = 5000
2s: Delta ms = 2000
11s: Delta ms = 11000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3003
2s: Delta ms = 2000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
2s: Delta ms = 2000
5s: Delta ms = 5000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3004
2s: Delta ms = 2000
11s: Delta ms = 11000
2s: Delta ms = 2000
blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3002
5s: Delta ms = 5000
2s: Delta ms = 2000
  1. The following is the sample terminal output when running exampleTimerInterruptTest on Adafruit SAMD51 ITSYBITSY_M4 to demonstrate the accuracy and how to start/stop Hardware Timers.
Starting TimerInterruptTest on ITSYBITSY_M4
Version : 1.0.0
F_CPU (MHz) = 120, TIMER_HZ = 48
TC_Timer::startTimer _Timer = 0x4101c000, TC3 = 0x4101c000
Starting  ITimer1 OK, millis() = 1820
ITimer0: millis() = 2820, delta = 1000
ITimer0: millis() = 3820, delta = 1000
ITimer0: millis() = 4820, delta = 1000
Stop ITimer0, millis() = 5001
Start ITimer0, millis() = 10002
ITimer0: millis() = 11002, delta = 1000
ITimer0: millis() = 12002, delta = 1000
ITimer0: millis() = 13002, delta = 1000
ITimer0: millis() = 14002, delta = 1000
ITimer0: millis() = 15002, delta = 1000
Stop ITimer0, millis() = 15003
Start ITimer0, millis() = 20004
ITimer0: millis() = 21004, delta = 1000
ITimer0: millis() = 22004, delta = 1000
ITimer0: millis() = 23004, delta = 1000
ITimer0: millis() = 24004, delta = 1000
ITimer0: millis() = 25004, delta = 1000
Stop ITimer0, millis() = 25005
Start ITimer0, millis() = 30006
ITimer0: millis() = 31006, delta = 1000
ITimer0: millis() = 32006, delta = 1000
ITimer0: millis() = 33006, delta = 1000
ITimer0: millis() = 34006, delta = 1000
ITimer0: millis() = 35006, delta = 1000
Stop ITimer0, millis() = 35007
Start ITimer0, millis() = 40008
ITimer0: millis() = 41008, delta = 1000
ITimer0: millis() = 42008, delta = 1000
ITimer0: millis() = 43008, delta = 1000
ITimer0: millis() = 44008, delta = 1000
ITimer0: millis() = 45008, delta = 1000
Stop ITimer0, millis() = 45009
Start ITimer0, millis() = 50010
ITimer0: millis() = 51010, delta = 1000
ITimer0: millis() = 52010, delta = 1000
ITimer0: millis() = 53010, delta = 1000
ITimer0: millis() = 54010, delta = 1000
ITimer0: millis() = 55010, delta = 1000
Stop ITimer0, millis() = 55011
Start ITimer0, millis() = 60012
ITimer0: millis() = 61012, delta = 1000
ITimer0: millis() = 62012, delta = 1000
ITimer0: millis() = 63012, delta = 1000
ITimer0: millis() = 64012, delta = 1000
ITimer0: millis() = 65012, delta = 1000
Stop ITimer0, millis() = 65013
Start ITimer0, millis() = 70014
ITimer0: millis() = 71014, delta = 1000
ITimer0: millis() = 72014, delta = 1000
ITimer0: millis() = 73014, delta = 1000
ITimer0: millis() = 74014, delta = 1000
ITimer0: millis() = 75014, delta = 1000
Stop ITimer0, millis() = 75015
Start ITimer0, millis() = 80016
ITimer0: millis() = 81016, delta = 1000
ITimer0: millis() = 82016, delta = 1000
ITimer0: millis() = 83016, delta = 1000
ITimer0: millis() = 84016, delta = 1000
ITimer0: millis() = 85016, delta = 1000
Stop ITimer0, millis() = 85017
Start ITimer0, millis() = 90018
ITimer0: millis() = 91018, delta = 1000

This is fabulous! Thank you for sharing it with us!

Releases v1.3.0

  1. Add support to Sparkfun SAMD21 boards such as SparkFun_RedBoard_Turbo, SparkFun_Qwiic_Micro, etc.
  2. Add support to Sparkfun SAMD51 boards such as SparkFun_SAMD51_Thing_Plus, SparkFun_SAMD51_MicroMod, etc.
  3. Update examples to support Sparkfun boards.

Releases v1.2.0

  1. Add better debug feature.
  2. Optimize code and examples to reduce RAM usage
  3. Add Table of Contents