Go Down

Topic: Looking for WGM Mode to Clear T1 on Input Capture (Read 4306 times) previous topic - next topic

HACF

I'm working with the Timer 1 input capture feature on anarduino nano and I've written a program which uses input captures and interrupts to timestamp rising edges on the input capture pin and displays the results.

What I have works, but I'm wondering if I can do better.

I'm currently using WGM "normal" mode 0 (same mode used by NGammon in his fantastic examples of T1 capture features)., but the question is...  Is there a waveform generation mode (WGM13:10) that would allow the program to work with less manual intervention on T1? Is there a different WGM mode that will CTC the timer T1 when there is a capture event?

Looking through the datasheet, "Mode 12" looked promising, but didn't work. Mode 12 is CTC mode with ICR1 as TOP. Sounds great. T1 counts up. Gets a capture event and copies T1 into ICR1 and then automatically clears T1 (because T1 = TOP = ICR1), right? But unfortunately it doesn't work that way.

Datasheet says "When the ICR1 is used as TOP value, the ICP1 is disconnected and consequently the Input Capture function is disabled."

And I have verified that is truly the case. If you're in a mode where ICR1 is used as TOP, the input capture pin has no effect. ICR1 is static at whatever value I put in it regardless of what happens on the ICR1 pin.

So I think I already know the answer, but I'm wondering if I'm just missing the obvious.

Is there a mode that will copy T1 into ICR1 and then automatically clear T1 at the same time?

jremington

No. CTC mode is for waveform generation.

What is wrong with performing the required "manual intervention"?

HACF

Thank you for the help. There's nothing "wrong" with it. I'm just finding that there is about 38ish cycles of latency by the time I get into the ISR. I'm subtracting the captured value from the current timer which leaves the latency value in there for the next measurement. Nothing wrong with that, but just looking for more efficient and cleaner.

If T1 cleared automatically on a capture event, I wouldn't have to adjust the value myself. In fact, I wouldn't need an ISR at all. I could just poll ICR1 and it would always have a fresh accurate timestamp (assuming no rollover).

It just seemed like it would be a useful application and I'm surprised the machine doesn't do that. I'm just wondering if I was missing something simple.

jremington

#3
Mar 23, 2020, 05:53 pm Last Edit: Mar 23, 2020, 06:20 pm by jremington
I see no reason to clear the timer, and that introduces unwanted latency.

If you do 16 bit overflow counting with an ISR (as Gammon demonstrates), treat the combined, 32 bit timestamp just as you would the millis() or micros() value, and do unsigned long subtraction to compute time differences.

The only latency in this approach is the time required to read out the values.

HACF


"I see no reason to clear the timer, and that introduces unwanted latency."

I'm not clearing the timer, and you're right... That would introduce error. Instead I'm subtracting the capture timestamp from the current timer value. Doing it that way, the ISR servicing latency comes out in the wash and my capture stamps are accurate to the machine cycle.

It just would have been convenient if the machine had a mode built in that already took care of it for me.

What I have works great until I overflow T1 at lower input frequencies. But in theory I'm not going down below about 250Hz, so an overflow condition for should be an error condition for me. I shouldn't need to do the counting of the overflows and shift-adding into 32 bits.

Thanks again for the help. Much appreciated.

jremington

#5
Mar 25, 2020, 05:18 am Last Edit: Mar 25, 2020, 05:21 am by jremington
The overflow feature of Gammon's input capture code works perfectly.

I have used it to accurately measure the frequency of the Arduino clock crystal, by capturing the 1PPS signal from a GPS, and running Timer1 with prescaler=1, so it counts at 16 MHz.

Think of it as a 62.5 nanosecond per tick version of millis(), except unlike millis() there are no missing counts.

Go Up