Jump to content

DC Motor with Encoder

From cognifront
Revision as of 11:58, 3 September 2026 by CogWikiEditor (talk | contribs) (Created page with "# Arduino L293D Motor Speed Measurement Using LM393 Encoder ## Overview This practical measures the **RPM (revolutions per minute)** of a geared DC motor using an **LM393 optical encoder module** and an **Arduino**. The encoder disc is mounted on the **gearbox output shaft** and contains **20 slots**. > **20 encoder pulses = 1 complete output-shaft revolution** The motor is driven using an **L293D motor driver**, while the encoder pulse signal is connected to Arduin...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
  1. Arduino L293D Motor Speed Measurement Using LM393 Encoder
    1. Overview

This practical measures the **RPM (revolutions per minute)** of a geared DC motor using an **LM393 optical encoder module** and an **Arduino**.

The encoder disc is mounted on the **gearbox output shaft** and contains **20 slots**.

> **20 encoder pulses = 1 complete output-shaft revolution**

The motor is driven using an **L293D motor driver**, while the encoder pulse signal is connected to Arduino digital pin **D2** and measured using an external interrupt.

---

    1. 1. Hardware Required

| Component | Quantity | | -------------------- | ----------: | | Arduino | 1 | | Geared DC Motor | 1 | | L293D Motor Driver | 1 | | LM393 Encoder Module | 1 | | Encoder Disc | 1 | | Jumper Wires | As required | | Motor Power Supply | 1 |

---

    1. 2. Pin Connections
      1. Encoder

| LM393 Encoder | Arduino | | ------------- | ------- | | DO | D2 | | VCC | 5V | | GND | GND |

The encoder's **DO (Digital Output)** generates a pulse whenever an encoder slot passes the sensor.

---

      1. L293D Motor Driver

| L293D | Arduino | | ----- | ------- | | EN1 | D5 | | IN1 | D7 | | IN2 | D8 |

The motor direction used in this program is:

```text IN1 = HIGH IN2 = LOW ```

Motor speed is controlled using PWM on **EN1 (D5)**.

---

    1. 3. System Operation

```text

       ┌─────────────────┐
       │   Arduino       │
       │                 │
       │ D5 ─────────────┼──── EN1
       │ D7 ─────────────┼──── IN1
       │ D8 ─────────────┼──── IN2
       │                 │
       │ D2 ◄────────────┼──── LM393 DO
       └────────┬────────┘
                │
                │ PWM / Direction
                ▼
         ┌─────────────┐
         │    L293D    │
         └──────┬──────┘
                │
                ▼
         ┌─────────────┐
         │  DC Motor   │
         │ + Gearbox   │
         └──────┬──────┘
                │
                ▼
         ┌─────────────┐
         │ Encoder     │
         │ 20 slots    │
         └──────┬──────┘
                │
                │ 20 pulses/rev
                ▼
            Arduino D2

```

---

  1. 4. RPM Measurement Principle

The encoder disc contains:

    • 20 slots per revolution**

Therefore:

```text 1 revolution = 20 pulses ```

The Arduino counts the number of encoder pulses received during a fixed measurement period.

In this program:

```text Measurement time = 1 second ```

The RPM is calculated using:

$$ RPM = \frac{Pulses \times 60} {Slots\ per\ revolution \times Measurement\ time\ (seconds)} $$

Since the measurement period is 1 second:

$$ RPM = \frac{Pulses \times 60}{20} $$

      1. Example

If the Arduino detects **100 pulses in 1 second**:

$$ RPM = \frac{100 \times 60}{20} $$

$$ RPM = 300 $$

Therefore:

> **100 pulses in one second = 300 RPM**

---

  1. 5. Encoder Interrupt

The encoder signal is connected to **D2**.

D2 is configured as an external interrupt:

```cpp attachInterrupt(

 digitalPinToInterrupt(ENCODER_PIN),
 encoderISR,
 RISING

); ```

Every **RISING edge** of the encoder signal calls:

```cpp encoderISR() ```

The pulse counter is then incremented:

```cpp pulseCount++; ```

This allows the Arduino to count encoder pulses without continuously checking the encoder inside `loop()`.

---

  1. 6. Pulse Filtering

The code includes a minimum pulse interval:

```cpp

  1. define MIN_PULSE_INTERVAL_US 2000

```

This corresponds to:

```text 2000 µs = 2 ms ```

If another pulse arrives within 2 ms of the previous accepted pulse, it is ignored.

This helps prevent unwanted multiple counts caused by noise or very fast signal transitions.

---

  1. 7. Motor Control

The motor speed is controlled using PWM:

```cpp int motorPWM = 150; ```

The PWM value is applied to EN1:

```cpp analogWrite(EN1, motorPWM); ```

The motor direction is set using:

```cpp digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); ```

Therefore:

```text EN1 → Speed IN1/IN2 → Direction ```

---

  1. 8. Complete Arduino Program

```cpp /*

 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
  • /
  1. define ENCODER_PIN 2
  1. define EN1 5
  2. define IN1 7
  3. define IN2 8
  1. define SLOTS_PER_REV 20
  2. define MIN_PULSE_INTERVAL_US 2000
  3. 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);
 // Motor direction
 digitalWrite(IN1, HIGH);
 digitalWrite(IN2, LOW);
 // Motor speed
 analogWrite(EN1, motorPWM);
 // Encoder interrupt
 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;
 }

} ```

---

  1. 9. Serial Monitor Output

Set the Serial Monitor baud rate to:

```text 115200 baud ```

Example output:

```text RPM Pulses 80,RPM 240.00 Pulses 82,RPM 246.00 Pulses 81,RPM 243.00 Pulses 83,RPM 249.00 ```

The first value is the number of encoder pulses detected during the measurement interval.

The second value is the calculated output-shaft speed.

---

  1. 10. Important Parameters

| Parameter | Value | Function | | ----------------------- | ------: | ----------------------------- | | `ENCODER_PIN` | 2 | Encoder signal input | | `EN1` | 5 | Motor PWM | | `IN1` | 7 | Motor direction | | `IN2` | 8 | Motor direction | | `SLOTS_PER_REV` | 20 | Encoder pulses per revolution | | `MIN_PULSE_INTERVAL_US` | 2000 µs | Pulse filtering | | `SAMPLE_TIME_MS` | 1000 ms | RPM measurement interval | | `motorPWM` | 150 | Motor PWM value |

---

    1. 11. Signal Flow

```text Motor rotates

     ↓

Gearbox output shaft rotates

     ↓

20-slot encoder disc rotates

     ↓

LM393 detects slots

     ↓

Digital pulses generated

     ↓

Arduino D2 interrupt

     ↓

Pulse counting

     ↓

1-second measurement

     ↓

RPM calculation

     ↓

Serial Monitor ```

---

    1. 12. Key Point

Because the encoder is mounted on the **gearbox output shaft**, the measured RPM represents the **actual output-shaft RPM**, not the motor's internal shaft RPM.

```text 20 pulses

   ↓

1 output revolution

   ↓

Pulse count

   ↓

RPM ```

    • Result:** Arduino controls the geared motor through the L293D and simultaneously measures its output-shaft speed using the LM393 encoder.