I'd like to use Timer1 to measure the time between rising edges of two input signals. Specifically, use Tn to start the timer counter and IPCn to latch the elapsed time since the rising edge of the Tn input signal. The goal is to measure the time between the rising edges of two input signals. Is there a Timer1 library out there that alread does this? Code suggestions welcomed.
2 Answers
It is not perfect for your simpler task, but here is a link to a sketch that I have used to record pulses, using the Timer1 Input Capture.
In short setup the Interrupt
void initTimer(void) {
// Input Capture setup
// ICNC1: Enable Input Capture Noise Canceler
// ICES1: =1 for trigger on rising edge
// CS10: =1 set prescaler to 1x system clock (F_CPU)
TCCR1A = 0;
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<CS10);
TCCR1C = 0;
//catchFallingEdge(); // initialize to catch
{ TCCR1B &= ~(1<<ICES1); TIFR1 |= (1<<ICF1); rising = 0; }
// Interrupt setup
// ICIE1: Input capture
// TOIE1: Timer1 overflow
TIFR1 = (1<<ICF1) | (1<<TOV1); // clear pending
TIMSK1 = (1<<ICIE1) | (1<<TOIE1); // and enable
// Set up the Input Capture pin, ICP1, which corresponds to Arduino D8
pinMode(8, INPUT);
digitalWrite(8, 0); // leave floating to count 60 Hz etc.
//digitalWrite(8, 1); // or enable the pullup
}
Then service it
ISR(TIMER1_CAPT_vect) {
union twobyte {
uint32_t word;
uint8_t byte[2];
} timevalue;
timevalue.byte[0] = ICR1L; // grab captured timer value
timevalue.byte[1] = ICR1H; // grab captured timer value
// watch for the other edge to catch the half-pulse width
//rising ? catchFallingEdge() : catchRisingEdge();
if (rising) {
TCCR1B &= ~(1<<ICES1);
TIFR1 |= (1<<ICF1);
rising = 0;
}
else {
TCCR1B |= (1<<ICES1);
TIFR1 |= (1<<ICF1);
rising = 1;
}
}
For more help and info, and many examples of various detailed aspects of timers, check out Nick Gammon's articles here: http://www.gammon.com.au/interrupts and here: http://www.gammon.com.au/timers
Under the first link, do a search for "The sketch below times intervals between RISING interrupts," for example, to find one code segment.
Now, important question: what is the minimum time you need to measure between events? Are we talking milliseconds, microseconds, or nanoseconds? For the former, you can use pin polling, external interrupts, or pin change interrupts, and the millis() or micros() Arduino functions to grab timestamps. For microseconds resolution, it depends. Even the micros() function only has a 4us resolution, so you'd have to custom-configure the timer if you want better than 4us resolution time-stamps, or you could use the timer2_counter library (http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html), or your own custom timer solution, for 0.5us resolution timestamps.
For nanosecond resolution (down to 62.5ns time steps), youd prob. need to use Timer1's input capture, as the other answer shows. You can also do a search for "Timing an interval using the input capture unit" under the 2nd link above, for another code segment on that.
// ICNC1: Enable Input Capture Noise Canceler // ICES1: =1 for trigger on rising edge // CS10: =1 set prescaler to 1x system clock (F_CPU) TCCR1A = 0; TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<CS10);
If I read this correctly (questionable), it looks like the everything is set backwards from what the text says it is supposed to be. Am I reading it wrong? Doesn't "(0<<ICNC1)" put a 0 into the ICNC1 bit? Doesn't that disable the noise canceler? This should be what you WANT for the purposes of catching every rising edge, but the explanation doesn't match the code. Also, doesn't "(0<<ICES1)" catch t