Rpm readout with ir sensor

is this an accurate measurement of the rpm to? because this works i think. the rpm value is a bit high i think. 4000 rpm roughly. its a 12V DC motor runing on 5V currently and before i was measuring around 2000 rpm and i'm not quite sure wich one is correct and i don't have the specs either.

int interrupt = 2;
int teller;

volatile unsigned long current_micros;
volatile unsigned long old_micros;

volatile unsigned long current_millis;
volatile unsigned long old_millis;

volatile bool state;

unsigned long time1;
unsigned long rpm;
unsigned long frequentie;
float periode;

void setup() {
  analogWrite(3, 127);
  pinMode(interrupt, INPUT);
  attachInterrupt(digitalPinToInterrupt(interrupt), toerental, RISING);
  Serial.begin(115200);

}

void loop() {
  current_millis = millis();

  if(current_millis - old_millis >= 1000){
    
    frequentie = teller/2;
    rpm = frequentie * 60ul;
    
    
    Serial.print(teller);
    Serial.print(" ");
    Serial.print(frequentie);
    Serial.print(" ");
    Serial.println(rpm);

    old_millis = current_millis;
    teller = 0;
  }

}

void toerental() {

  if(micros() - old_micros > 1000){
    
    old_micros = micros();
    teller++;
    

  }
}

Tested in Wokwi image
490 is your "teller" value (which is the actual PWM frequency)
245 is your "frequentie" value
14700 is your "rpm" value

This

frequentie = teller/2;

causes frequentie and rpm to be 50%.

What is the reason for dividing by 2?

image

Edit: Are there 2 slots on the rotating disc? If so, then dividing by 2 is correct.

i divided the value by 2 because there are 2 slots in the rotating disc, so 2 counts/revelution. i think i got the solution. thank you so much for the help.

int interrupt = 2;
int teller;

volatile unsigned long current_micros;
volatile unsigned long old_micros;

volatile unsigned long current_millis;
volatile unsigned long old_millis;

unsigned long rpm;
unsigned long frequentie;

void setup() {
  pinMode(interrupt, INPUT);
  attachInterrupt(digitalPinToInterrupt(interrupt), irs, RISING);
  Serial.begin(9600);

}

void loop() {
  current_millis = millis();
  
  if(current_millis - old_millis >= 500){
    
    frequentie = teller;
    rpm = frequentie * 60ul;
    
    
    Serial.print(teller);
    Serial.print(" ");
    Serial.print(frequentie);
    Serial.print(" ");
    Serial.println(rpm);

    old_millis = current_millis;
    teller = 0;
  }

}

void irs() {

  if(micros() - old_micros > 6000){
    old_micros = micros();
    teller++;
    

  }
}
1 Like

is it possible maybe that the clockpin of a 7 segment display interrups the isr of the sensor?

Note:

  • 6000μs limits the maximum frequency to 1/0.006 = 166 Hz = 10,000 rpm

However, there's something much more important that needs to be considered. That is what the signal looks like.

  • Is the signal is mostly LOW (i.e. 8-bit pwm with duty 1-127)?
  • Is the signal is mostly HIGH (i.e. 8-bit pwm with duty 128-254)?
  • If it's mostly LOW, I suggest using RISING interrupt mode
  • If it's mostly HIGH, I suggest using FALLING interrupt mode

To see what it looks like, I suggest monitoring the signal with a scope or maybe using an analog input and the serial plotter.

Check the updated wokwi example in post #11.

  • I've updated it to include an easy way to turn on/off bounce on the 492Hz pwm signal
  • Change the pwm duty to closely match what your signal looks like
  • Change the interrupt mode as required
  • Test with appropriate debounce value so as its not too high (limiting the max required rpm) and not too low (letting through noise or bounce)

Tip: In the example, change the debounce duration to 2000

PWM with bounce on rising and falling ...

Bounce on rising zoomed in ...

my analog signal looks like this:

it's mostly high so i used falling for interrupt, still no luck. my max rpm should be around 5000 rpm so i'm not worried of hitting any limits. if i copy and paste your code and run it, it enters the if function around 8 times per ms. this should be impossible right?

somehow it doesn't update the old- and new micros properly.

Knipsel

The signal is defiantly bouncing as seen in post#26.

The OP might consider putting a cap resistor network on pin interrupt to serve as hardware debouncing.

what kind of values am i looking for? 10k resistor and a 220µF capacitor?

That would give a 60% charge on the cap at 1RC. A good starting point.

little update, i switched to the analog output of my ir sensor and the problem seems to be away

Can't print from inside an interrupt routine.

Anyways, you only work with the teller variable outside of the interrupt routine, so you'll need to turn off interrupts, take a copy of teller, then clear teller, then turn on interrupts. Now you can work with teller_copy in the main loop without issue.

Here's a new simulation example ...

thank you so much for the help. this saved my schoolproject.

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