Tachometer DAQ - aliasing issues

Hello, I am new to arduino so i am relying on what has been done and using my ability to copy and paste. I am trying to measure rotational speed with a inductive prox probe if5793 and plot it versus time in excel. The speed I am testing ranges from 15-1000 rpm. I have used the code from jurs here.

I made a few simple modifications, like sampling every 1 second, and printing current time to the serial monitor. However, i am getting some aliasing every 12-15 seconds or so, the rpm reading will return -1, or a value that is slightly higher than the previous 15 measured values. Here is my code. Any advice would be appreciated! Thank you.

#define TENMINUTES (1000L) // ten minutes are 600000 milliseconds
#define REEDPIN 2
volatile int reedCount_ISR;
long int mytime = 0;
long int oldtime = 0;
long int diftime =0;
long int rpm =0;

void reedSwitch_ISR()
{
reedCount_ISR++;
}

void setup() {
Serial.begin(9600);
// setup whatever your sensors will need
pinMode(REEDPIN,INPUT_PULLUP);
attachInterrupt(0,reedSwitch_ISR, FALLING);
}

unsigned long last10Minutes;
void loop()
{
mytime = millis()/1000;
diftime = mytime - oldtime;

if (millis()-last10Minutes>=TENMINUTES)
{
last10Minutes+=TENMINUTES; // remember the time

noInterrupts();
int reedCount=reedCount_ISR;
    interrupts();
    rpm = 60*reedCount/diftime;
reedCount_ISR=0;
  oldtime = mytime;

  Serial.print(mytime); 
  Serial.print("\t");
  Serial.println(rpm);

}
}

You are measuring time in full seconds and taking a reading every second so sometimes your time will be 0 and sometimes 2 but mostly 1.

I'm not sure I follow. What do you suggest I change?

thanks.

Measure 'diftime' in milliseconds instead of seconds. Then you will have values around 1000 (998 to 1002, for example) instead of numbers around 1 (0, 1, or 2) to divide by.

Note: You should clear reedCount_ISR while interrupts are still disabled.

const unsigned long ONE_SECOND = 1000UL;
const byte REEDPIN = 2;
volatile unsigned reedCount_ISR;
unsigned long mytime, oldtime, diftime = 0;
unsigned long lastReadingTime;

long int rpm = 0;

void reedSwitch_ISR()
{
  reedCount_ISR++;
}

void setup()
{
  Serial.begin(9600);
  // setup whatever your sensors will need
  pinMode(REEDPIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(REEDPIN), reedSwitch_ISR, FALLING);
}

void loop()
{
  mytime = millis();

  if (mytime - lastReadingTime >= ONE_SECOND)
  {
    lastReadingTime += ONE_SECOND; // remember the time

    // Read and write volatile variables only with interrupts disabled.
    noInterrupts();
    unsigned reedCount = reedCount_ISR;
    reedCount_ISR = 0;
    interrupts();

    diftime = mytime - oldtime;
    oldtime = mytime;
        
    rpm = 60000UL * reedCount / diftime;

    Serial.print(mytime/1000);
    Serial.print("\t");
    Serial.println(reedCount);
        Serial.print("\t");
    Serial.println(rpm);
  }
}
1 Like

Thank you kind sir! this is working a little better now. at slow speed 120rpm and below, the reading is good. however 120-2000 there is always a value that is off. I think it has something to do with the sampling rate of the interrupt and the rpm. I know serial.print is not reccomended for interups - perhaps this is causing the issue? i've tried chaining the sapling range and using micros with no succus.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.