SAMDUE_TimerInterrupt Library

SAMDUE_TimerInterrupt Library

SAMDUE_TimerInterrupt Library

How To Install Using Arduino Library Manager

This library enables you to use Interrupt from Hardware Timers on an SAM-DUE-based board.

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 SAMDUE_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 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.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 SAM DUE.

Examples:

  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

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.0.1
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_16_Timers_Array on Arduino SAM DUE to demonstrate the accuracy and how to use 16 ISR Timers from just 1 Hardware Timer.
Starting ISR_16_Timers_Array on SAM DUE
Version : 1.0.1
CPU Frequency = 84 MHz
Timer Frequency = 84 MHz
Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn
Timer(0), us = 100.00
ITimer attached to Timer(0)
1s: Delta ms = 1006, ms = 1006
1s: Delta ms = 1000, ms = 2006
1s: Delta ms = 1000, ms = 3006
1s: Delta ms = 1000, ms = 4006
1s: Delta ms = 1000, ms = 5006
1s: Delta ms = 1000, ms = 6006
1s: Delta ms = 1000, ms = 7006
1s: Delta ms = 1000, ms = 8006
1s: Delta ms = 1000, ms = 9006
1s: Delta ms = 1000, ms = 10006
1s: Delta ms = 1000, ms = 11006
simpleTimer2s: Dms=2000, actual=11118
1s: Delta ms = 1000, ms = 12006
1s: Delta ms = 1000, ms = 13006
1s: Delta ms = 1000, ms = 14006
1s: Delta ms = 1000, ms = 15006
1s: Delta ms = 1000, ms = 16006
1s: Delta ms = 1000, ms = 17006
1s: Delta ms = 1000, ms = 18006
1s: Delta ms = 1000, ms = 19006
1s: Delta ms = 1000, ms = 20006
1s: Delta ms = 1000, ms = 21006
1s: Delta ms = 1000, ms = 22006
simpleTimer2s: Dms=2000, actual=11111
1s: Delta ms = 1000, ms = 23006
1s: Delta ms = 1000, ms = 24006
1s: Delta ms = 1000, ms = 25006
1s: Delta ms = 1000, ms = 26006
1s: Delta ms = 1000, ms = 27006
1s: Delta ms = 1000, ms = 28006
1s: Delta ms = 1000, ms = 29006
1s: Delta ms = 1000, ms = 30006
1s: Delta ms = 1000, ms = 31006
1s: Delta ms = 1000, ms = 32006
1s: Delta ms = 1000, ms = 33006
simpleTimer2s: Dms=2000, actual=11111
  1. The following is the sample terminal output when running example TimerInterruptTest on Arduino SAM DUE to demonstrate the accuracy and how to start/stop Hardware Timers.
Starting TimerInterruptTest on SAM DUE
Version : 1.0.1
CPU Frequency = 84 MHz
Timer Frequency = 84 MHz
Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn
ITimer0 attached to Timer(0)
Using Timer(1) = TC0, channel = 1, IRQ = TC1_IRQn
ITimer1 attached to Timer(1)
ITimer0: millis() = 1104, delta = 1104
ITimer0: millis() = 2104, delta = 1000
ITimer0: millis() = 3104, delta = 1000
ITimer1: millis() = 3111, delta = 3111
ITimer0: millis() = 4104, delta = 1000
Stop ITimer0, millis() = 5001
ITimer1: millis() = 6111, delta = 3000
ITimer1: millis() = 9111, delta = 3000
Start ITimer0, millis() = 10002
ITimer0: millis() = 11002, delta = 1000
ITimer0: millis() = 12002, delta = 1000
ITimer1: millis() = 12111, delta = 3000
ITimer0: millis() = 13002, delta = 1000
ITimer0: millis() = 14002, delta = 1000
Stop ITimer1, millis() = 15001
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 ITimer1, millis() = 30002
Start ITimer0, millis() = 30006
ITimer0: millis() = 31006, delta = 1000
ITimer0: millis() = 32006, delta = 1000
ITimer1: millis() = 33002, delta = 3000
ITimer0: millis() = 33006, delta = 1000
ITimer0: millis() = 34006, delta = 1000
ITimer0: millis() = 35006, delta = 1000
Stop ITimer0, millis() = 35007

Can you merge your timer libraries into a single library that works on any processor (hopefully with a bunch of common code)?

That's a very good idea, thanks.
I'll merge all these following TimerInterrupt Lbraries into a super TimerInterrupt_Generic Library within several days

  1. TimerInterrupt Library
  2. ESP8266TimerInterrupt Library
  3. ESP32TimerInterrupt Library
  4. STM32_TimerInterrupt Library
  5. SAMD_TimerInterrupt Library
  6. NRF52_TimerInterrupt Library
  7. SAMDUE_TimerInterrupt Library

TimerInterrupt_Generic Library
How To Install Using Arduino Library Manager

Done. Thanks and Regards @westfw.

That was quick!