Help with calculating encoder RPM

Hello everyone,

I wanted to ask i somebody could help with encoder RPM calculations. According to motor driver datasheet motor driver datasheet at 6V it gives 8000 rpm.
It has a gearratio of 1:(52,734) which means the encoder rpm should around 8000*52,734 = 421872 rpm. Since i know what the solution should be I looked around the forum how to calculate rpm from encoder pulse values

which I got on the monitor using the code from this library encoder_buffer code .
I also had to know the pulses per revolutions. Since i already knew that encoder rpm is 421872 rpm, I converted it so RPS which is 7031 RPS. Using an oscilloscoop I saw that the encoder outputs( of the motor) had a frequency of around 379 hz or cyles/sec). Since i knew the frequency and the RPS, i could calculate counts per revolution = 379/7031 => 0,054. The formula for calculating RPM is revolutions/minute = (counts/minute) / (counts/revolution). So i changed the counts( i think those are the pulse values) per minute to:
interval is 100 ms
RPM = ((new_reading - old_reading )/ interval ) * 60*10)/ CPR. The only problem is the value I calculated is much larger than it should be. Could somebody tell where i did something wrong and how to fix it?

thank you very much. Oh I made only some changes when i tested it in de encoder_buffer_code so it would in quadrature count mode.

290-008_ig220053x00085r_ds.pdf (187 KB)

Could somebody tell where i did something wrong and how to fix it?

No, because you haven’t told us what is wrong and you haven’t shared your code.

421872 rpm

Impossible. None of your numbers are correct.

But you could check the gearmotor data sheet you linked, which says: no load, 150 RPM, rated speed 125 RPM.

ratio.png

ratio.png

code of the encoder buffer

// Inclde the standard Arduino SPI Library, please ensure the SPI pins are
// connected properly for your Arduino version
#include <SPI.h>

// Slave Select pins for encoders 1 and 2
// Feel free to reallocate these pins to best suit your circuit
const int slaveSelectEnc1 = 7;
const int slaveSelectEnc2 = 8;

// These hold the current encoder count.
signed long encoder1count = 0;
signed long encoder2count = 0;

void initEncoders() {
  
  // Set slave selects as outputs
  pinMode(slaveSelectEnc1, OUTPUT);
  pinMode(slaveSelectEnc2, OUTPUT);
  
  // Raise select pins
  // Communication begins when you drop the individual select signsl
  digitalWrite(slaveSelectEnc1,HIGH);
  digitalWrite(slaveSelectEnc2,HIGH);
  
  SPI.begin();
  
  // Initialize encoder 1
  //    Clock division factor: 0
  //    Negative index input
  //    free-running count mode
  //    x4 quatrature count mode (four counts per quadrature cycle)
  // NOTE: For more information on commands, see datasheet
  digitalWrite(slaveSelectEnc1,LOW);        // Begin SPI conversation
  SPI.transfer(0x83);                       // Write to MDR0
  SPI.transfer(0x10);                       // Configure to 4 byte mode
  digitalWrite(slaveSelectEnc1,HIGH);       // Terminate SPI conversation 

  // Initialize encoder 2
  //    Clock division factor: 0
  //    Negative index input
  //    free-running count mode
  //    x4 quatrature count mode (four counts per quadrature cycle)
  // NOTE: For more information on commands, see datasheet
  digitalWrite(slaveSelectEnc2,LOW);        // Begin SPI conversation
  SPI.transfer(0x83);                       // Write to MDR0
  SPI.transfer(0x10);                       // Configure to 4 byte mode
  digitalWrite(slaveSelectEnc2,HIGH);       // Terminate SPI conversation 
}

long readEncoder(int encoder) {
  
  // Initialize temporary variables for SPI read
  unsigned int count_1, count_2, count_3, count_4;
  long count_value;  
  
  // Read encoder 1
  if (encoder == 1) {
    digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation
    SPI.transfer(0x60);                     // Request count
    count_1 = SPI.transfer(0x00);           // Read highest order byte
    count_2 = SPI.transfer(0x00);           
    count_3 = SPI.transfer(0x00);           
    count_4 = SPI.transfer(0x00);           // Read lowest order byte
    digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation 
  }
  
  // Read encoder 2
  else if (encoder == 2) {
    digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation
    SPI.transfer(0x60);                      // Request count
    count_1 = SPI.transfer(0x00);           // Read highest order byte
    count_2 = SPI.transfer(0x00);           
    count_3 = SPI.transfer(0x00);           
    count_4 = SPI.transfer(0x00);           // Read lowest order byte
    digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
  }
  
  // Calculate encoder count
  count_value = (count_1 << 8) + count_2;
  count_value = (count_value << 8) + count_3;
  count_value = (count_value << 8) + count_4;
  
  return count_value;
}

void clearEncoderCount() {
    
  // Set encoder1's data register to 0
  digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation  
  // Write to CNTR
  SPI.transfer(0x20);    
  // Load data
  SPI.transfer(0x00);  // Highest order byte
  SPI.transfer(0x00);           
  SPI.transfer(0x00);           
  SPI.transfer(0x00);  // lowest order byte
  digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation 
  
  delayMicroseconds(100);  // provides some breathing room between SPI conversations
  
  // Set encoder1's current data register to center
  digitalWrite(slaveSelectEnc1,LOW);      // Begin SPI conversation  
  SPI.transfer(0xE0);    
  digitalWrite(slaveSelectEnc1,HIGH);     // Terminate SPI conversation   
  
  // Set encoder2's data register to 0
  digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation  
  // Write to CNTR
  SPI.transfer(0x20);    
  // Load data
  SPI.transfer(0x00);  // Highest order byte
  SPI.transfer(0x00);           
  SPI.transfer(0x00);           
  SPI.transfer(0x00);  // lowest order byte
  digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
  
  delayMicroseconds(100);  // provides some breathing room between SPI conversations
  
  // Set encoder2's current data register to center
  digitalWrite(slaveSelectEnc2,LOW);      // Begin SPI conversation  
  SPI.transfer(0xE0);    
  digitalWrite(slaveSelectEnc2,HIGH);     // Terminate SPI conversation 
}


