ESP32 S3 - IR Slotted Optical Speed Sensor

This guide walks you through using the ESP32 S3 with an IR slotted optical speed sensor to count objects and to measure how fast a motor turns. Whether you're building a small tachometer for a robot wheel or just getting started with sensors, this step-by-step tutorial will get you up and running.

What you'll build in this tutorial:

  1. What the IR slotted optical speed sensor (photo interrupter) is and how it works
  2. How to connect the sensor to the ESP32 S3 safely at 3.3V
  3. A sketch that counts every object that passes through the slot
  4. A sketch that measures motor speed in RPM using an encoder disc and an interrupt
ESP32 S3 - IR Slotted Optical Speed Sensor

Hardware Preparation

1×ESP32 S3 WROOM N16R8
1×Alternatively, ESP32 S3 SuperMini Dev Module
1×Alternatively, ESP32 S3 Uno-form Board
1×Alternatively, ESP32 S3 Camera Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×IR Slotted Optical Speed Sensor
1×Jumper Wires
1×Optionally, Breadboard
1×Optionally, DC Power Jack
1×Recommended: Screw Terminal Expansion Board for ESP32 S3
1×Recommended: Breakout Expansion Board for ESP32 S3
1×Recommended: Power Splitter for ESP32 S3

Or you can buy the following kits:

1×DIYables ESP32 S3 Starter Kit (ESP32 S3 included)
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 part. Some people call it a photo interrupter, an opto interrupter, or an IR slot sensor. One arm holds an infrared LED. The other arm holds an NPN phototransistor. The two face each other across a narrow gap, and the sensor tells the ESP32 S3 whether something is inside that gap.

Key Specifications

Item Value
Sensor type slot-type photoelectric (IR LED + NPN phototransistor)
Slot width 5.9 mm
Operating voltage 3.3V – 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)

IR Slotted Optical Speed Sensor Pinout

The module has only three pins, so the wiring is short and easy.

  1. VCC — power input, 3.3V to 5V (use 3.3V on the ESP32 S3)
  2. GND — ground (0V)
  3. OUT — digital signal that goes to an ESP32 S3 input pin
IR Slotted Optical Speed Sensor Pinout

※ NOTE THAT:

The pin order can change from one batch to another. Always read the labels printed on your module before you connect the wires.

How the Slotted Optical Sensor Works

Think of the slot as a tiny light gate. When the gap is empty, the infrared light crosses it and reaches the phototransistor, so the OUT pin is HIGH. When an opaque object enters the gap, such as a piece of card or one tooth of an encoder disc, it blocks the light and the OUT pin drops to LOW.

A built-in Schmitt trigger cleans up the signal before it leaves the module. Because of this, the ESP32 S3 gets a sharp 0 or 1 with no jitter, and you do not need any debounce code. One thing to keep in mind: clear plastic or glass may let infrared light pass, so use opaque objects for reliable results.

How the IR slotted optical speed sensor works

Modules from some other makers use the opposite logic. If your module reports "blocked" while the slot is empty, simply swap LOW and HIGH in the first sketch. The RPM sketch counts one edge per slot, so it works with either type.

Wiring Diagram

The sensor needs just three jumper wires to the ESP32 S3. Run VCC to the 3.3V pin, GND to any GND pin, and OUT to GPIO4, which both sketches in this guide use.

The wiring diagram between ESP32 S3 IR slotted optical speed sensor

This image is created using Fritzing. Click to enlarge image

Speed Sensor Pin ESP32 S3 Pin
VCC 3.3V
GND GND
OUT GPIO4

Safety Notes

The OUT pin swings all the way up to whatever voltage you feed into VCC. The ESP32 S3 GPIO pins are made for 3.3V, so power the sensor from the 3.3V pin and not from 5V. This keeps the OUT signal at a level the board can read without harm. Also check the labels on the module once more before you plug in the USB cable, because a swapped VCC and GND can damage the sensor.

How To Program For IR Slotted Optical Speed Sensor

The first sketch uses digitalRead() to check the OUT pin again and again. It remembers the last state and prints a message only when the state changes, and it adds one to a counter each time the slot becomes blocked.

The second sketch is made for speed. Disc teeth pass very fast, so checking the pin inside loop() could miss some of them. Instead, the sketch calls attachInterrupt() on the FALLING edge, which fires once each time a tooth blocks the light. The interrupt function is marked with IRAM_ATTR, as the ESP32 S3 requires, and it only adds one to a volatile counter. Once per second, loop() reads the counter, resets it, and works out the speed.

