How to measure a pulse width

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you think about the following way to measure a pulse width of an input signal (square wave), about equal to (tfall - trise) ?

Since Timer1 rolls over continuously, in order to measure time differences greater than 2^n*Tck, I was thinking to add a count number to keep trace of which period is referring the TCNT1 data.

For example, if the timer has 2bit:

count +4      +8     +12      +16
       |       |       |       |
0|1|2|3|0|1|2|3|0|1|2|3|0|1|2|3|0|1|2|3|...
   |<------------->|      
  rise            fall

Infact:

fall_time - rise_time = (10-2) * Tclock

At every timer overflow, the variable count is incremented of 4 (2^n).

A possible pseudo code:


count = 0;

Timer1 Overflow Interrupt:
{
  count = count + 2^n;
}


Capture Input Interrupt:
{
   if input is rising
   {
      rise_time = ICR1 + count;
      change input sense to falling; 
   } 
   else 
   {
      fall_time = ICR1 + count;
      change input sense to rising;
      calculate pulse width as (fall_time - rise_time);
      count = 0; 
   }

}

What do you think about?

My (HW && SW) Setup: (MyAVR USB Programmer | bread-board | Butterfly | Arduino 10k | ATtiny2313 | ATmega8) && (WinAVR | AVR asm | AVRstudio)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What do you think about?

Keira Knightley mostly - but when thinking about the more mundane matters of AVR timers I wonder why one would not use ICP or asynchronous timer clocking to measure pulse widths rather than doing it "soft" as you propose.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've described the 'usual' method, but the devil is in the detail. If both a capture and an overflow occurred at the same time, what interrupt would be serviced first? How would you code to cope with that possibility?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
You've described the 'usual' method, but the devil is in the detail. If both a capture and an overflow occurred at the same time, what interrupt would be serviced first? How would you code to cope with that possibility?
You check the TOV1 bit.

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Keira Knightley

better Monica Bellucci :)

My (HW && SW) Setup: (MyAVR USB Programmer | bread-board | Butterfly | Arduino 10k | ATtiny2313 | ATmega8) && (WinAVR | AVR asm | AVRstudio)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Half points Arnold, you also need to reset the tov1 bit once you've dealt with it. You know this already I'd presume.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
If both a capture and an overflow occurred at the same time, what interrupt would be serviced first?

TIMER1 CAPT is vector 11
TIMER1 OVF is vector 14

So capture will be serviced first than overflow?

My (HW && SW) Setup: (MyAVR USB Programmer | bread-board | Butterfly | Arduino 10k | ATtiny2313 | ATmega8) && (WinAVR | AVR asm | AVRstudio)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If my memory seves me correct, yes. Therefore in the capture isr you would check the status of the TOV1 bit to see if an overflow had occured, if so, do the same processing you would in the overflow isr then write a '1' bit back to the TOV1 to clear it (seems weird, but it makes sense when you think about it) - this resets the TOV1 isr from executing when you exit your current isr.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Half points Arnold, you also need to reset the tov1 bit once you've dealt with it.
That depends on how you "deal with it". if you do the work of the TOV ISR (that is, increment the counter), then, yes. If you just take the overflow into account in the current measurement, then no. If all the TOV ISR does is increment the counter, then the first would be the way to go. If that ISR does more than that, you might want to consider the second.

Also, just checking the flag is not good enough since it might have happened after the capture. If the captured value is close to BOTTOM, then the overflow happened before the capture interrupt. If the captured value is close to TOP, then the overflow happened after the capture, so you ignore the overflow and let the TOV ISR take care of it.

Quote:
So capture will be serviced first than overflow?
Yes.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Measuring pulse width is complicated. This is a disadvantage of AVRs - timers do not have "enable" pin (like PICs for example) to count only while "enable" pin is high/low. ICP seems more universal than "enable" but toggling must not be too frequent or too close to each other to manage with ISR servicing. What is even worse - if three edges happen - you will never know about that. So it is basically suited for:

    - low frequency (below 20kHz) - pulse width of about 10-90%
    - low jitter (to be able to assign enough time for edge switch)

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
If the captured value is close to BOTTOM, then the overflow happened before the capture interrupt. If the captured value is close to TOP, then the overflow happened after the capture, so you ignore the overflow and let the TOV ISR take care of it.

You can check the MSB of captured value to see if it's close to BOTTOM (TOP).

It's a trick that was described on a 68HC11 manual (which use same system to capture input events); there is also the code but it is in assembly.

My (HW && SW) Setup: (MyAVR USB Programmer | bread-board | Butterfly | Arduino 10k | ATtiny2313 | ATmega8) && (WinAVR | AVR asm | AVRstudio)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was trying to measure periods like this: timer1_ovf int, and a pinchange int. PCints are either edge, so when the int hits, you read the input, and if its hi, you read the timer+ovf counter and return. Next edge int, you read the timer+ovf counter and calc diff. The detail that confuses me is it takes a usec or 2 to get in and out of the interrupt, so we need to deal with the situation where the timer wraps and tries to cause an ovf int, but the edge might happen before the ovf gets serviced, so you are off by 65536 and everything looks negative and the calc go out the window. How do you defend against 'timer almost ready to wrap'? Figure out how many counts is 2usec back from the overflow?

Imagecraft compiler user