Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

RE: [AVR-Chat] How to measure a pulse width

2006-03-09 by wbounce

Thanks for the explanation. I think I can put the missing pieces together and code it tommorrow.
-----Original Message-----
From: AVR-Chat@yahoogroups.com [mailto:AVR-Chat@yahoogroups.com] On Behalf Of Ned Konz
Sent: Wednesday, March 08, 2006 1:14 AM
To: AVR-Chat@yahoogroups.com
Subject: Re: [AVR-Chat] How to measure a pulse width


On Mar 7, 2006, at 8:49 PM, wbounce wrote:

I guess I forgot to say I was operating at 16MHZ. 16us is probably close enough. So I hook the sensor to PIND4 and set timer1 to a prescale of 256

OK, that'd give you a resolution of 1/16 MHz (or 16usec).

Then I need to enable the TICIE1 interrupt in TIMSK.

Yes. But you also have to set up the input capture.

So look at TCCR1B, in which you have to set up ICNC1 and ICES1.

The setting of ICES1 is important:

• Bit 6 – ICESn: Input Capture Edge Select
This bit selects which edge on the Input Capture Pin (ICPn) that is used to trigger a capture
event. When the ICESn bit is written to zero, a falling (negative) edge is used as
trigger, and when the ICESn bit is written to one, a rising (positive) edge will trigger the
capture.
When a capture is triggered according to the ICESn setting, the counter value is copied
into the Input Capture Register (ICRn). The event will also set the Input Capture Flag
(ICFn), and this can be used to cause an Input Capture Interrupt, if this interrupt is
enabled.
When the ICRn is used as TOP value (see description of the WGMn3:0 bits located in
the TCCRnA and the TCCRnB Register), the ICPn is disconnected and consequently
the Input Capture function is disabled.

So let's think about it: you want to have the first interrupt happen on a rising edge. And the second interrupt should happen on the falling edge.

So you'd set up ICES1 to be 1 at first.
You might also like to set up a pointer to an area in RAM where you'll save the timer information.
And maybe a counter to tell how many edges you've seen.

In the ICP1 interrupt handler you'd do this:

* save the value of TCNT1L and TCNT1H to where your pointer points (incrementing it)
* increment (or decrement) your edge counter
* complement ICES1 so you can see the complementary edge
* if this was the falling edge (that is, if ICES1 was 0) then you can compute the high period by subtracting the last value from the first value (both 16 bits).

But I still do not understand how I time the "high" part. In the interrupt routine, I guess I disable interrupts and save ICR1 to a variable

Yes.

and reenable interrupts.

Not really necessary; the RETI instruction will do this for you.

Then the variable holds the elapsed time but how do I know it it the "high" time and not the low time.

Because you set ICES1 to be 0 to catch the falling edge (after setting it to be 1 to catch the rising edge).

On page 115 under Input Capture Unit it mentions "and this change conforms to the setting of the edge detector, a capture is triggerred." But I do not see anything about how to set the "edge detector." Ideally it should start timing on the rising edge and trigger the capture on the falling edge.
Also what happens if the input capture exceed the timer resolution?

Exceeds the resolution, or exceeds the total period?

You have to make sure that the period you're timing is no longer than the period taken by 65536 counts of your timer if you want a reliable count.

Otherwise, you have to extend the counter length by keeping an extension counter that's incremented in the Timer1 overflow handler. But if you've set up Timer1 so that the overflow period is always longer than the intervals you're timing (the high or the low periods if you're complementing ICES1) then subtracting the two numbers will work fine, even if there's an overflow in between (as long as there's only 1 maximum).

Imagine a free-running Timer1.

First you set up ICES1 to 1, and enable the IC1 interrupt.

When you get the IC1 interrupt, it'll be for the rising edge. You capture TCCNT1L/H.

Let's say that it's 0xC000.

Then you complement ICES1 to catch the falling edge.

The next interrupt you capture TCCNT1L/H into another variable.

Let's say that it's overflowed, and now reads 0x1000.

That is, the counter has advanced by 0x5000 counts.
And it's overflowed betwen 0xFFFF and 0x0000, but you don't care:
If you subtract 0xC000 from 0x1000 you will get 0x5000.

Same thing would happen if you'd read it as 0x1000 and 0x6000.

--
Ned Konz


Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.