Arduino Nano - IR Slotted Optical Speed Sensor
This tutorial instructs you how to use Arduino Nano to read the IR slotted optical speed sensor, a small U-shaped part that tells the board when something passes through its gap. In detail, we will learn:
- How to connect Arduino Nano to the IR slotted optical speed sensor on a breadboard
- How to program Arduino Nano to count each object that goes through the slot
- How to program Arduino Nano to work out the speed of a motor in RPM, using an encoder disc and the D2 interrupt pin
We suggest:
- Utilizing a rotary encoder if you are building a hand-turned knob, or if your project must know which way something turns.
- Utilizing an infrared obstacle avoidance sensor if the object you want to find is out in the open and will not pass through a small gap.

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
People call this part by many names: slot sensor, photo interrupter, opto interrupter, or U-shaped IR sensor. All of them mean the same thing. It is a light gate. A light shines from one side of a gap to the other side, and the module reports whether that light gets through.
How It Detects an Object

Look at the two arms of the "U". The first arm has an infrared LED inside. The second arm has an NPN phototransistor inside. They look at each other across a gap of 5.9 mm.
There are only two cases:
- The gap is empty. The phototransistor sees the infrared light, so the module sets OUT to HIGH.
- Something opaque sits in the gap, such as a strip of card or one tooth of an encoder disc. The light cannot pass, so the module sets OUT to LOW.
The module also has a Schmitt trigger on board. Its job is to turn the raw light level into a sharp 0 or 1. Because the edges are already clean, your Arduino Nano sketch does not need any debounce code.
Two things to remember:
- Clear plastic or glass can let infrared light through. Test with something you cannot see through.
- A few modules from other brands work the other way round (LOW when empty). If yours does, swap LOW and HIGH in the first sketch. The RPM sketch counts one edge for each slot, so it gives the right answer with both kinds.
Specifications
| 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) |
You will find this sensor in projects like these: a tachometer for a small motor, wheel speed feedback on a robot car, a counter for parts on a belt, an end-stop that tells a moving part it has reached its limit, and a simple odometer that counts how many times a wheel has turned.
The IR Slotted Optical Speed Sensor Pinout

Only three pins come out of the module:
- VCC pin: must be connected to the 5V pin of Arduino Nano
- GND pin: must be connected to GND (0V)
- OUT pin: the digital signal line; it must go to an input pin of Arduino Nano (D2 in this tutorial)
※ NOTE THAT:
The arrangement of pins on a module may differ from one manufacturer to another, and the order can even change between two batches of the same product. It is essential to always refer to the labels printed on the module when using it. Take a close look!
Turning Pulses into Speed
On its own, the sensor only sees "something" or "nothing". To read speed, we add an encoder disc. This is a thin wheel with holes around its edge. It sits on the motor shaft, and its edge spins through the gap. Every tooth cuts the beam once, so the OUT pin gives one LOW pulse per tooth.
The disc that comes with most TT gear motors has 20 slots. So 20 pulses mean one full turn. If Arduino Nano counts the pulses for one second, the math is:
RPM = (pulses in one second x 60) / 20
The "x 60" changes seconds into minutes. The "/ 20" changes pulses into turns.
Wiring Diagram
Place the Arduino Nano across the middle of the breadboard, then run three jumper wires from the sensor: VCC to 5V, GND to GND, and OUT to D2, as the picture below shows.

