Jump to content

DC Motor with Encoder

From cognifront


Arduino Motor Speed Measurement
Controller Arduino
Motor driver L293D
Encoder LM393 optical encoder
Encoder disc 20 slots
Encoder position Gearbox output shaft
Encoder output Digital (DO)
Encoder input Arduino D2
Motor PWM Arduino D5
Motor direction Arduino D7, D8
Measurement period 1 second
Output RPM

Arduino Motor Speed Measurement Using L293D and LM393 Encoder is an embedded motor-control system that controls a geared DC motor using an L293D motor driver and measures the rotational speed of the gearbox output shaft using an LM393 optical encoder.

The encoder disc contains 20 slots. Because the encoder is mounted on the gearbox output shaft, 20 encoder pulses correspond to one complete output-shaft revolution.

Objective

  • Control a geared DC motor using an L293D motor driver.
  • Measure the rotational speed of the gearbox output shaft.
  • Count encoder pulses using an Arduino external interrupt.
  • Calculate and display the speed in revolutions per minute (RPM).

Hardware

Component Quantity
Arduino 1
Geared DC motor 1
L293D motor driver 1
LM393 optical encoder module 1
20-slot encoder disc 1
Jumper wires As required
Motor power supply 1

Pin connections

Encoder

LM393 Arduino Purpose
DO D2 Encoder pulse signal
VCC 5V Power
GND GND Ground

L293D

L293D Arduino Purpose
EN1 D5 PWM speed control
IN1 D7 Motor direction
IN2 D8 Motor direction

The motor direction used by the program is:

<syntaxhighlight lang="cpp"> IN1 = HIGH IN2 = LOW </syntaxhighlight>

The PWM signal applied to EN1 controls the motor speed.

System diagram

<syntaxhighlight>

                        ARDUINO
                   ┌────────────────┐
                   │                │
            D5 ────┼───────────────►│ EN1
            D7 ────┼───────────────►│ IN1
            D8 ────┼───────────────►│ IN2
                   │                │
            D2 ◄───┼────────────────┤ LM393 DO
                   │                │
                   └────────────────┘
                            │
                            │ PWM + Direction
                            ▼
                      ┌───────────┐
                      │   L293D   │
                      └─────┬─────┘
                            │
                            ▼
                      ┌───────────┐
                      │ DC MOTOR  │
                      │ + GEARBOX │
                      └─────┬─────┘
                            │
                            ▼
                      ┌───────────┐
                      │  ENCODER  │
                      │ 20 SLOTS  │
                      └─────┬─────┘
                            │
                            │ 20 pulses / revolution
                            ▼
                        Arduino D2

</syntaxhighlight>

Working

The geared motor rotates the gearbox output shaft. The encoder disc is attached to this output shaft.

As the disc rotates, its slots pass the LM393 optical sensor. The sensor generates digital pulses at its DO output.

The Arduino receives these pulses on D2 using an external interrupt.

The basic sequence is:

<syntaxhighlight> Motor rotation

     ↓

Gearbox output shaft

     ↓

20-slot encoder disc

     ↓

LM393 optical sensor

     ↓

Digital pulses

     ↓

Arduino D2 interrupt

     ↓

Pulse counting

     ↓

RPM calculation

     ↓

Serial Monitor </syntaxhighlight>

Encoder resolution

The encoder disc has:

<math> 20\ slots/revolution </math>

Therefore:

<math> 20\ pulses = 1\ revolution </math>

Since the encoder is located on the gearbox output shaft, the calculated RPM represents the gearbox output-shaft speed.

RPM calculation

The program measures the number of encoder pulses received during a fixed time interval.

The general equation is:

<math> RPM = \frac{Pulses \times 60} {Slots\ per\ revolution \times Measurement\ time\ (seconds)} </math>

For this implementation:

<math> Slots\ per\ revolution = 20 </math>

and:

<math> Measurement\ time = 1\ second </math>

Therefore:

<math> RPM = \frac{Pulses \times 60}{20} </math>

Example

If the Arduino detects 100 pulses during one second:

<math> RPM = \frac{100 \times 60}{20} </math>

<math> RPM = 300 </math>

Thus, 100 pulses per second correspond to an output-shaft speed of 300 RPM.

Interrupt-based pulse counting

The encoder is connected to Arduino D2 and configured to generate an interrupt on a rising edge.

<syntaxhighlight lang="cpp"> attachInterrupt(

 digitalPinToInterrupt(ENCODER_PIN),
 encoderISR,
 RISING

); </syntaxhighlight>

When a rising edge is detected, the interrupt service routine is executed.

<syntaxhighlight lang="cpp"> void encoderISR() {

 unsigned long currentTime = micros();
 if ((currentTime - lastPulseTime) >= MIN_PULSE_INTERVAL_US)
 {
   pulseCount++;
   lastPulseTime = currentTime;
 }

} </syntaxhighlight>

Each accepted pulse increments the variable pulseCount.

Pulse filtering

A minimum pulse interval is defined as:

<syntaxhighlight lang="cpp">

  1. define MIN_PULSE_INTERVAL_US 2000

</syntaxhighlight>

This corresponds to:

<math> 2000\ \mu s = 2\ ms </math>

If another pulse is detected before this interval has elapsed, it is ignored.

Motor control

The motor is controlled through the L293D.

The PWM value is defined as:

<syntaxhighlight lang="cpp"> int motorPWM = 150; </syntaxhighlight>

The PWM signal is applied to EN1:

<syntaxhighlight lang="cpp"> analogWrite(EN1, motorPWM); </syntaxhighlight>

The motor direction is set using IN1 and IN2:

<syntaxhighlight lang="cpp"> digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); </syntaxhighlight>

Signal Arduino pin Function
EN1 D5 Motor speed
IN1 D7 Direction
IN2 D8 Direction

/*

 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);
 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;
 }

}

Serial Monitor

The Serial Monitor should be configured for 115200 baud.

Example output:

<syntaxhighlight> RPM Pulses 80,RPM 240.00 Pulses 82,RPM 246.00 Pulses 81,RPM 243.00 Pulses 83,RPM 249.00 </syntaxhighlight>

Output Meaning
Pulses 80 80 encoder pulses detected during the measurement interval
RPM 240.00 Calculated gearbox output-shaft speed

Program parameters

Parameter Value Description
ENCODER_PIN 2 Encoder input
EN1 5 Motor PWM output
IN1 7 Motor direction
IN2 8 Motor direction
SLOTS_PER_REV 20 Encoder slots per revolution
MIN_PULSE_INTERVAL_US 2000 Minimum pulse interval
SAMPLE_TIME_MS 1000 Measurement interval
motorPWM 150 PWM value

Result

The system controls a geared DC motor using the L293D and measures the rotational speed of its gearbox output shaft using a 20-slot LM393 encoder.

The encoder provides:

<math> 20\ pulses = 1\ output\ revolution </math>

The Arduino counts the encoder pulses for one second and converts the count into RPM.

Measured output: RPM of the gearbox output shaft.