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:
- How the IR slotted optical speed sensor (also called a photo interrupter or opto interrupter) works
- How to connect Arduino Mega to the IR slotted optical speed sensor
- How to program Arduino Mega to detect and count objects that pass through the slot
- How to program Arduino Mega to measure the speed (RPM) of a motor with an encoder disc and an external interrupt
- Which Arduino Mega pins can be used for interrupts, and why this matters for speed measurement
We suggest:
- Utilizing a rotary encoder if you are looking for knob input or need to know the turning direction.
- Utilizing an infrared obstacle avoidance sensor if you are looking to detect objects at a distance, not inside a narrow slot.

Hardware Preparation
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
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

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

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.

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:
- The next step is to configure the pin as a digital input in the setup() function:
- 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:
- 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:
- A short function is written to run on each pulse. It only adds one to the counter:
- 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:
- 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:
- Finally, the RPM is calculated from the pulses counted in one second:
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.
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.
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.
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.
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.