RPM Measurement without Interrupts

Hi all

I'm trying to measure RPM of a DC Motor using Quadrature encoder. I have a problem with the B output of encoder so I'm just using one output. I don't need direction and some missing pulses are not a problem. I want to see RPM approximately.

With the code below, I have tried at several voltages and I'm able to count revolutions correctly. 64 indicates the number of pulse for one revolution.

int counter = 0;
int Pre;
void setup() {
  Serial.begin(9600);
  pinMode(PE0, INPUT);
  Pre = digitalRead(PE0);
}

void loop() {

  if (digitalRead(PE0) != Pre)
  {
    counter++;
    Serial.println(counter / 64);
    Pre = digitalRead(PE0);
  }
}

Instead of counting all the pulses, I wanted to add a millis function that I can count pulses in 100ms and multiply it with 600 to get 1 minute rpm approximately however I have a problem with my code.

int counter;
int interval = 100;
int Pre;
int time1 = 0;
int time2 = 0;
int time3 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(PE0, INPUT);
  Pre = digitalRead(PE0);
}

void loop() {

  time1 = millis();
  time3 = time1 -= time2;
  if (time3 > interval) {
    time2 = millis();
    if (digitalRead(PE0) != Pre)  {
      counter++;
      Pre = digitalRead(PE0);
      Serial.println(counter * 600 / 64);
      counter = 0;
    }
  }
}

If I add counter = 0, all I get from serial print is 0. If I don't add it, pulses are not resetting. I have tried to change counter position to beginning of loop etc. but nothing worked. What else I can do to measure rpm using milis function?

BTW: I'm using STM32 board with Arduino IDE, that's the reason of PE0 pin. Thank you.

  time1 = millis();
  time3 = time1 -= time2;
  if (time3 > interval) {
    time2 = millis();

Maybe those names mean something to you. The don't mean squat to me.

You are decrementing now by time2. Does that make sense to you?

If you want to count pulses for some period of time, I'd rather expect to see a while statement somewhere.

Yes you are correct, it’s not clear.

Time1= Current time Time2= Previous time Time3= Interval.

I have checked several examples that all of it had if statements in such way. That’s why I didn’t think about while statement to be honest.

I'd have done it something like this, based on your code (untested) :

int interval = 100;
int counter = 0 ;
uint32_t frameStartAtMs ;
int Pre;

void setup() {
  Serial.begin(9600);
  pinMode(PE0, INPUT);
  Pre = digitalRead(PE0);
  frameStartAtMs = millis() ;
}

void loop() {  

   if ( millis() - frameStartAtMs > interval ) {
      Serial.println(counter * 600 / 64);
      frameStartAtMs = millis() ;
      counter = 0;
   }
   if (digitalRead(PE0) != Pre)  {
      counter++;
      Pre = digitalRead(PE0);
   }
}

6v6gt: I'd have done it something like this, based on your code (untested) :

int interval = 100;
int counter = 0 ;
uint32_t frameStartAtMs ;
int Pre;

void setup() {   Serial.begin(9600);   pinMode(PE0, INPUT);   Pre = digitalRead(PE0);   frameStartAtMs = millis() ; }

void loop() { 

  if ( millis() - frameStartAtMs > interval ) {       Serial.println(counter * 600 / 64);       frameStartAtMs = millis() ;       counter = 0;   }   if (digitalRead(PE0) != Pre)  {       counter++;       Pre = digitalRead(PE0);   } }

Working like a charm, thank you very much.

How fast is the shaft rotating and how many pulses per second are produced at maximum speed?

Measuring RPM is one situation where IMHO using interrupts is very convenient. Have a look at the code in this link. It is designed for 1 pulse per rev but could easily be adapted to more. It works happily at 15,000 RPM

...R

Motor is producing 11.700 pulses per second at maximum speed. The reason why I don’t use external interrupt is, I’m not using a genuine Arduino. It’s a STM32 board and I am using Arduino IDE. On my previous trials, I have tried to use external interrupts but I think Arduino IDE doesn’t support fully my card so pins didn’t react as external interrupts. With the code above, I’m capable to measure my rpm approximately. It may missing some pulses but very high accuracy isn’t a big deal for me, I’m just trying to understand the coding logic and results are satisfactory enough.