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
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;
}
}
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)
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