Arduino Mega - IR Slotted Optical Speed Sensor

This tutorial instructs you how to use Arduino Mega to read the signal from an IR slotted optical speed sensor, and then turn that signal into an object count or a motor speed in RPM. In detail, we will learn:

We suggest:

Arduino Mega and IR slotted optical speed sensor

Hardware Preparation

1×Arduino MEGA
1×Alternatively, DIYables MEGA Development Board
1×USB 2.0 cable type A/B (for USB-A PC)
1×USB 2.0 cable type C/B (for USB-C PC)
1×IR Slotted Optical Speed Sensor
1×Jumper Wires
1×Optionally, Breadboard
1×Recommended: Screw Terminal Block Shield for Arduino Uno/Mega
1×Recommended: Sensors/Servo Expansion Shield for Arduino Mega
1×Recommended: Breadboard Shield for Arduino Mega
1×Recommended: Enclosure for Arduino Mega

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of IR Slotted Optical Speed Sensor

The IR slotted optical speed sensor is a small U-shaped module. One arm of the "U" holds an infrared LED. The other arm holds an NPN phototransistor. The two parts face each other across a 5.9 mm gap. This gap is the slot.

The sensor gives a simple digital signal. It tells Arduino Mega one thing only: is the slot clear, or is something inside it? Because of this, it is a good fit for counting, for limit and position detection, and, with a slotted encoder disc, for measuring speed.

IR Slotted Optical Speed Sensor
Sensor type Slot-type photoelectric (IR LED + NPN phototransistor)
Slot width 5.9 mm
Operating voltage 3.3V to 5V DC
Output Digital (TTL), LOW when blocked, HIGH when clear
Signal conditioning Built-in Schmitt trigger
Mounting M3 screw holes at both ends
Pins 3 (VCC, GND, OUT)

Common uses:

  • Measuring motor speed (RPM) with an encoder disc
  • Building a simple tachometer
  • Counting objects or pulses
  • Measuring distance by counting wheel turns
  • Speed feedback for robot wheels
  • Limit and position detection

The IR Slotted Optical Speed Sensor Pinout

IR Slotted Optical Speed Sensor Pinout

The module has three pins:

  • VCC pin: must be connected to VCC (5V on Arduino Mega)
  • GND pin: must be connected to GND (0V)
  • OUT pin: digital output, used to send the slot state from the sensor to Arduino Mega

※ NOTE THAT:

The arrangement of pins on a module may differ from one manufacturer to another, and even from one batch to another. It is essential to always refer to the labels printed on the module when using it. Take a close look!

How the IR Slotted Optical Speed Sensor Works

How IR Slotted Optical Speed Sensor Works

The IR LED shines a beam of infrared light across the slot, all the time. What happens next depends on what is in the slot:

  • Nothing in the slot: the IR light reaches the phototransistor, and the OUT pin is HIGH.
  • An opaque object in the slot (a piece of card, a tooth of an encoder disc): the light is blocked, and the OUT pin is LOW.

A Schmitt trigger is built into the module. It cleans up the signal, so the OUT pin gives a clean and stable 0 or 1 with no jitter. For this reason, there is no need for software debounce in the Arduino Mega code.

Keep these points in mind:

  • Transparent objects may not block IR light well. Use opaque objects.
  • Some modules from other makers have the opposite logic. If your sensor says "blocked" when the slot is empty, just swap LOW and HIGH in the first code. The RPM code counts one edge per slot, so it works either way.

Measuring Speed with an Encoder Disc

To measure speed, a round encoder disc with slots is fixed on the motor shaft or the wheel. The edge of the disc turns inside the slot of the sensor. Each tooth blocks the light for a short moment, and each hole lets it pass. So, the OUT pin makes one pulse per slot of the disc.

The common encoder disc for TT gear motors has 20 slots. This means:

  • 1 full turn = 20 pulses
  • Pulses in 1 second x 60 = pulses per minute
  • Pulses per minute / 20 = turns per minute (RPM)

Wiring Diagram

The wiring between Arduino Mega and the IR slotted optical speed sensor is shown in the image below.

The wiring diagram between Arduino Mega IR Slotted Optical Speed Sensor

This image is created using Fritzing. Click to enlarge image

IR Slotted Optical Speed Sensor Arduino Mega
VCC 5V
GND GND
OUT Pin 2

Why Pin 2 on Arduino Mega?

The first code only uses digitalRead(), so any digital pin of Arduino Mega would work. However, the RPM code uses an external interrupt, and not every pin of Arduino Mega supports this. The Arduino Mega 2560 has six external interrupt pins:

