RPM measurements strange behavior

So, iv'e been fiddling around with different methods of measuring RPMs last couple of days.

I did find this thread on the forum:
https://forum.arduino.cc/index.php?topic=416602.0

and the post by dlloyd peaked my interest.

So i tried it out, and it seems to work great, mostly.

At a bit higher frequencies, say, over 200Hz, there is some measurements that reads to high.

output [you can see the freak value in the middle]:

17026.11 RPM 283.77 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
17026.11 RPM 283.77 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
34052.21 RPM 567.54 Hz
17026.11 RPM 283.77 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17016.45 RPM 283.61 Hz
17026.11 RPM 283.77 Hz

code:

const byte rpmInputPin = 2;
const byte rpmMeasurementCycles = 2;
const byte printInterval = 500;

volatile unsigned long startTime, stopTime;
volatile byte rpmCount, testState;
unsigned long rpmPeriod, currentMillis, previousMillis = 0;;
float rpmFrequency, rpm;

void setup()
{
  Serial.begin(115200);
  pinMode(rpmInputPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(rpmInputPin), rpmMeasure, RISING);
}

void loop()
{
  if (testState == 2) EIMSK &= ~bit(INT0); // disable INT0 interrupt
  currentMillis = millis();

  if (currentMillis - previousMillis >= printInterval) {
    previousMillis = currentMillis;
    if (testState == 2) {    // testing completed, results are ready
      noInterrupts();
      rpmPeriod = (stopTime - startTime) / rpmMeasurementCycles;
      interrupts();
      rpmFrequency = 1000000.0 / rpmPeriod;
      rpm = rpmFrequency * 60.0;
      Serial.print(rpm);
      Serial.print(" RPM  ");
      Serial.print(rpmFrequency);
      Serial.println(" Hz");
      rpmCount = 0;
      testState = 0;        // clear testState
      EIFR |= bit(INTF0);   // clear INT0 interrupt flag
      EIMSK |= bit(INT0);   // enable INT0 interrupt
    }
  }
}

void rpmMeasure() {
  switch (testState) {
    case 0:
      startTime = micros();
      testState = 1;
      break;
    case 1:
      rpmCount++;
      if (rpmCount == rpmMeasurementCycles) {
        stopTime = micros();
        testState = 2;
      }
      break;
  }
}

Could there be something with the serial routine that is bothering it?

Thanks!

Post a link to the sensor that is being used. Perhaps the output bounces.

This:

      EIFR |= bit(INTF0);   // clear INT0 interrupt flag

should be:

      EIFR = bit(INTF0);   // clear INT0 interrupt flag

Otherwise you may inadvertently clear other interrupt bits. See the processor data sheet for an explanation.

Thank you very much for your input.

Actually iam using a function generator.
However, i have tried to catch any problems in the signal with my oscilloscope, but i cannot find any.

jremington:
Post a link to the sensor that is being used. Perhaps the output bounces.

This:

      EIFR |= bit(INTF0);   // clear INT0 interrupt flag

should be:

      EIFR = bit(INTF0);   // clear INT0 interrupt flag

Otherwise you may inadvertently clear other interrupt bits. See the processor data sheet for an explanation.

Could this be the cause? I changed that, and i cannot seem to catch the error again after that.

Could this be the cause?

Who knows? If the problem is fixed, celebrate!

It sure seems like it!

Thank you for your help & good catch.