# Measuring RPM using Proximity Sensor

**URL:** <https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900>\
**Category:** Sensors\
**Created:** [July 23, 2023, 2:12pm UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900 "2023-07-23T14:12:01Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 23, 2023, 2:12pm UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/1 "2023-07-23T14:12:01Z")

</div>

Hello Community,

I am trying to make a project that should determine the rpm of a motor. To do that I am using a 200 rpm geared motor, proximity sensor and arduino clone. Suggest me a code to achieve this. I am currently using this code:-

```arduino
// Pin connected to the sensor output
#include "U8glib.h"
U8GLIB_SH1106_128X64 oled(U8G_I2C_OPT_NONE);
const int sensorPin = 2;

// Variables
volatile int rotationCount = 0;
volatile bool rotationDetected = false;
unsigned long prevTime = 0;
float rpm = 0.0;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Attach an interrupt to the sensor pin
  attachInterrupt(digitalPinToInterrupt(sensorPin), countRotation, FALLING);
}

void loop() {
   oled.firstPage();
  do {
    page1();
  } while (oled.nextPage() ); 
  if (rotationDetected) {
    unsigned long currTime = micros();
    unsigned long timeDiff = currTime - prevTime;

    // Calculate RPM
    rpm = 60000000.0 / timeDiff; // Convert to RPM
    rotationDetected = false;
    prevTime = currTime;
  }
}

void countRotation() {
  // Increment the rotation count
  rotationCount++;
  rotationDetected = true;
}
void page1(void) {
  oled.setFont(u8g_font_profont12);
  oled.setPrintPos(0, 10);
  oled.print("No of rotation : " );

  oled.setPrintPos(0, 25);
  oled.print(rotationCount);
  oled.setPrintPos(0, 40);
  oled.print("RPM of DC Motor :");
  oled.print(rpm);
}

```

But it has some error, it increases the rpm value as I increase the speed of motor but shows only some fixed values rather than the correct value.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [July 23, 2023, 2:25pm UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/2 "2023-07-23T14:25:18Z")

</div>

Many proximity sensors are slow, and might not even work for measuring RPM.

Please post a link to whatever it is you have, and explain how it is mounted and what it is supposed to detect.

---

<div class="post-metadata">

**Author:** ![johnerrington](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/johnerrington/32/340106_2.png) [@johnerrington](https://forum.arduino.cc/u/johnerrington)\
**Post date:** [July 23, 2023, 4:22pm UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/3 "2023-07-23T16:22:44Z")

</div>

> [@RSTAR](#):
>
> I am using a 200 rpm geared motor, proximity sensor and arduino clone

Post links to your components please, I'm too lazy to look them up myself.

---

<div class="post-metadata">

**Author:** ![jim-p](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jim-p/32/922840_2.png) [@jim-p](https://forum.arduino.cc/u/jim-p)\
**Post date:** [July 23, 2023, 4:41pm UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/4 "2023-07-23T16:41:05Z")

</div>

Does your sensor need a Pullup?  
Try adding this line  
to setup()

```arduino
pinMode(sensorPin, INPUT_PULLUP);

```

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 6:06am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/5 "2023-07-24T06:06:58Z")

</div>

Proximity Sensor Features/Specs:

- Model: JG-GI12-04N1
- Manufacturer: Jigo
- Material: Metal and plastic
- Operating Voltage: 6 ~ 36 VDC
- Output Type: NPN Normally Open
- Detection object: Metal Objects
- **Detection distance: 4 mm**
- Output Current: 300 mA
- Total Length of Sensor: 55mm
- Thread length: 35mm.
- Outer (Theard) Diameter: M12
- Polarity protection: yes
- Surge protection: yes
- Short circuit protection: yes
- High repeated positioning accuracy
- High switching frequency
- Wide voltage range
- Antivibration, dust, water, and oil prevention
- Reverse power protection, short circuit protection, directly connecting with PLC
- Can replace small switches and limit switches
- Working temperature(°C): -25 ~ +70, ±15%
- Cable Length: Approx 1.5 Meter
- Dimensions: 12 mm Screw Diamete

Motor Specs:-

- RPM - 200 (i hope, probably higher)
- Rated Voltage and Current - 12V and 10 amps

Microcontroller:-  
Arduino Uno Clone - works just like arduino uno

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 6:07am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/6 "2023-07-24T06:07:53Z")

</div>

I have attached external resistors... It works fine the rotation count works perfect, only the rpm measurement has the problem.

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 6:19am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/7 "2023-07-24T06:19:29Z")

</div>

Find the attached picture and link of the working video... Notice the rotation count is working fine but the rpm value is changing if fixed values. I changed the speed of the motor by gently adjusting the knob of pwm speed controller.

 ![WhatsApp Image 2023-07-24 at 11.26.30](https://europe1.discourse-cdn.com/arduino/original/4X/8/4/9/849bafbc1380074fbf1de5f29d237a8190c957d2.jpeg)

Working Video:- [https://drive.google.com/file/d/1dnwpmWMSZAZI9oEUdOoEYUdjk15OCpV-/view?usp=drive\_link](https://drive.google.com/file/d/1dnwpmWMSZAZI9oEUdOoEYUdjk15OCpV-/view?usp=drive_link)

---

<div class="post-metadata">

**Author:** ![jim-p](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jim-p/32/922840_2.png) [@jim-p](https://forum.arduino.cc/u/jim-p)\
**Post date:** [July 24, 2023, 7:42am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/8 "2023-07-24T07:42:50Z")

</div>

You are computing RPMs based on the time for 1 revolution. That number will vary a little for each revolution.

Try computing RPMs based on the time of 10 revolutions

I don't have a google account so I can't see your video.

---

<div class="post-metadata">

**Author:** ![JohnLincoln](https://avatars.discourse-cdn.com/v4/letter/j/7ba0ec/32.png) [@JohnLincoln](https://forum.arduino.cc/u/JohnLincoln)\
**Post date:** [July 24, 2023, 8:59am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/9 "2023-07-24T08:59:49Z")

</div>

> [@jim-p](#):
>
> I don't have a google account so I can't see your video.

Access Denied - I've got a google account, but I am asked to "request access".

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 9:13am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/10 "2023-07-24T09:13:13Z")

</div>

Try Now!

> **[VID\_20230724112140.mp4](https://drive.google.com/file/d/1dnwpmWMSZAZI9oEUdOoEYUdjk15OCpV-/view?usp=drive_link)**
>
> Google Drive file.

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 9:14am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/11 "2023-07-24T09:14:04Z")

</div>

Will try it.

---

<div class="post-metadata">

**Author:** ![jim-p](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jim-p/32/922840_2.png) [@jim-p](https://forum.arduino.cc/u/jim-p)\
**Post date:** [July 24, 2023, 9:27am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/12 "2023-07-24T09:27:17Z")

</div>

The fluctions are to be expected.  
What that shows is the the motor rotation isn't perfect.  
You need to take an average RPM for maybe 10 revolutions

---

<div class="post-metadata">

**Author:** ![RSTAR](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/rstar/32/986619_2.png) [@RSTAR](https://forum.arduino.cc/u/RSTAR)\
**Post date:** [July 24, 2023, 10:57am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/13 "2023-07-24T10:57:35Z")

</div>

I have made few changes to the code.

```arduino
#include "U8glib.h"
U8GLIB_SH1106_128X64 oled(U8G_I2C_OPT_NONE);
const int sensorPin = 2;

// Variables
volatile int rotationCount = 0;
volatile bool rotationDetected = false;
unsigned long prevTime = 0;
float rpm = 0.0;
float avgRpm = 0.0;
float avgrpm = 0.0;
int count = 0;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Attach an interrupt to the sensor pin
  attachInterrupt(digitalPinToInterrupt(sensorPin), countRotation, FALLING);
}

void loop() {
   oled.firstPage();
  do {
    page1();
  } while (oled.nextPage() ); 
  if (rotationDetected) {
    
    unsigned long currTime = micros();
    unsigned long timeDiff = currTime - prevTime;

    // Calculate RPM
    rpm = 60000000.0 / timeDiff; // Convert to RPM
    rotationDetected = false;
    prevTime = currTime;
    
    if (count < 10) {
      avgRpm += rpm;
      count++;
    } else {
      avgrpm = avgRpm/10;
      Serial.print("Average RPM: ");
      Serial.println(avgrpm);
      count = 0;
      avgRpm = 0.0;
    }
  }
}

void countRotation() {
  // Increment the rotation count
  rotationCount++;
  rotationDetected = true;
}
void page1(void) {
  oled.setFont(u8g_font_profont12);
  oled.setPrintPos(0, 10);
  oled.print("No of rotation : " );

  oled.setPrintPos(0, 25);
  oled.print(rotationCount);
  oled.setPrintPos(0, 40);
  oled.print("RPM of DC Motor :");
  oled.setPrintPos(0, 55);
  oled.print(avgrpm);
}

```

It does work to a certain limit, I could get rpm readings in much greater resolution compared to the one obtained using previous code. But I feel like it could still be optimized. Forum, any other suggestions?

---

<div class="post-metadata">

**Author:** ![johnerrington](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/johnerrington/32/340106_2.png) [@johnerrington](https://forum.arduino.cc/u/johnerrington)\
**Post date:** [July 25, 2023, 5:44am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/14 "2023-07-25T05:44:41Z")

</div>

You need the best estimate of the actual rpm. Now the RPM will not change instantaneously, so you can improve your estimate based on the history of the readings.  
To do this you can use a simple digital filter. An exponential moving average filter is described here

> **[skillbank: Experiments and projects with an Arduino microcontroller](https://skillbank.co.uk/arduino/switchbounce.htm#Bounce6)**
>
> Using digital inputs: Switch bounce and solutions to it

**new EMA =F \* new reading + (1 -F) \* last EMA**  
where F is a value normally between 0.1 and 0.3

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [January 21, 2024, 5:45am UTC](https://forum.arduino.cc/t/measuring-rpm-using-proximity-sensor/1150900/15 "2024-01-21T05:45:28Z")

</div>

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