This image is created using Fritzing. Click to enlarge image
See The best way to supply power to the Arduino Nano and other components.
The Nano is a 5V board, so we take power from its 5V pin. The OUT signal then moves between 0V and 5V, and that matches the Nano input pins exactly. You do not need a level shifter or any extra resistor.
How To Program For IR Slotted Optical Speed Sensor
You do not need to install a library. Both sketches use only functions that are already part of the Arduino core.
Part 1: checking the slot with digitalRead()
- The first step is to specify the Arduino Nano pin that is wired to OUT:
- Inside setup(), that pin is set as an input. The module drives the line by itself, so a plain INPUT is enough:
- Inside loop(), the pin is read over and over. A LOW value tells us the beam is broken:
- The sketch keeps the last value in lastState. It prints and counts only when the new value is not the same as the old one, so one object gives one count, even if it stays in the gap for a long time.
Part 2: catching fast pulses with an interrupt
The Arduino Nano has only two pins that can trigger an external interrupt: D2 and D3. This is why the sensor goes to D2. Any other digital pin works for Part 1, but not for Part 2.
- The pulse counter is declared with the volatile keyword. This tells the compiler that the value can change at any moment, from outside the normal flow of loop():
- The interrupt routine does one small job. It adds 1 to the counter and returns:
- In setup(), the routine is linked to D2. The FALLING option starts it at the moment OUT drops from HIGH to LOW. That is the moment a tooth enters the gap, so each tooth is counted once:
- Once per second, the sketch copies the counter and sets it back to zero. The ATmega328P chip on the Nano handles 8 bits at a time, so copying a 4-byte number takes several steps. noInterrupts() and interrupts() make sure a new pulse cannot change the number halfway through the copy:
- The last step uses the formula from above:
Arduino Nano Code for Counting Objects in the Slot
The sketch below polls D2 in loop(). Each time a new object breaks the beam, it adds one to the count and prints it. When the gap is empty again, it prints a short message.
Detailed Instructions
- If this is the first time you use Arduino Nano, see how to set up the environment for Arduino Nano in Arduino IDE.
- Wire the components as shown in the diagram.
- Connect the Arduino Nano board to your computer using a USB cable.
- Open Arduino IDE on your computer.
- Choose the Arduino Nano board and the COM port it is using. If the upload fails later, try ATmega328P (Old Bootloader) in the Processor menu.
- Paste the code above into a new sketch.
- Press the Upload button and wait for the "Done uploading" message.
- Open the Serial Monitor and pick 9600 baud.
- Slide a piece of card, or a finger, into the gap and take it out again. Do this three times.
- Watch the messages on the Serial Monitor.
Do you see "blocked" while the gap is empty? Then your module has reversed logic. Swap the LOW and HIGH checks in the code and upload again.
Arduino Nano Code for Measuring Motor Speed (RPM)
A motor with a 20-slot disc can make hundreds of pulses per second. Polling may miss some of them, for example while Serial.print() is busy sending text. With an interrupt, the Nano pauses its current work for a very short time, counts the pulse, and then goes on. Every tooth gets counted.
The sketch prints the number of pulses and the RPM once per second. The constant SLOTS_PER_TURN is 20. If your disc has a different number of holes, count them and put that number in the code.
Detailed Instructions
- Do not change the wiring from the first sketch. OUT must stay on D2. D3 is the only other choice on the Nano; if you use it, set SENSOR_PIN to 3.
- Mount the encoder disc on the motor shaft or wheel. Line it up so the teeth run through the middle of the gap and do not rub the plastic.
- Paste the RPM code into Arduino IDE and upload it to the Nano.
- Open the Serial Monitor at 9600 baud.
- Turn the disc with your hand, or switch on the motor. The Arduino Nano - DC Motor tutorial shows how to drive a motor from the Nano.
- Read the speed on the Serial Monitor.
Here the motor turns at about 300 RPM. Take the line with 98 pulses: 98 x 60 = 5880 pulses per minute, and 5880 / 20 = 294 RPM. The 0 lines at the top and bottom were printed before the motor started and after it stopped.
Good habits for interrupt code on the Nano:
- Mark every variable that the interrupt routine changes as volatile.
- Keep the routine tiny. Never put delay() or Serial.print() inside it.
- Stay with FALLING. CHANGE would fire twice per tooth and double your RPM.
Additional Knowledge
Which Sensor Should You Pick?
A slot sensor, an IR obstacle sensor and a rotary encoder can all give pulses to Arduino Nano. Still, each one solves a different problem. Ask yourself these questions:
- Does the object pass through a small, fixed gap (a disc tooth, a flag on a moving part)? Pick the IR slotted optical speed sensor. It gives one clean digital signal for each pass.
- Is the object somewhere in front of the sensor, not inside a gap (a wall, a hand, a box on a table)? Pick the IR obstacle avoidance sensor. It sees reflected light in open space.
- Does a person turn a knob, and does the code need the direction (left or right)? Pick the rotary encoder. It has two outputs (CLK and DT) and a push button.
It is evident that the slotted sensor gives the most reliable count for fast spinning parts, since the target always crosses the same 5.9 mm gap at the same place. Its only limit is that it cannot tell the direction of rotation.
Two Wheels, Two Sensors
A small robot car often has two driven wheels. The Nano has exactly two interrupt pins, so one sensor can go on D2 and a second sensor on D3. Each sensor then needs its own counter and its own interrupt routine. Keep this in mind before you plan the rest of the robot: if D2 and D3 are already used by other parts, move those parts to other pins, because no other Nano pin can do this job.
Troubleshooting
| Problem | What to check |
|---|---|
| Count never changes | Check that OUT goes to D2 and VCC goes to 5V. Read the pin labels on your module, because the order is not the same on every batch. |
| "Blocked" when the gap is empty | Your module uses reversed logic. Swap LOW and HIGH in the first sketch. |
| RPM is always 0 | The disc teeth may not reach the gap. Move the sensor so the teeth pass through the middle of the slot. |
| RPM jumps up and down | Make sure the disc is tight on the shaft and does not wobble or touch the sensor. |
| RPM is too high or too low | SLOTS_PER_TURN does not match your disc. Count the holes and fix the constant. |