Arduino Mega Pin Other use of this pin
2 None (free)
3 None (free)
18 TX1 (Serial1)
19 RX1 (Serial1)
20 SDA (I2C)
21 SCL (I2C)

Pin 2 and pin 3 are the best choices, because they do not share a job with Serial1 or I2C. If your project also uses an I2C LCD or a Serial1 device, keep away from pins 18 to 21. We use pin 2 in both code examples, so you can wire the sensor once and run both programs.

※ NOTE THAT:

Arduino Mega works with 5V logic. Power the sensor from the 5V pin of Arduino Mega. The OUT pin then swings between 0V and 5V, which is exactly what the Mega input pins expect. No level shifter is needed.

How To Program For IR Slotted Optical Speed Sensor

No library is needed. The code uses only built-in Arduino functions.

Reading the Slot State

  • The first step is to specify the Arduino Mega pin that is connected to the OUT pin of the sensor:
const int SENSOR_PIN = 2;
  • The next step is to configure the pin as a digital input in the setup() function:
pinMode(SENSOR_PIN, INPUT);
  • After that, the state of the slot is read with digitalRead(). LOW means something is in the slot, and HIGH means the slot is clear:
int state = digitalRead(SENSOR_PIN);
  • To count each object only once, the new state is compared with the previous state. A change from HIGH to LOW means a new object has entered the slot.

Counting Pulses with an Interrupt

  • A counter variable is declared as volatile, because it is changed inside the interrupt function:
volatile unsigned long pulseCount = 0;
  • A short function is written to run on each pulse. It only adds one to the counter:
void countPulse() { pulseCount++; }
  • The function is attached to pin 2 in the setup() function. FALLING means the function runs each time the OUT pin goes from HIGH to LOW, that is, each time a tooth of the disc blocks the slot:
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), countPulse, FALLING);
  • Once every second, the counter is read and reset. Arduino Mega is an 8-bit board, so it reads a 32-bit variable in several steps. Turning interrupts off for a moment stops the value from changing in the middle of the read:
noInterrupts(); unsigned long pulses = pulseCount; pulseCount = 0; interrupts();
  • Finally, the RPM is calculated from the pulses counted in one second:
float rpm = pulses * 60.0 / SLOTS_PER_TURN;

Arduino Mega Code for Detecting Objects in the Slot

This code checks the OUT pin again and again in loop(). It prints a message only when the state changes, and it counts every time the slot is blocked.

