PITimer: PIT (Periodic Interrupt Timer) library for Teensy 3.0

Status
Not open for further replies.
Allright, thanks for the clarification.

In that case maybe it's wise to change the library link in the opening post to point to IntervalTimer instead of PITimer.
 
Non-periodic timing with FTM1

The plan is to include IntervalTimer into the built-in core library.

If you use IntervalTimer, your code will probably work with future versions of Teensyduino without needing to install the library separately.

PITimer will stop working when IntervalTimer is built in, so you probably should use IntervalTimer rather than PITimer for any new projects.

If one needed non-periodic interrupts, like for coordinated-axis stepper motor control as in https://github.com/triffid/Teacup_Firmware/blob/Gen7/timer.c#L85, would trying to use FTM1 (and sacrificing PWM on pins 2&3) be reasonable?
 
If one needed non-periodic interrupts, like for coordinated-axis stepper motor control as in https://github.com/triffid/Teacup_Firmware/blob/Gen7/timer.c#L85, would trying to use FTM1 (and sacrificing PWM on pins 2&3) be reasonable?

Yes, using one of the FTM timers would be best.

If you do it carefully, by reading the MOD register to know what the maximum count is, you could probably design code that would use only 1 channel. If you avoid writing to the MOD register and other settings, it's a bit more work, but you could avoid interfering with the PWM running on the other channels.
 
This looks very interesting and something I need for an upcoming project. Sorry, lots of questions:

1) What is the status of IntervalTimer?
2) Is the plan still to incorporate this directly in the core?
3) What about tone() updates to release timer3? Once these changes are done, will tone() not lock-up a timer unless it's used?
4) Still assuming only 3 timers can currently be used with either PITimer or IntervalTimer, correct?
5) Are updates planned for the next release? If not, any idea when?
6) Is there a beta available?
7) Is it best to use PITimer or IntervalTimer for now?

Thanks.
 
Use IntervalTimer. If you want more details, please read all the posts for this thread. There are 2 pages of posts.
 
1) What is the status of IntervalTimer?
2) Is the plan still to incorporate this directly in the core?

I'm planning to include it in Teensyduino 1.14 or 1.15.

The timing depends somewhat on when Arduino 1.05 is released. Seven days ago, they upped the version to 1.0.5 on github, so 1.0.5 might release soon. If it does, I'll publish 1.14 quickly without IntervalTimer, and add it later in 1.15. If they delay several more days, I'll delay 1.14 and probably get a few more things in. IntervalTimer is on my short list.....

When I include IntervalTimer, of course I'll change tone() to use it.

Linuxgeek is correct, you should use IntervalTimer. Some of your questions are probably answered in the messages on this thread.
 
Great work, but the reset function did not work for me.
This modification did fix the problem:

void PITimer::reset() {
*PIT_TCTRL = 0;
// writeValue();
*PIT_TCTRL = 3;
}
 
I've been working on integrating IntervalTimer into the core library. One change I made was adding back the ability to use floating point to specify the interval. It's currently implement as inline functions, so the float math is done at compile time if the input is a constant.

Soooo... here's the main thing I'd like to discuss. I'm contemplating whether the interval ought to be expressed in microseconds or milliseconds?

Changing to milliseconds will of course break compatibility with all programs using the library today. If there were ever a time to make this change, it would be going from a separate library to built in. Once 1.14 is released, I really do not want to consider this type of change.... but I'm thinking about it now and asking here.

The advantage of milliseconds is many people will tend to use integers, and any integer number of milliseconds has the opportunity to someday be implemented by the systick interrupt, which frees the PIT timers for more demanding uses. A secondary advantage is a human perception, that using something like mytimer.begin(funct, 0.02) just "feels" like requesting something really small, compared to mytimer.begin(funct, 20).

If anyone is still following this thread and using IntervalTimer, please let me know your thoughts? I'm seriously considering this change, but I am also sensitive to how much code it might break. After 1.14 is released, the API will be frozen.
 
I'd prefer the precision of being able to use microseconds.
I like the idea of looking to the future where faster clock speeds, ever smaller timing intervals and increased resolution are the norm.
I'm currently using IntervalTimer but it's in an active project, so It'll be easy for me to make the modifications when the 1.14 update is released.

Oh and many THANKS to Dan (Loglow) for his excellent efforts on PITtimer and IntervalTimer.
 
Last edited:
I've been working on integrating IntervalTimer into the core library. One change I made was adding back the ability to use floating point to specify the interval. It's currently implement as inline functions, so the float math is done at compile time if the input is a constant.

Is the idea that internally it will use integer microseconds, but that the user can specify time in that format OR using a floating point interface which converts to microseconds (via an inline function which the compiler can optimize)? Or would floating point times be required in order to use the library?
 