void setup() {
 Serial.begin(9600);      // Serial com for data output
 
 initEncoders();       Serial.println("Encoders Initialized...");  
 clearEncoderCount();  Serial.println("Encoders Cleared...");
}

void loop() {
 delay(500);
 
 // Retrieve current encoder counters
 encoder1count = readEncoder(1); 
 encoder2count = readEncoder(2);
 
 Serial.print("Enc1: "); Serial.print(encoder1count); Serial.print(" Enc2: "); Serial.println(encoder2count); 
}

Code i added to give rpm

void loop()
{
     int interval = 100; // 100 ms
     int CPR = 0.054; // calculated counts per revolutions
     if(currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;  
    new_reading = readEncoder(1);
    RPM = ((new_reading - old_reading) / interval *(60*10)) / CPR;
    old_reading = new_reading;

}

the problem is the value i should get for RPM is 421872, but instead i get the value 21777777. Where did I do wrong with the calculations. I based to code of the formula revolutions/minute = (counts/minute) / (counts/revolution).

    int CPR = 0.054; // calculated counts per revolutionsAn integer cannot contain a fractional number.

See reply #2 for some of your other problems.

Ok thank you for your response for my problem. Maybe i wasn't clear about my other problem, which i will apologize for that. But again, my problem is I want make a formula to calculate the RPM from a LS766r quadrature encoder counter, but I'm not sure if i made the right approach(I don't have a definite code for formula, so I wrote one on paper). If i made a mistake somewhere could somebody point it out? So what I did

1e : To make the formula I looked into another forum and I found that to calculate RPM => revolutions/minute = (counts/minute) / (counts/revolution).

2e : The motor datasheet gives 150RPM(+/-15%), I converted this value to revolutions per sec. I also used a oscilloscoop to measure frequency of the pulses which I found a value of 379 cycles/sec. Using those two values I freq/rps => I have a CPR of around 3.

3e: To find (counts/minute) I considered the counts as the reading of the pulses( difference between the old and new value. Is it oke to consider that? Also the I considered the minute as the interval between the readings. So if I take for example a interval of 100 ms, do I need to make the interval 100*10*60 to make it one minute again? Or did I make a wrong approach here?

So in short I have some trouble defining a formule for RPM calculations and I was hoping if somebody could help or point out the errors I made in the 3 steps I did.

kind regards

Post a link to the encoder or its data sheet (LS766r does not seem to be correct) and explain how it is connected to the gear motor.

Then we can figure out the exact formula.

Are you using a LS7366?

With motor RPM of 8000, output shaft should be 151.7 RPM, 2.528 RPS.

Post a link to the encoder or its data sheet (LS766r does not seem to be correct) and explain how it is connected to the gear motor.

Then we can figure out the exact formula.

LS7366r This is the data sheet. I forgot to add the 3.

Are you using a LS7366? https://lsicsi.com/pdfs/Data_Sheets/LS7366R.pdf With motor RPM of 8000, output shaft should be 151.7 RPM, 2.528 RPS.

yes I use that one, RPM => revolutions/minute = (counts/minute) / (counts/revolution). I used your your rps and I using the formula freq/rps = counts per revolution. I get a value of 149 right?

The LS7366 is an encoder monitor IC, not an encoder.

We need to know the details of the encoder, specifically how many pulses per revolution.

Post the data sheet for the encoder.

Slow the motor down so you have a stable reading of 60 RPM, then count the revs against a stopwatch or clock. Start counting in your head at 0 seconds, count revs to 300 (don't miscount :) ), the clock should show exactly 5 minutes elapsed.

2e : The motor datasheet gives 150RPM(+/-15%), I converted this value to revolutions per sec. I also used a oscilloscoop to measure frequency of the pulses which I found a value of 379 cycles/sec. Using those two values I freq/rps => I have a CPR of around 3.

This is finally starting to look reasonable. You have fixed most of the earlier mistakes.

You need to be very clear on what end of the gearbox you are measuring. 150rpm is the output of the gearbox. The gear ratio is about 52, meaning the motor is spinning about 7800rpm.

You never said, but is the encoder on the motor end or on the output end of the gearbox? It is usually on the motor. That allows the encoder to measure the output very accurately because 1 revolution of the output requires 52 motor revolutions.

3e: To find (counts/minute) I considered the counts as the reading of the pulses( difference between the old and new value. Is it oke to consider that? Also the I considered the minute as the interval between the readings. So if I take for example a interval of 100 ms, do I need to make the interval 100*10*60 to make it one minute again? Or did I make a wrong approach here?

There are.two ways to go: A) measure the number of pulses in a fixed time. B) measure the time between a fixed number of pulses.

It sort of sounds like you are doiing (A). You could wait for a whole minute and count all the pulses in a minute. Then divide by 3 (pulses per motor revolutions) and divide by 52.734. (gear ratio.) That will give you the output rpm.

But a minute is a long time and a lot of pulses. If you only counted for a quarter (1/4) of a minute then multiply by 4 before dividing by 3 and 52.734. If you count for 100ms then that is a 100/1000/60th of a minute.

Method (B) is sometimes more suitable. Measuring the time between one pulse and the next can be very fast but has a lot of errors. In your case, if the 3 pulses in one revolution are not perfectly spaced then it will always measure incorrectly. You would probably choose to measure the time taken for 6 pulses or 30 or 300.