/* * This Arduino Mega code was developed by newbiely.com * * This Arduino Mega code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-mega/arduino-mega-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 2; // Arduino Mega pin connected to the OUT pin of the speed sensor int lastState; // the previous state of the sensor int objectCount = 0; // how many times the slot was blocked void setup() { Serial.begin(9600); pinMode(SENSOR_PIN, INPUT); lastState = digitalRead(SENSOR_PIN); } void loop() { int state = digitalRead(SENSOR_PIN); if (state != lastState) { // the state has changed if (state == LOW) { // LOW = something is in the slot objectCount++; Serial.print("The slot is blocked - count: "); Serial.println(objectCount); } else { // HIGH = the slot is clear Serial.println("The slot is clear"); } lastState = state; } }

Detailed Instructions

  • If this is the first time you use Arduino Mega, see how to setup environment for Arduino Mega on Arduino IDE.
  • Wire the components as shown in the diagram.
  • Connect the Arduino Mega board to your computer using a USB cable.
  • Open Arduino IDE on your computer.
  • Select the Arduino Mega or Mega 2560 board and the correct COM port.
  • Copy the above code and paste it into Arduino IDE.
  • Click the Upload button on Arduino IDE to upload the code to Arduino Mega.
  • Open the Serial Monitor and set the baud rate to 9600.
  • Pass a piece of card or your finger through the slot a few times.
  • Check the result on the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Mega Or...
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Mega Or...' on 'COM15')
New Line
9600 baud
The slot is blocked - count: 1 The slot is clear The slot is blocked - count: 2 The slot is clear The slot is blocked - count: 3 The slot is clear
Ln 11, Col 1
Arduino Mega Or... on COM15
2

If the messages are the wrong way round ("blocked" when the slot is empty), your module uses the opposite logic. Swap LOW and HIGH in the code.

Arduino Mega Code for Measuring Motor Speed (RPM)

Pulses from a spinning disc are fast. If the code only checks the pin in loop(), it can miss some of them, for example while it is busy printing to the Serial Monitor. An interrupt fixes this. Arduino Mega stops what it is doing, adds one to the counter, and goes back, so no pulse is lost.

This code counts the pulses on interrupt pin 2. Every second, it calculates the RPM and prints both values. SLOTS_PER_TURN is set to 20. Change it to match the number of slots in your disc.

/* * This Arduino Mega code was developed by newbiely.com * * This Arduino Mega code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-mega/arduino-mega-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 2; // Arduino Mega pin connected to the OUT pin of the speed sensor const int SLOTS_PER_TURN = 20; // number of slots (holes) in the encoder disc volatile unsigned long pulseCount = 0; // changed inside the interrupt unsigned long lastTime = 0; // runs every time a tooth of the disc blocks the slot void countPulse() { pulseCount++; } void setup() { Serial.begin(9600); pinMode(SENSOR_PIN, INPUT); attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), countPulse, FALLING); } void loop() { if (millis() - lastTime >= 1000) { // every 1 second lastTime = millis(); noInterrupts(); // read and reset the counter safely unsigned long pulses = pulseCount; pulseCount = 0; interrupts(); float rpm = pulses * 60.0 / SLOTS_PER_TURN; // pulses per second -> turns per minute Serial.print("Pulses: "); Serial.print(pulses); Serial.print(" | Speed: "); Serial.print(rpm); Serial.println(" RPM"); } }

Detailed Instructions

  • Keep the same wiring as in the first example. The OUT pin must stay on pin 2 (or another interrupt pin: 3, 18, 19, 20 or 21; if you move it, change SENSOR_PIN in the code).
  • Fix the encoder disc on the motor shaft or the wheel. Make sure the teeth pass through the slot without touching the sensor.
  • Copy the above code and paste it into Arduino IDE.
  • Click the Upload button to upload the code to Arduino Mega.
  • Open the Serial Monitor at 9600 baud.
  • Spin the disc by hand, or power the motor. To drive the motor from Arduino Mega, see the Arduino Mega - DC Motor tutorial.
  • Check the result on the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Mega Or...
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Mega Or...' on 'COM15')
New Line
9600 baud
Pulses: 0 | Speed: 0.00 RPM Pulses: 98 | Speed: 294.00 RPM Pulses: 101 | Speed: 303.00 RPM Pulses: 100 | Speed: 300.00 RPM Pulses: 99 | Speed: 297.00 RPM Pulses: 0 | Speed: 0.00 RPM
Ln 11, Col 1
Arduino Mega Or... on COM15
2

In the output above, the motor spins at around 300 RPM. For example, 100 pulses in one second gives 100 x 60 / 20 = 300 RPM. The first and last lines show 0 RPM because the disc is not turning.

※ NOTE THAT:

  • Declare any variable that is changed inside the interrupt function as volatile.
  • Keep the interrupt function short. Do not call Serial.print() or delay() inside it.
  • Use FALLING so that each tooth of the disc gives exactly one count.

Additional Knowledge

Slotted Optical Sensor vs IR Obstacle Avoidance Sensor vs Rotary Encoder

These three parts all give pulses or digital signals to Arduino Mega, but each one is made for a different job.

IR Slotted Optical Speed Sensor IR Obstacle Avoidance Sensor Rotary Encoder
How it senses Object breaks a light beam inside a slot IR light reflects off an object in front Turning a knob or shaft
Detection area Only inside the 5.9 mm slot Open space in front of the sensor No object, it senses rotation
Output 1 digital signal 1 digital signal 2 signals (CLK, DT) + button
Turning direction No No Yes
Best for RPM, counting, position detection Robots avoiding walls, proximity alarms Menus, volume knobs, manual input

It is evident that the slotted optical sensor is more precise for counting fast pulses, because the object always passes through the same small, fixed gap. Choose the obstacle sensor when the object does not pass through a slot, and choose the rotary encoder when you also need to know the direction.

Choosing the Number of Slots per Turn

The number of slots in the disc sets the resolution of the measurement:

  • More slots: more pulses per turn, so slow speeds can be measured more smoothly. The code reads in steps of 60 / SLOTS_PER_TURN RPM. With 20 slots, each step is 3 RPM.
  • Fewer slots: fewer pulses per second, so less work for Arduino Mega at very high speeds.

A 20-slot disc is a good middle choice for small gear motors. If you use a different disc, count its slots and change SLOTS_PER_TURN in the code.

Measuring Distance from Wheel Turns

When the encoder disc is fixed on a robot wheel, the same pulses can also give the distance the wheel has rolled:

  • Turns = total pulses / SLOTS_PER_TURN
  • Wheel circumference = π x wheel diameter
  • Distance = turns x wheel circumference

For example, a 65 mm wheel has a circumference of about 204 mm. After 200 pulses with a 20-slot disc, the wheel has made 10 turns, so it has rolled about 2.04 meters.

Video Tutorial

Function References

Learn More

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!