Microseconds please!
I am looking at what it will take for Arduino (especially the Teensy) to be able to do PTP IEEE1588 and API's
with more resolution will be required.
 
I would prefer microseconds as integers. I would think that there's quite a few people like me who will use the interrupt over long periods of time, and are concerned with drift. Using a float that's converted to a microsecond would seem to add to an unexpected drift.

Couldn't systick still be used for microseconds that are based evenly on 1000's? I'm wondering how systick would work. Is it almost like a free interrupt?

I'm personally not concerned with breaking compatibility.
 
Professional Time Engineers (yes, this is a real sub-discipline) don't like floating point representations of time because the resolution goes down as the time values go up. They usually use multi-word integers, e.g. PTP time stamp. I am hoping the Teensy 3.0++ uses a K60 w/ethernet core because they have an IEEE1588 timer which you can use
even if you don't use the ethernet MAC on the chip.
 
Internally, IntervalTimer works in resolution of bus clock cycles, not microseconds. The bus clock is 48 MHz.

In another thread, the point was raised that even integer microseconds don't offer enough resolution to get specific interrupt rates, like exactly 7 kHz, or as close as the hardware can generate, which is 7.000149 kHz. That got me thinking about the IntervalTimer API. I generally like keeping things as simple as possible, but adding the option to express the number as a float or integer provides access to the full native clock-cycle resolution without increasing the number of functions or parameters. I think it's worth doing.

Regardless of the API using microseconds or milliseconds, you still get full access the cycle-level resolution. For 7 kHz, with milliseconds you'd write myTimer.begin(funct, 0.142857). With microseconds, you'd write myTimer.begin(funct, 142.857). It's the same result either way.

So far, there's 4 votes for microseconds, and slightly over half a vote (me) for milliseconds.

I just to make sure everyone who's so strongly in favor of microseconds understands it does NOT give you any extra precision. You still get 20.83 ns timing resolution (yes, nanoseconds). There is the issue of floating point precision, but for constant inputs the calculation is done at compile time using double precision, which is far better precision than this hardware actually offers. Even with single precision float, the rounding errors only start to become a factor (a 20.8 ns factor) at intervals of approx 0.25 seconds or longer.

My main reason for favoring milliseconds is the likelihood of many people just using integer constants for relatively undemanding applications. Someday I want to extend IntervalTimer to also use systick. Today, you get only 3 timers. With Teensyduino 1.14, you'll get 4 timers (but calling tone will consume a timer for as long as the tone plays). A future version may allow 8 or 12 timers, where 4 can be higher precision and the rest only millisecond resolution.
 
I have a project which is using IntervalTimer extensively. Regarding micro vs milli seconds my vote would be for microseconds if we have to choose a single unit of measure. A suggestion would be to choose one of the units as a default, and provide an optional way to specify another unit if desired. Example: myTimer.begin(funct, 142.0, MICRO) selects the unit of microseconds and myTimer.begin(funct, 0.142) selects the default unit of milliseconds.

In my case, if milliseconds is selected, it will mean that I have to do a converting calculation 1000 times a second for each of the 4 timers I'd like to use. If I can use microseconds directly, I can avoid all of this.
 
I'd say implement both interfaces:

timer.begin(cb0, 1); // milliseconds
timer.beginMicroseconds(cb0, 1000); // microseconds

This matches the convention on delay() and extends obviously to Nanoseconds in the future.

Allowing both integer and floating point intervals should be matched with the same change to delay() and delayMicroseconds().
 
How do you propose to deal with the problem of rounding?

I mean if it is rounded, how do you know it is rounded? It might not be a big deal that the resolution is imprecise to the interval that was asked, but I think we'd want to know exactly what the interval is that will be used. To avoid compounded time drift from what one would expect. So do you return a value? If so, I think it's better to return the # of clock cycles used as the interval. It makes me uneasy working with floats for something that is clearly integer math, like dollars and cents.
 
It's getting rounded even when you give it an integer number of milliseconds or microseconds. What you get is integer numbers of whatever clocks the processor has to count, with whatever jitter or drift there might be to that number. If the interval you want is a whole number of clock ticks, but not a whole number of microseconds, you should be able to specify the correct fraction of a microsecond.

-- rec --
 
It's getting rounded even when you give it an integer number of milliseconds or microseconds.
-- rec --

I realize that's a possibility (after Paul described it), which is why I was wondering if it might be better to have the actual # of clock cycles as the return value. If you don't care, you wouldn't do anything with it.
And it's only done during setup so it's not like there's any overhead to worry about. But if you did care, you could store that and use that for other calculations, when accuracy counted. And if I had to calculate the fraction so that it matched a clock cycle, I'd feel more comfortable just passing the actual clock cycle.
 
Hello, sorry for the thread hijack, if im wrong let me know and ill make a new post

