I've been testing different ways to measure pulse width using Teensy 3.1 and 48 MHz clock. The signal is a narrow positive going pulse at a 10 msec rate.
First, pulseIn, 1 usec resolution.
Second, polling with digitalRead, about 0.5 usec resolution.
Third, polling with digitalReadFast, about 0.27 usec resolution.
Fourth, interrupt using ARM cycle clock, 0.021 usec resolution, 1/(48 MHz).
I noticed the interrupt-based code below doesn't work correctly for pulses less than about 2.4 usec wide. Does that sound right for interrupt response time?
I just read about flextimer but I didn't understand the details. Would it work for narrower pulses?
I may also just use digitalReadFast and 72 MHz.
Thanks.
First, pulseIn, 1 usec resolution.
Second, polling with digitalRead, about 0.5 usec resolution.
Third, polling with digitalReadFast, about 0.27 usec resolution.
Fourth, interrupt using ARM cycle clock, 0.021 usec resolution, 1/(48 MHz).
I noticed the interrupt-based code below doesn't work correctly for pulses less than about 2.4 usec wide. Does that sound right for interrupt response time?
I just read about flextimer but I didn't understand the details. Would it work for narrower pulses?
I may also just use digitalReadFast and 72 MHz.
Thanks.
Code:
/* tests for Pulsein vs counting loop to test resolution
16 Sept 2016
Teensy 3.1, Arduino 1.6.9 and Teensyduino 1.29
tests variation in readings using ARM cycle clock
*/
// global variables
const int testPin = 7; // 100 Hz input from pulse gen
unsigned long longCounter = 0; // counts passes thru loop
unsigned long pw = 0;
volatile unsigned long timeStamp = 0; //system clock captured in interrupt
unsigned long riseIntr = 0; //system clock at rising edge
int testStat; // value of testPin
void setup() {
// From Teensy forum
ARM_DEMCR |= ARM_DEMCR_TRCENA; // debug exception monitor control register; enables trace and debug
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; // enable cycle counter
Serial.begin(115200); // PC serial monitor via USB for debugging
pinMode(testPin, INPUT);
longCounter = -1; // I first noticed an occasional bad first read when testing digitalReadFast; skip 1st reading
delay(20000); // delay to start serial monitor
Serial.println("Test usng ARM cycle counter");
} // end of setup------------------------------------------------
void loop() {
longCounter++;
delay(50);
do { // wait for input to go low
testStat = digitalReadFast(testPin);
} while (testStat == 1);
attachInterrupt(testPin, phase_ISR, CHANGE); // turn on interrupt just after input goes low
timeStamp = 0; // use as a flag too
while (timeStamp == 0) { // wait for input to go high signalled by timeStamp
}
riseIntr = timeStamp; // system time at rising edge
timeStamp = 0;
while (timeStamp == 0) { // wait for the next edge, will be falling edge
}
detachInterrupt(testPin); // off so other msmnts not affected
pw = timeStamp - riseIntr;
Serial.print(longCounter);
Serial.print(" ");
Serial.println(pw);
} // end of loop
//-----------------------
void phase_ISR() {
timeStamp = ARM_DWT_CYCCNT;
}