DC Motor with Encoder
Arduino Motor RPM Measurement Using LM393 Encoder
| Motor RPM Measurement | |
|---|---|
| Controller | Arduino |
| Motor Driver | L293D |
| Encoder | LM393 |
| Encoder Disc | 20 slots |
| Encoder Position | Gearbox output shaft |
| Output | RPM |
Arduino Motor RPM Measurement is a simple motor-control and speed-measurement setup using an Arduino, L293D motor driver and LM393 optical encoder.
The 20-slot encoder disc is mounted on the gearbox output shaft. Therefore:
20 pulses = 1 output-shaft revolution
The Arduino controls the motor and counts encoder pulses for one second to calculate the output-shaft RPM.
Connections
| Device | Pin | Arduino | Function |
|---|---|---|---|
| LM393 | DO | D2 | Encoder pulse |
| LM393 | VCC | 5V | Power |
| LM393 | GND | GND | Ground |
| Motor | EN1 | D5 | Motor PWM |
| Motor | IN1 | D7 | Motor direction |
| Motor | IN2 | D8 | Motor direction |
| Motor | 5V | External 5 V | Motor Positive |
| Motor | GND | Arduino GND | Motor GND |
| External GND | GND | Arduino GND | Common Groudings |
Motor direction
IN1 = HIGH
IN2 = LOW
Encoder
The LM393 produces a digital pulse whenever a slot on the encoder disc passes the sensor.
20 slots ➡️ 20 pulses ➡️ 1 output-shaft revolution

Working
The motor is driven through the L293D. The encoder disc rotates together with the gearbox output shaft.
The LM393 detects the slots and produces digital pulses. These pulses are connected to Arduino D2.
D2 uses an external interrupt to count the pulses.
Every 1 second, the Arduino:
- Reads the number of encoder pulses.
- Resets the pulse counter.
- Converts the pulse count into RPM.
- Displays the result on the Serial Monitor.
The RPM calculation is:
RPM = (Pulses × 60) / 20
Arduino Code
/*
Encoder disc:
20 slots
Encoder location:
Gearbox OUTPUT shaft
Therefore:
20 pulses = 1 output-shaft revolution
Encoder:
LM393 DO -> Arduino D2
Motor driver:
L293D
EN1 -> D5
IN1 -> D7
IN2 -> D8
*/
#define ENCODER_PIN 2
#define EN1 5
#define IN1 7
#define IN2 8
#define SLOTS_PER_REV 20
#define MIN_PULSE_INTERVAL_US 2000
#define SAMPLE_TIME_MS 1000
volatile unsigned long pulseCount = 0;
volatile unsigned long lastPulseTime = 0;
int motorPWM = 150;
// ENCODER INTERRUPT
void encoderISR()
{
unsigned long currentTime = micros();
if ((currentTime - lastPulseTime) >= MIN_PULSE_INTERVAL_US)
{
pulseCount++;
lastPulseTime = currentTime;
}
}
void setup()
{
Serial.begin(115200);
pinMode(ENCODER_PIN, INPUT);
pinMode(EN1, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
analogWrite(EN1, motorPWM);
attachInterrupt(
digitalPinToInterrupt(ENCODER_PIN),
encoderISR,
RISING
);
Serial.println("RPM");
}
void loop()
{
static unsigned long lastMeasurement = 0;
unsigned long currentTime = millis();
if (currentTime - lastMeasurement >= SAMPLE_TIME_MS)
{
unsigned long pulses;
noInterrupts();
pulses = pulseCount;
pulseCount = 0;
interrupts();
float rpm =
(pulses * 60.0) /
(SLOTS_PER_REV * (SAMPLE_TIME_MS / 1000.0));
Serial.print ("Pulses ");
Serial.print (pulses);
Serial.print (",RPM ");
Serial.println (rpm);
lastMeasurement = currentTime;
}
}
Observation
The Serial Monitor is set to 115200 baud. And observe the speed of the motor
Result: The Arduino successfully controls the geared motor and measures the gearbox output-shaft RPM using the 20-slot LM393 encoder.