Im having some trouble using this library (first time im including an extern library)
What ive done is to download the PITimer.h and .ccp to a folder named PITimer in the libraries section of Arduino.
Then created a new sketch, pasted the example (https://github.com/loglow/PITimer) and verify the code.

The problem is that i get all kind of errors:

Arduino: 1.0.5 (Windows XP), Board: "Teensy 3.0"
C:\Archivos de programa\Arduino\hardware\tools\arm-none-eabi\bin\arm-none-eabi-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mcpu=cortex-m4 -DF_CPU=48000000 -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=105 -mthumb -nostdlib -D__MK20DX128__ -fno-rtti -felide-constructors -std=gnu++0x -DUSB_SERIAL -DLAYOUT_US_ENGLISH -IC:\Archivos de programa\Arduino\hardware\teensy\cores\teensy3 -IC:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer C:\DOCUME~1\Fran\CONFIG~1\Temp\build139943992695985522.tmp\sketch_oct03a.cpp -o C:\DOCUME~1\Fran\CONFIG~1\Temp\build139943992695985522.tmp\sketch_oct03a.cpp.o

In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:7:19: warning: character constant too long for its type [enabled by default]
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:9:9: error: stray '\302' in program
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:9:9: error: stray '\267' in program
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:9:9: error: stray '\302' in program
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:9:9: error: stray '\267' in program
In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:50:39: warning: character constant too long for its type [enabled by default]
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:50:56: warning: character constant too long for its type [enabled by default]
In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:215:25: warning: character constant too long for its type [enabled by default]
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:221:25: warning: character constant too long for its type [enabled by default]
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:392:17: warning: character constant too long for its type [enabled by default]
In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:523:60: warning: multi-character character constant [-Wmultichar]
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:523:70: warning: multi-character character constant [-Wmultichar]
In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:4:1: error: expected unqualified-id before '<' token
In file included from sketch_oct03a.ino:1:0:
C:\Documents and Settings\Fran\Mis documentos\Arduino\libraries\PITimer/PITimer.h:567:18: error: expected unqualified-id before numeric constant
sketch_oct03a.ino: In function 'void timerCallback0()':
sketch_oct03a:6: error: 'PITimer0' was not declared in this scope
sketch_oct03a:9: error: 'PITimer1' was not declared in this scope
sketch_oct03a:12: error: 'PITimer2' was not declared in this scope
sketch_oct03a.ino: In function 'void timerCallback1()':
sketch_oct03a:17: error: 'PITimer2' was not declared in this scope
sketch_oct03a.ino: In function 'void setup()':
sketch_oct03a:26: error: 'PITimer1' was not declared in this scope
sketch_oct03a:27: error: 'PITimer2' was not declared in this scope
sketch_oct03a:30: error: 'PITimer0' was not declared in this scope

I dont like large errors messages in forum post, but i want to give as much information as i can.
Can anyone spot my mystake?
 
The PITimer library was replaced by IntervalTimer, which is now part of the built-in core library. You can no longer use PITimer, because it conflicts with IntervalTimer.
 
Hi Paul -
You might want to add notes/examples about IntervalTimer to your page on Delay and Timing. I was looking to embark on adding timer interrupts and happened to run into this - was going down a much longer path before a fortuitous google search took me to this thread.

And thanks so much for pulling this into Teensy - as an old embedded guy I was going nuts without timer interrupts but wasn't quite ready to dig deep into the chip.
 
Hi all,
I try to trigger an ISR with high frequency (< 1 microsecond). Currently, the IntervalTimer library limits the timer period to minimum 40 F_BUS cycles, so the minimum period with F_BUS=48MHz is limited to 0.822916667 µs.
Is this a hardware limit of the cpu/timer?
I checked and my ISR needs far less than 1µs for execution (around 300ns). Is there a significant overhead for calling the ISR?

If so, is there another way to periodically fire a small function (with kind of timing control) on a Teensy 3.1, allowing periods <1µs?
Thanks.
 
Hi all,
I try to trigger an ISR with high frequency (< 1 microsecond). Currently, the IntervalTimer library limits the timer period to minimum 40 F_BUS cycles, so the minimum period with F_BUS=48MHz is limited to 0.822916667 µs.
Is this a hardware limit of the cpu/timer?
I checked and my ISR needs far less than 1µs for execution (around 300ns). Is there a significant overhead for calling the ISR?

If so, is there another way to periodically fire a small function (with kind of timing control) on a Teensy 3.1, allowing periods <1µs?
Thanks.
Recurring interrupt with interval < 1 microsecond is too frequent to be viable or useful. Anything on the order of 100 microseconds or less, recurring, would cost too much CPU time, and have too much latency.
 
Status
Not open for further replies.
Back
Top