skip navigational linksPJRC
Shopping Cart Checkout Shipping Cost Download Website
Home MP3 Player 8051 Tools All Projects PJRC Store Site Map
You are here: Teensy Teensyduino Timing IntervalTimer

PJRC Store
Teensy 3.6, $29.25
Teensy 3.5, $24.25
Teensy 3.2, $19.80
Teensy LC, $11.65
Teensy 2.0, $16.00
Teensy++ 2.0, $24.00
Teensy
Main Page
Hardware
Getting Started
How-To Tips
Code Library
Projects
Teensyduino
Reference

IntervalTimer

IntervalTimer uses interrupts to call a function at a precise timing interval.

Advanced programming is required to properly use IntervalTimer, because your function runs as an interrupt. See below for details.

IntervalTimer is generally recommended for use only in libraries and advanced applications which require highly precise timing. Usually the Metro library or an elapsedMillis variables are easier to use, because they avoid the pitfalls of interrupt programming.

Compatibility

IntervalTimer is supported only on 32 bit boards: Teensy LC, 3.0, 3.1, 3.2, 3.5 & 3.6.

Up to 4 IntervalTimer objects may be active simultaneuously on Teensy 3.0 - 3.6. Teensy LC has only 2 timers for IntervalTimer.

The tone function and several libraries use an IntervalTimer. Libraries known to use an IntervalTimer include DmxSimple, Adafruit_VS1053, NewPing, FreqCount, RadioHead (only some uses), ShiftPWM, SoftPWM, Talkie, VirtualWire, MsTimer2 & FlexiTimer2.

For Teensy 2.0 and Teensy++ 2.0, the TimerOne & TimerThree and FlexiTimer2 libraries provide similar capability.

IntervalTimer Usage

IntervalTimer myTimer;

Create an IntervalTimer object. You may create as many IntervalTimers as needed, but only a limited number may be active simultaneously. Normally IntervalTimer objects should be created as global variables.

myTimer.begin(function, microseconds);

Begin calling the function. The interval is specified in microseconds, which may be an integer or floating point number, for more highly precise timing. This functions returns true if sucessful. False is returned if all hardware resources are busy, used by other IntervalTimer objects.

myTimer.priority(number);

Set the interrupt priority level, controlling which other interrupts this timer is allowed to interrupt. Lower numbers are higher priority, with 0 the highest and 255 the lowest. Most other interrupts default to 128. As a general guideline, interrupt routines that run longer should be given lower priority (higher numerical values).

myTimer.end();

Stop calling the function. The hardware resource becomes available for use by other IntervalTimer objects.

Example Program

// Create an IntervalTimer object 
IntervalTimer myTimer;

const int ledPin = LED_BUILTIN;  // the pin with a LED

void setup(void) {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  myTimer.begin(blinkLED, 150000);  // blinkLED to run every 0.15 seconds
}

// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
int ledState = LOW;
volatile unsigned long blinkCount = 0; // use volatile for shared variables

// functions called by IntervalTimer should be short, run as quickly as
// possible, and should avoid calling other functions if possible.
void blinkLED(void) {
  if (ledState == LOW) {
    ledState = HIGH;
    blinkCount = blinkCount + 1;  // increase when LED turns on
  } else {
    ledState = LOW;
  }
  digitalWrite(ledPin, ledState);
}

// The main program will print the blink count
// to the Arduino Serial Monitor
void loop(void) {
  unsigned long blinkCopy;  // holds a copy of the blinkCount

  // to read a variable which the interrupt code writes, we
  // must temporarily disable interrupts, to be sure it will
  // not change while we are reading.  To minimize the time
  // with interrupts off, just quickly make a copy, and then
  // use the copy while allowing the interrupt to keep working.
  noInterrupts();
  blinkCopy = blinkCount;
  interrupts();

  Serial.print("blinkCount = ");
  Serial.println(blinkCopy);
  delay(100);
}

Interrupt Context Issues

IntervalTimer will call you function from interrupt context. Because it can interrupt your program at any moment, special design is necessary to share data with the rest of your program.

Many ordinary functions are not designed to work properly from interrupt context. String objects should be avoided. A general guideline is to keep your function short and avoid calling other functions if possible.

Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume variable can not spontaneously change. Because your function may change variables while your program is using them, the compiler needs this hint. But volatile alone is often not enough.

When accessing shared variables, usually interrupts must be disabled. Even with volatile, if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled for the entire sequence of your code which accesses the data.

Other Libraries

More delays can be implemented on the FTM timers with this library.