Jump to content

DC Motor with Encoder: Difference between revisions

From cognifront
CogWikiEditor (talk | contribs)
CogWikiEditor (talk | contribs)
No edit summary
Line 1: Line 1:
{{DISPLAYTITLE:Arduino Motor Speed Measurement Using L293D and LM393 Encoder}}
```wiki
{{DISPLAYTITLE:Arduino Motor RPM Measurement Using LM393 Encoder}}


{| class="wikitable infobox" style="float:right; margin:0 0 1em 1em; width:300px;"
{| class="wikitable" style="float:right; margin-left:20px; width:300px;"
! colspan="2" style="font-size:125%;" | Arduino Motor Speed Measurement
! colspan="2" style="font-size:120%;" | Motor RPM Measurement
|-
|-
! Controller
! Controller
| Arduino
| Arduino
|-
|-
! Motor driver
! Motor Driver
| L293D
| L293D
|-
|-
! Encoder
! Encoder
| LM393 optical encoder
| LM393
|-
|-
! Encoder disc
! Encoder Disc
| 20 slots
| 20 slots
|-
|-
! Encoder position
! Encoder Position
| Gearbox output shaft
| 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
! Output
Line 38: Line 24:
|}
|}


'''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.
'''Arduino Motor RPM Measurement''' is a simple motor-control and speed-measurement setup using an Arduino, L293D motor driver and 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'''.
The '''20-slot encoder disc''' is mounted on the '''gearbox output shaft'''. Therefore:


__TOC__
<center>
'''20 pulses = 1 output-shaft revolution'''
</center>


== Objective ==
The Arduino controls the motor and counts encoder pulses for one second to calculate the output-shaft RPM.


* Control a geared DC motor using an L293D motor driver.
== Connections ==
* 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 ==


{| class="wikitable"
{| class="wikitable"
! Component
! Device
! Quantity
! Pin
|-
| 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 ===
 
{| class="wikitable"
! LM393
! Arduino
! Arduino
! Purpose
! Function
|-
|-
| LM393
| DO
| DO
| D2
| D2
| Encoder pulse signal
| Encoder pulse
|-
|-
| LM393
| VCC
| VCC
| 5V
| 5V
| Power
| Power
|-
|-
| LM393
| GND
| GND
| GND
| GND
| Ground
| Ground
|}
=== L293D ===
{| class="wikitable"
! L293D
! Arduino
! Purpose
|-
|-
| L293D
| EN1
| EN1
| D5
| D5
| PWM speed control
| Motor PWM
|-
|-
| L293D
| IN1
| IN1
| D7
| D7
| Motor direction
| Motor direction
|-
|-
| L293D
| IN2
| IN2
| D8
| D8
Line 121: Line 73:
|}
|}


The motor direction used by the program is:
=== Motor direction ===


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 128: Line 80:
</syntaxhighlight>
</syntaxhighlight>


The PWM signal applied to EN1 controls the motor speed.
=== Encoder ===


== System diagram ==
The LM393 produces a digital pulse whenever a slot on the encoder disc passes the sensor.


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


== Working ==
== Working ==


The geared motor rotates the gearbox output shaft. The encoder disc is attached to this output shaft.
The motor is driven through the L293D. The encoder disc rotates together with the gearbox 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 LM393 detects the slots and produces digital pulses. These pulses are connected to Arduino '''D2'''.


The program measures the number of encoder pulses received during a fixed time interval.
D2 uses an external interrupt to count the pulses.


The general equation is:
Every '''1 second''', the Arduino:


<math>
# Reads the number of encoder pulses.
RPM =
# Resets the pulse counter.
\frac{Pulses \times 60}
# Converts the pulse count into RPM.
{Slots\ per\ revolution \times Measurement\ time\ (seconds)}
# Displays the result on the Serial Monitor.
</math>


For this implementation:
The RPM calculation is:


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


and:
For example:


<math>
<math>
Measurement\ time = 1\ second
100\ pulses \rightarrow \frac{100 \times 60}{20} = 300\ RPM
</math>
</math>


Therefore:
== Arduino Code ==
 
<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">
<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 <code>pulseCount</code>.
== Pulse filtering ==
A minimum pulse interval is defined as:
<syntaxhighlight lang="cpp">
#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>
{| class="wikitable"
! Signal
! Arduino pin
! Function
|-
| EN1
| D5
| Motor speed
|-
| IN1
| D7
| Direction
|-
| IN2
| D8
| Direction
|}
/*
/*
   Encoder disc:
   Encoder disc:
       20 slots
       20 slots
   Encoder location:
   Encoder location:
       Gearbox OUTPUT shaft
       Gearbox OUTPUT shaft
   Therefore:
   Therefore:
       20 pulses = 1 output-shaft revolution
       20 pulses = 1 output-shaft revolution
   Encoder:
   Encoder:
       LM393 DO -> Arduino D2
       LM393 DO -> Arduino D2
   Motor driver:
   Motor driver:
       L293D
       L293D
Line 376: Line 157:
int motorPWM = 150;
int motorPWM = 150;


// ENCODER INTERRUPT
// Encoder interrupt
void encoderISR()
void encoderISR()
{
{
   unsigned long currentTime = micros();
   unsigned long currentTime = micros();
   if ((currentTime - lastPulseTime) >= MIN_PULSE_INTERVAL_US)
   if ((currentTime - lastPulseTime) >= MIN_PULSE_INTERVAL_US)
   {
   {
Line 390: Line 172:
{
{
   Serial.begin(115200);
   Serial.begin(115200);
   pinMode(ENCODER_PIN, INPUT);
   pinMode(ENCODER_PIN, INPUT);
   pinMode(EN1, OUTPUT);
   pinMode(EN1, OUTPUT);
   pinMode(IN1, OUTPUT);
   pinMode(IN1, OUTPUT);
   pinMode(IN2, OUTPUT);
   pinMode(IN2, OUTPUT);
  // Motor direction
   digitalWrite(IN1, HIGH);
   digitalWrite(IN1, HIGH);
   digitalWrite(IN2, LOW);
   digitalWrite(IN2, LOW);
  // Motor speed
   analogWrite(EN1, motorPWM);
   analogWrite(EN1, motorPWM);
  // Encoder interrupt
   attachInterrupt(
   attachInterrupt(
     digitalPinToInterrupt(ENCODER_PIN),
     digitalPinToInterrupt(ENCODER_PIN),
Line 409: Line 199:
{
{
   static unsigned long lastMeasurement = 0;
   static unsigned long lastMeasurement = 0;
   unsigned long currentTime = millis();
   unsigned long currentTime = millis();
   if (currentTime - lastMeasurement >= SAMPLE_TIME_MS)
   if (currentTime - lastMeasurement >= SAMPLE_TIME_MS)
   {
   {
     unsigned long pulses;
     unsigned long pulses;
     noInterrupts();
     noInterrupts();
     pulses = pulseCount;
     pulses = pulseCount;
Line 421: Line 214:
       (pulses * 60.0) /
       (pulses * 60.0) /
       (SLOTS_PER_REV * (SAMPLE_TIME_MS / 1000.0));
       (SLOTS_PER_REV * (SAMPLE_TIME_MS / 1000.0));
     Serial.print ("Pulses ");
 
     Serial.print (pulses);
     Serial.print("Pulses ");
     Serial.print (",RPM ");
     Serial.print(pulses);
     Serial.println (rpm);
 
     Serial.print(",RPM ");
     Serial.println(rpm);
 
     lastMeasurement = currentTime;
     lastMeasurement = currentTime;
   }
   }
}
}
</syntaxhighlight>


== Serial Monitor ==
== Observation ==


The Serial Monitor should be configured for '''115200 baud'''.
The Serial Monitor is set to '''115200 baud'''.


Example output:
Example observations:
 
<syntaxhighlight>
RPM
Pulses 80,RPM 240.00
Pulses 82,RPM 246.00
Pulses 81,RPM 243.00
Pulses 83,RPM 249.00
</syntaxhighlight>


{| class="wikitable"
{| class="wikitable"
! Output
! Pulse Count
! Meaning
! Calculated RPM
|-
|-
| <code>Pulses 80</code>
| 80
| 80 encoder pulses detected during the measurement interval
| 240 RPM
|-
|-
| <code>RPM 240.00</code>
| 82
| Calculated gearbox output-shaft speed
| 246 RPM
|}
 
== Program parameters ==
 
{| class="wikitable"
! Parameter
! Value
! Description
|-
| <code>ENCODER_PIN</code>
| 2
| Encoder input
|-
| <code>EN1</code>
| 5
| Motor PWM output
|-
| <code>IN1</code>
| 7
| Motor direction
|-
| <code>IN2</code>
| 8
| Motor direction
|-
|-
| <code>SLOTS_PER_REV</code>
| 81
| 20
| 243 RPM
| Encoder slots per revolution
|-
|-
| <code>MIN_PULSE_INTERVAL_US</code>
| 83
| 2000
| 249 RPM
| Minimum pulse interval
|-
| <code>SAMPLE_TIME_MS</code>
| 1000
| Measurement interval
|-
| <code>motorPWM</code>
| 150
| PWM value
|}
|}


== Result ==
Example Serial Monitor output:


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.
<syntaxhighlight>
 
RPM
The encoder provides:
Pulses 80,RPM 240.00
 
Pulses 82,RPM 246.00
<math>
Pulses 81,RPM 243.00
20\ pulses = 1\ output\ revolution
Pulses 83,RPM 249.00
</math>
</syntaxhighlight>


The Arduino counts the encoder pulses for one second and converts the count into RPM.
'''Result:''' The Arduino successfully controls the geared motor and measures the '''gearbox output-shaft RPM''' using the 20-slot LM393 encoder.


'''Measured output: RPM of the gearbox output shaft.'''
[[Category:Arduino]]
[[Category:Motor Control]]
[[Category:Rotary Encoder]]
[[Category:Electronics]]
```

Revision as of 12:03, 3 September 2026

```wiki


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
L293D EN1 D5 Motor PWM
L293D IN1 D7 Motor direction
L293D IN2 D8 Motor direction

Motor direction

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

Encoder

The LM393 produces a digital pulse whenever a slot on the encoder disc passes the sensor.

<syntaxhighlight> 20 slots

  ↓

20 pulses

  ↓

1 output-shaft revolution </syntaxhighlight>

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:

  1. Reads the number of encoder pulses.
  2. Resets the pulse counter.
  3. Converts the pulse count into RPM.
  4. Displays the result on the Serial Monitor.

The RPM calculation is:

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

For example:

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

Arduino Code

<syntaxhighlight lang="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;
 }

} </syntaxhighlight>

Observation

The Serial Monitor is set to 115200 baud.

Example observations:

Pulse Count Calculated RPM
80 240 RPM
82 246 RPM
81 243 RPM
83 249 RPM

Example Serial Monitor output:

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

Result: The Arduino successfully controls the geared motor and measures the gearbox output-shaft RPM using the 20-slot LM393 encoder. ```