The speed formula is simple. A standard encoder disc has 20 slots, so one full turn gives 20 pulses. The pulses counted in one second, times 60, gives pulses per minute. Divide that by 20 and you get turns per minute (RPM):

float rpm = pulses * 60.0 / SLOTS_PER_TURN;

ESP32 S3 Code - Count Objects in the Slot

This sketch watches GPIO4 and prints a line each time the slot is blocked or becomes clear again. Every new block raises the count by one, so you can use it as a simple object counter.

/* * This ESP32 S3 code was developed by newbiely.com * * This ESP32 S3 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3/esp32-s3-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 4; // ESP32 S3 GPIO4 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

  1. New to ESP32 S3? Complete our Getting Started with ESP32 S3 guide first.
  2. Wire the speed sensor to the ESP32 S3 as shown in the wiring diagram.
  3. Plug the ESP32 S3 into your computer with the USB Type-C cable.
  4. Open the Arduino IDE and pick ESP32S3 Dev Module under Tools > Board, then choose the right COM port.
  5. Copy the code above and paste it into a new sketch.
  6. Click the Upload button to send the code to the board.
  7. Open the Serial Monitor and set the baud rate to 9600.
  8. Pass a piece of card or your finger through the slot a few times.
  9. Watch the messages and the count in the Serial Monitor.
  10. Pro Tip: Fix the sensor with M3 screws through the holes at each end. A sensor that does not move gives steady counts, even when objects pass quickly.

Serial Monitor Output

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' 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
ESP32S3 Dev Module on COM15
2

ESP32 S3 Code - Measure Motor Speed (RPM)

Now let's turn the sensor into a tachometer. Mount an encoder disc on the motor shaft or wheel so that its teeth pass through the slot without touching the sensor. Each tooth gives one pulse, and the sketch prints the pulse count and the speed once every second.

/* * This ESP32 S3 code was developed by newbiely.com * * This ESP32 S3 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3/esp32-s3-ir-slotted-optical-speed-sensor */ const int SENSOR_PIN = 4; // ESP32 S3 GPIO4 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 IRAM_ATTR 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(); unsigned long pulses = pulseCount; // read and reset the counter pulseCount = 0; 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

  1. New to ESP32 S3? Complete our Getting Started with ESP32 S3 guide first.
  2. Keep the same wiring as in the first example.
  3. Fix the encoder disc on the shaft so its teeth pass through the slot.
  4. Copy the RPM code above into the Arduino IDE and click Upload.
  5. Open the Serial Monitor at 9600 baud.
  6. Spin the disc by hand, or power the motor. To drive the motor, see the ESP32 S3 DC motor tutorial.
  7. Read the pulses and the RPM value that appear every second.
  8. Pro Tip: If your disc does not have 20 slots, count them and change the SLOTS_PER_TURN value in the code. Otherwise the RPM will be wrong.

Serial Monitor Output

The output below shows a motor spinning at about 300 RPM, then stopping.

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' 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
ESP32S3 Dev Module on COM15
2

If you want to know how far a wheel has traveled, multiply the number of turns by the wheel's circumference (π × diameter).

Application Ideas

The speed sensor gives a clean pulse for every event, so it fits many measuring and counting projects on the ESP32 S3.

  1. Motor Tachometer: Show the RPM of a DC motor and check how speed changes with load.
  2. Robot Wheel Feedback: Measure the speed of each wheel so a robot can drive in a straight line.
  3. Distance Meter: Count wheel turns and convert them to distance traveled.
  4. Item Counter: Count small parts that drop through the slot on a sorting line.
  5. Limit and Position Detection: Put a thin flag on a moving part and stop it when the flag enters the slot.
  6. Fan Speed Monitor: Track how fast a cooling fan spins and warn when it slows down.

For objects that are farther away and do not fit in a slot, the ESP32 S3 obstacle sensor tutorial is a better choice. To read a hand-turned knob with direction, see the ESP32 S3 rotary encoder tutorial.

Challenge Yourself

Try these tasks to build on what you learned in this guide.

  1. Beginner: Turn on an LED while the slot is blocked and turn it off when the slot is clear.
  2. Intermediate: Add the distance calculation to the RPM sketch and print the total distance in centimeters.
  3. Advanced: Use the measured RPM to keep a DC motor at a fixed speed by adjusting its PWM value up or down.

Video Tutorial

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!