I'm working on a project that involves measuring the intervals between a series of short (~10 uS) low-high-low pulses. The code below works but I noticed that the first interval comes out to be about 50 clock cycles longer than all of the subsequent ones. (Though sometimes the difference is close to zero or around a hundred.)
This sketch is running on a Duemilanove and for testing purposes I'm using another Arduino as a pulse generator. I've looked at the test pulses on my scope and I'm pretty confident that the intervals are more consistent than this.
The sketch works well enough for my purposes but there's obviously something going on that I don't understand, so I'd appreciate any efforts to cast light on what's going on here. General feedback on the approach I am taking here is welcome, too.
(Thank you, Nick Gammon, for the examples on your website. This is my first foray into interrupts and timers and your code was super helpful.)
const int outPin = PD2; //pin 2
const int inPin = PD7; // pin 7
volatile unsigned int overflowCount;
unsigned int timer1CounterValue;
unsigned int overflowCountCopy;
unsigned long t1Count[] = {0,0,0,0}; //measuring four splits between five signals
unsigned long t1ovf[] = {0,0,0,0};
void setup() {
pinMode(inPin, INPUT);
Serial.begin(9600);
}
void loop() {
scan5();
delay(1000);
}
ISR (TIMER1_OVF_vect) {
++overflowCount; // count number of Counter1 overflows
} // end of TIMER1_OVF_vect
void scan5() {
overflowCount = 0;
TCCR1A = 0;
TCCR1B = 0;
TIFR1 = bit (TOV1);
TIMSK1 = bit (TOIE1); // interrupt on Timer 1 overflow
// start Timer 1, no prescaler
TCCR1B = bit (CS10); //Set CS12:0 to 001 for no prescaling
for (int i = 0; i < 4; i++){
//wait for first rising edge:
while ((PIND &= _BV(inPin)) == 0) {/*wait*/}
TCNT1 = 0; //signal line went high so reset counter to zero
overflowCount = 0;
// do nothing while pin stays high
while ((PIND &= _BV(inPin)) == _BV(inPin)) {/*wait*/}
// wait for inPin to go high again
while ((PIND &= _BV(inPin)) == 0) {/*wait*/}
timer1CounterValue = TCNT1;
overflowCountCopy = overflowCount;
overflowCount = 0;
//check for interrupt while getting TCNT1
if ((TIFR1 & bit(TOV1)) && timer1CounterValue < 256){
overflowCountCopy++;
}
t1Count[i] = timer1CounterValue;
t1ovf[i] = overflowCountCopy;
}
for (int i = 0; i < 4; i++){
float microSeconds;
unsigned long totalCounts;
totalCounts = (t1ovf[i] << 16) + t1Count[i];
microSeconds = float(totalCounts)/16;
Serial.print("Overflow count: "); Serial.print(t1ovf[i]); Serial.print("\tT1 count: ");
Serial.print(t1Count[i]);
Serial.print(" -- "); Serial.print(microSeconds); Serial.println(" microseconds");
}
Serial.println(t1Count[0]-t1Count[1]); // show discrepancy between measurements
Serial.println("****************************************************");
}