Measuring RPM from Laser Optical Sensor

Hello! :slight_smile:

I am currently working on a project in which I am using a ROLS-24 Laser Optical Sensor to count RPM values[0-24000] from a spinning motor. See sketch below

Here is the laser sensor datashet I am using.

I am currently measuring rpm by using the analog pin from the arduino and I am measuring the revolutions per second and then I multiply that by 60 to get the revolutions per minute. I am unsure if the calculations and the logic behind my code is correct and I need some guidance.
My rpm output values are always a factor of 60 (because I convert rps to rpm) and I am assuming that makes the reading inaccurate?

Can you please guide me to count the rpm correctly?

Here is the code I am using at the moment.

const int analogPin = A0;  // Change this to the desired analog pin
int sensorValue = 0;
int rev = 0;
float rpm = 0.0;
int deltaT = 1000; 
unsigned long lastTime = 0;

void setup() {
  Serial.begin(9600);  // Initialize serial communication
  sensorValue = analogRead(analogPin);
}

void loop() {
  // Read the analog value from the specified pin
  //sensorValue = analogRead(analogPin);

  // Print the analog value to the serial monitor
  //Serial.print("Analog Value: ");
  //Serial.println(sensorValue);

  // Check if the sensor value is zero and increment the counter
  if (sensorValue == 1023 && analogRead(analogPin) == 0) {
    Serial.print("Analog Value: ");
    Serial.println(sensorValue);
    rev++;
    Serial.print("Rev Count: ");
    Serial.println(rev);
    sensorValue = 0;
  }
  else if (analogRead(analogPin) != 0) {
    sensorValue = 1023;
  }

  // Check if one second has elapsed
  unsigned long currentTime = millis();
  if (currentTime - lastTime >= deltaT) {
    // Calculate RPM
    rpm = rev / (deltaT / 1000.0) * 60.0;
    // Print the results
    Serial.print("RPM: ");
    Serial.println(rpm);

    // Reset counters and update last time
    rev = 0;
    lastTime = currentTime;
  }
}

And here is the current output

In your printout, your sensor reading is always 1023,
In other words, he is not noticing any variation in luminosity.

Have you placed something that can reflect the light beam back to the sensor?

Place something that acts as a mirror on one side of the hexagonal nut that fixes the cutters.

Your diagram shows you have it connected to digital pin 6 not A0
The signal is digital NOT analog

Hello, yes I have a reflective tape and when I have the print analogread function outside of the if statement it prints out 0's as well

Hello Jim, my apologies I forgot to update my diagram but I can confirm the pin is connected to A0 and not pin 6. Are my calculations correct for reading rpm?

It should be connected to pin 6 and NOT A0
It is a digital signal NOT analog.
The signal is inverted, so you need to detect it when it goes LOW NOT HIGH

Your 5V pulses should be connected to an external interrupt pin and counted with one of the numerous Arduino tachometer programs. Search: "Arduino tachometer".

Hello Jim, thank you for that. I have connected it to an analog pin and I am trying to detect when the signal is LOW so then I can calculate the low (pulse) duration and then from that I have the pulse period. Then I calculate the frequency to find the rpm. Does this sound sensible? Here is the code I am using at the moment;

const int digitalPin = 2;  
float freq = 0.0;
float rpm = 0.0;

void setup() {
  Serial.begin(9600);
  pinMode(digitalPin, INPUT);
}

void loop() {
  // Read the digital pin
  int digitalValue = digitalRead(digitalPin);

  // Check if the digital reading is low
  if (digitalValue == LOW) {
    unsigned long startTime = millis();  // Record the start time when it becomes low

    // Wait until the pin goes high again
    while (digitalRead(digitalPin) == LOW) {
      // Do nothing, just wait for the pin to go high
    }

    unsigned long endTime = millis();  // Record the end time when it becomes high

    // Calculate and print the duration in seconds
    unsigned long duration = (endTime - startTime);
    Serial.print("Low state duration: ");
    Serial.print(duration);
    Serial.println(" milliseconds");

    // Calculate frequency and RPM
    freq = 1.0 / (duration / 1000.0);
    rpm = freq * 60.0;
    
    Serial.print("Frequency: ");
    Serial.print(freq);
    Serial.print(" Hz, RPM: ");
    Serial.println(rpm);
  }
}

But my results don't seem correct at all. I am using a reflective tape and I just passing from the laser sensor in a steady speed (should we around 40rpm)

Do you have any comments for the code?

You need to measure he time between pulses not the length of one pulse
Check when the pulse go from HIGH to LOW and do start = millis()
Then check when the pulse go from HIGH to LOW again and do stop = millis()
The period will be stop-start. So if stop-start = 1.5 seconds, then the RPM = (60/1.5)

Hello Jim, appreciate your support in this. How does this code look now?

const int digitalPin = 2;  // Change this to the desired digital pin
float freq = 0.0;
float rpm = 0.0;
unsigned long previousMillis = 0;
float startTime=0.0;
float endTime=0.0;
const unsigned long deltaT = 1000;  // Print RPM every 1000 milliseconds (1 second)

void setup() {
  Serial.begin(9600);
  pinMode(digitalPin, INPUT);
}

void loop() {
  // Read the digital pin
  int digitalValue = digitalRead(digitalPin);

  // Check if the digital reading is high
  if (digitalValue == HIGH) {
    unsigned long startTime = millis();  // Record the start time when it becomes high

    // Wait until the pin goes low again
    while (digitalRead(digitalPin) == HIGH) {
      // Do nothing, just wait for the pin to go low
    }

    unsigned long endTime = millis();  // Record the end time when it becomes low

    // Calculate the period in milliseconds
    unsigned long period = (endTime - startTime);

    // Calculate frequency and RPM
    freq = 1000.0 / period;
    rpm = freq * 60.0;

    // Print RPM every second
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= deltaT) {
      previousMillis = currentMillis;
      Serial.print("RPM: ");
      Serial.println(rpm);

    }
  }
}

Not quite right.
You are still measuring the length of a pulse and not the time between pulses.
You need to check when the pulse goes from High to Low.
See this tutorial on state change.
It is for pushbutons but will also work for the optical sensor

OR google Arduino measure RPM for examples.

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