How to measure pulse width on Teensy 3.1 input pin.

RLN37

Member
How can I measure the pulse width seen on a Teensy 3.1 input pin, say pin 4?
If this requires use of Timer1 (and TimerOne.h), how do I do it?
Thanks for any hints. . . .
 
How about attachInterrupt() on pin 4 with CHANGE as the mode, then in the interrupt routine use digitalReadFast() to see if the pin is high or low, and use the current clock with micros() or millis() (depending on the resolution) to see how long the width was? You could either use a global for the time if you only care about one pulse, or an array to record many samples for later analysis?
 
You only need to know if it is high or low once. the next time will be the opposite

...unless your ISR is too slow or frequency input is too fast. ;-)
 
How can I measure the pulse width seen on a Teensy 3.1 input pin, say pin 4?
If this requires use of Timer1 (and TimerOne.h), how do I do it?
Thanks for any hints. . . .

I am using the Teensy 3.1 to capture and measure the duration of a Loom Pick Pulse. Basically the Time of Flight for a Pick to move a thread across a Loom Fabric. This is just the critical pieces you would need to capture the pulse. I wasn't as successful get the CHANGE interrupt to work, but using the HIGH and LOW checks, I am able to capture down to the Millisecond with ease. I am still a novice coder, but the non-techies here are pretty impressed. I have about $80 in the install, compared to two bids of over $3500 each to do the same thing...!! The Teensy3.1 is amazing.

Hope this helps....
Steve


Code:
Setup() {
Variables and other setup stuff goes HERE....
attachInterrupt(Loom_Pulse, GoHigh, RISING); // encoder pin on interrupt 0 (pin 2);
}

[COLOR="#0000FF"][B]Then when it detects a High Pulse....[/B][/COLOR]

void GoHigh() {
  detachInterrupt(Loom_Pulse);
  microseconds = micros();
  attachInterrupt(Loom_Pulse, GoLow, FALLING); // encoder pin on interrupt 0 (pin 2);
}  

[B][COLOR="#0000FF"]Then it waits for a Low Pulse....Does some Stuff then Resets the Interrupt to Looking for High.[/COLOR][/B]
	
void GoLow() {
  detachInterrupt(Loom_Pulse);  
  if(indexer < numberOfEntries ) {
    FlightTime = micros() - microseconds;
    if ((indexer > 0) && (FlightTime > 5000) && (FlightTime < 100000) && (Break_Out ==0)) {  //Eliminate readings below 5000 after Breakout and Restart   
      results[indexer] = FlightTime + MsecOffset;
      pressure[indexer] = analogRead(analogPin);
      indexer = indexer + 1; 
    }
    if (indexer == 0) {  //Throw away first measurement
      indexer = indexer + 1;
    }  
  }
 Break_Out = 0;
 attachInterrupt(Loom_Pulse, GoHigh, RISING); // encoder pin on interrupt 0 (pin 2);
}
 
I need to measure pulse width on two input pins. I want to use the same interrupt handler.
is there a way to determine which pin caused the interrupt from the interrupt handler?
In avr arduino, I use the pin mask to determine which pin changed. How do I do it in teensy 3.1?

Thanks.
 
I did some more reading, it looks like I can find out which pin caused the interrupt by reading the ISFR register.
so if I configure pins 1 and 2 to use the same handler, I can check PORTB_ISFR bit 17 (for pin1) and PORTD_ISFR bit 0 (for pin 2) to find out which pin caused the interrupt? I assume the bits are not cleared until isr handler returns.
 
there is also a pulse width measuring library as I recall that uses a hardware timer in capture mode. This is simpler/better/more accurate than interrupts.
 
I tried it and it works. It is quite simple. I just added this at the start of my handler

Code:
  uint8_t i=0;
  
  if (PORTD_ISFR & CORE_PIN2_BITMASK)
    i = 1;

I have pin change interrupt on pins 1 and 2. and my variables are in an array of size 2.
if interrupt originated from pin2, it sets i=1 otherwise, assume it is pin 1 that caused the interrupt.

this is good enough for me. it does not have to be accurate.
I've used a similar feature you described with the library that use hardware timer on AVR, it is needed if you want exact timing, as even if other higher priority interrupt is executing, the timestamp of the actual time the interrupt occurred is captured.
 
Hmmm... maybe I ought to make a PulseMeasure library, similar to FreqMeasure, but returning the time between rising and falling edges. FreqMeasure returns the time between successive rising edges.
 
I took a quick look at FreqMeasure, can only be used with hard coded pin 3, so I can't use it as I am measuring rpm on 2 pins.
I agree a library should be usable with any pin, or better, multiple pins simultaneously (at least equal to number of FTM available) to be more useful.
 
Looking at Pulseposition library I believe it shows: // rxPin can be 5,6,9,10,20,21,22,23
 
I agree a library should be usable with any pin, or better, multiple pins simultaneously (at least equal to number of FTM available) to be more useful.

I'd love to do this with the FreqMeasure library someday.

If anyone gets to it before I do, pull requests are welcome. This is open source, afterall.

But eventually, I'll probably do this. It really is needed, and it seems unlikely anyone else will write such a library.
 
I thought I posted something a few months ago on this, but can't find it now. Anyway I remember making a fairly small modification to the "pulse position" library http://www.pjrc.com/teensy/td_libs_PulsePosition.html and getting good resolution (0.02 usec) on a pulse width.

Can the Pulse Position library also be used as a replacement to the slow pulseIn() function to read microsecond PWM pulses from an RC Receiver, rather than PPM?
 
Hi Paul
Any progress on the pwm measure library. I can do some testing if you want :eek:
Hi All,
Digging up an old thread...

I have a sync pulse on one pin and need to measure 4 other signals timing relative to the sync. I basically need a non-blocking PulseIn() between two pins (it's relatively low frequency, durations of 10us to 100ms). I understand that some of the Teensy timers can natively do this between two pins that are associated with that timer. I started looking at hacking up FreqMeasure, FreqMeasureMulti, Pulseposition , and the PWM decoder libs.

Before I do, has there been any progress on a library for this, or does someone have some code that is close that I can build on?

If not, is FreqMeasure the best place to start?

Thanks a lot,
Dave.
 
One way I can think of doing this with the least amount of hassle would be to choose one pin for "sync" on a pin group different than the other four and to set the priority lower than the pins on a different port, or set different port IRQ as a higher priority.
 
Back
Top