Arduino L298N Motor Control for DC Motor Speed Regulation
2026/09/24
The L298N dc motor control module controls motor speed & direction of motor. Engineers use it as a motor speed controller. A PWM signal to the enable pin allows engineers to control the speed of the motor. An Arduino board reads a potentiometer to adjust the PWM signal duty cycle. This setup provides precise operation.
Key Takeaways
- Use a PWM signal to the L298N enable pin to control motor speed.
- Connect the Arduino and L298N grounds together for the circuit to work.
- Use the input pins to change the motor direction, not the speed.
- Read a potentiometer with analogRead() and map the value to set motor speed.
- Use a button with a short delay to reverse the motor direction without errors.
How PWM and the H-Bridge Control Motor Speed & Direction
What PWM Is and How Duty Cycle Sets Speed
Pulse width modulation (PWM) is a technique that switches a signal on and off rapidly. The percentage of time the signal stays on is called the duty cycle. A higher duty cycle means the signal stays on longer. This directly affects the speed of the dc motor. The average output voltage in an H-bridge is linearly proportional to the PWM duty cycle.
The formula is: V_avg = V_supply × (D/100), where D is the duty cycle percentage.
A 50% duty cycle delivers half the supply voltage to the motor. A 100% duty cycle delivers full voltage. The Arduino generates a PWM signal on specific pins. This PWM signal to the enable pins sets the motor speed. The PWM output changes smoothly. The motor speed responds in kind.
What an H-Bridge Does for Direction
An H-bridge circuit arranges four switches around the motor. Closing two opposite switches pushes current one way. Closing the other two reverses the current. This action flips the motor rotation. The L298N module contains two H-bridge circuits. Each circuit controls one motor. Input 1 and Input 2 set the direction for motor A. Input 3 and Input 4 set the direction for motor B. The input pins do not affect speed. They only determine rotation.
Why the L298N Enable Pins Handle Speed
The L298N uses separate pins for speed and direction control. The ENA pin controls motor A. The ENB pin controls motor B. A PWM signal to the enable pins adjusts the average voltage. This method allows engineers to control the speed of the motor without touching the input pins. The enable pins accept a PWM input from the Arduino. This design separates speed and direction control into two clean operations. Enabling and controlling the speed becomes straightforward. The PWM signal frequency also matters for motor speed.
The optimal PWM frequency is 2-5kHz, but it is also most audible. Therefore it is often a tradeoff between switching losses and noise free operation.
- PWM frequencies between 1 kHz and 20 kHz provide optimal performance for most applications.
- Smaller low-inductance motors perform best at higher frequencies (10-20 kHz), which eliminates audible noise.
- Larger higher-inductance motors work well at lower frequencies (1-5 kHz).
- To eliminate audible whining or buzzing, increase the PWM frequency above 20 kHz to push acoustic emissions beyond the audible range.
- Frequencies above 20 kHz eliminate acoustic noise but increase switching losses in the drive electronics.
What You Need and How to Wire the DC Motor Control Module
This section explains the required components and the connection process. Engineers must gather the correct parts and follow a clear wiring plan. The L298N dc motor control module serves as the core of this system. An arduino board generates the control signals for speed and direction. Proper wiring guarantees stable motor speed regulation and reliable operation.
Parts List for This Project
The following items form the complete system:
- L298N motor driver module
- Arduino Uno (or any compatible arduino board)
- DC motor with a 6V to 12V rating
- 10kΩ potentiometer
- Momentary push button
- 9V to 12V power supply for the motor (battery or adapter)
- Breadboard and jumper wires
- 100µF and 0.1µF decoupling capacitors
The dc motor control module has specific physical dimensions. Engineers need these measurements for enclosure design or mounting. The module measures approximately 43mm × 43mm × 28.6mm. The mounting holes have a 3.0mm diameter with a 36.6mm center-to-center spacing.
| Specification | Value |
|---|---|
| Module dimensions | ~43mm × 43mm × 28.6mm |
| Mounting hole diameter | ~3.0mm |
| Mounting hole spacing | ~36.6mm (center to center) |
The L298N requires two separate power inputs. The logic supply (VSS) powers the internal control circuitry. This pin accepts a specific voltage range. The module can also derive the 5V logic supply internally from the motor power.
- VSS accepts voltages from 4.5V to 7V.
- The power supply range for the logic section terminals Vss is +5V to +7V.
- The module can supply +5V internally through its onboard regulator.
Wiring the L298N to the Arduino and Motor
The wiring process follows a straightforward sequence. Engineers must connect each terminal to its correct counterpart. The circuit schematics for this project detail the exact connections. Follow these steps to complete the wiring:
- Connect the Arduino 5V pin to the L298N VSS pin. This provides logic power.
- Connect the Arduino GND to the L298N GND. This shares the ground reference.
- Connect L298N Enable A (enA) to Arduino pin 9. This pin receives the PWM signal.
- Connect L298N Input 1 (in1) to Arduino pin 6. This controls one rotation direction.
- Connect L298N Input 2 (in2) to Arduino pin 7. This controls the opposite rotation direction.
- Connect the push button between Arduino pin 4 and GND. This provides the direction toggle input.
- Connect the potentiometer center pin to Arduino analog pin A0. The outer pins connect to 5V and GND.
The table below summarizes the pin mappings for this project:
| L298N Module Terminal | Arduino Digital Pin |
|---|---|
| Enable A (enA) | 9 |
| Input 1 (in1) | 6 |
| Input 2 (in2) | 7 |
| Button (not L298N) | 4 |
The L298N module uses Enable A and Enable B pins to control motor speed via PWM. These pins also enable or disable the motor entirely. Input 1 and Input 2 determine the rotation direction of motor A. Input 3 and Input 4 control motor B in the same fashion. In this configuration, enA connects to pin 9, in1 to pin 6, and in2 to pin 7. This partial pinout mapping represents a typical wiring arrangement. Engineers can expand the pattern for a second motor by adding enB, in3, and in4.
The L298N belongs to a family of popular dc motor drivers. Engineers choose it for its simplicity and dual H-bridge design. The module handles two motors independently without additional components.
Powering the Motor and Sharing Ground
Power delivery requires careful attention. The motor supply voltage connects to the L298N VS pin. A 9V to 12V supply works well for common hobby motors. The logic section receives power from the Arduino 5V pin or from the module's internal 5V regulator.
Grounding forms the most critical connection. The Arduino GND and L298N GND must connect together. This shared ground creates a common reference for all control signals. Without this connection, the signals cannot function correctly and the motor will not respond.
Decoupling capacitors stabilize the power supply. They reduce electrical noise and prevent voltage drops during motor operation. Place a 100µF bulk capacitor near the L298N power pins. Place a 0.1µF ceramic capacitor close to the IC power pins. The following table summarizes the recommended values:
| Capacitor Type | Recommended Value | Placement | Purpose |
|---|---|---|---|
| Bulk capacitor | 100µF or more | Near the IC's power pins | Stabilizing power supply rails |
| Ceramic capacitor | 0.1µF | Close to the IC's power pins | Effective noise suppression |
These capacitors prevent the motor from disrupting the logic signals. Large motors draw significant current during startup. The bulk capacitor supplies the extra charge during these peaks. The ceramic capacitor filters high-frequency noise. This combination ensures stable and reliable operation.
Arduino Code to Control the Speed & Direction of Motor
The Arduino sketch brings together the potentiometer, button, and L298N dc motor control module into one working system. The code reads an analog voltage, converts that reading into a PWM value, and writes the result to the enable pin. A separate routine watches the button and flips the input pins when pressed. This section builds the sketch step by step.
Reading a Potentiometer for Speed
The potentiometer acts as a voltage divider. Turning the knob changes the voltage at the center pin. The Arduino board reads this voltage on an analog input pin. The analogRead() function returns a number between 0 and 1023. This range corresponds to the 10-bit analog-to-digital converter inside the microcontroller.
A 10k ohm rotary potentiometer works well for this task. The product listing for a carbon rotary potentiometer rated at 10k ohm explicitly specifies a resistance tolerance of 30%. This tolerance means the actual resistance may vary, but the Arduino reads voltage ratios rather than absolute resistance. The ratiometric measurement cancels out most tolerance effects. The reading stays stable across the potentiometer's rotation.
The code must convert the 0-1023 reading into a 0-255 range. The analogWrite() function accepts values from 0 to 255. This 8-bit resolution sets the PWM duty cycle. A value of 0 produces a 0% duty cycle. A value of 255 produces a 100% duty cycle. The map() function performs this conversion in one line. The mapped value then goes to the enable pin.
The PWM frequency on the Arduino Uno affects how the motor responds. The default frequencies vary by pin. The following table shows the values documented in the Atmel datasheet:
| Pin(s) | Default PWM Frequency |
|---|---|
| D5 & D6 | 976.56 Hz |
| D9 & D10 | 490.20 Hz |
Pin 9 carries the PWM signal in this project. The 490.20 Hz default frequency falls within the optimal range for most hobby motors. Engineers who need quieter operation can change the timer prescaler. This adjustment raises the PWM frequency above the audible range.
Using a Button to Reverse Direction
The push button provides a simple way to flip rotation. One side of the button connects to Arduino pin 4. The other side connects to ground. The code enables the internal pull-up resistor with INPUT_PULLUP. This configuration holds the pin HIGH when the button is released. Pressing the button pulls the pin LOW.
The sketch must detect the moment of pressing rather than the held state. A simple digitalRead() check would trigger repeatedly while the button stays down. The code tracks the previous button state instead. A change from HIGH to LOW signals a new press. This edge detection prevents multiple toggles from one press.
A state variable stores the current direction. Each valid press flips this variable between two values. The code then writes the new direction to the input pins. Setting in1 HIGH and in2 LOW drives the motor forward. Setting in1 LOW and in2 HIGH drives the motor backward. The enable pin keeps receiving the PWM signal throughout. This design lets the user control the speed & direction of motor independently.
Debouncing improves reliability. Mechanical buttons produce brief electrical noise when pressed. A short delay after detection skips this noise. The code ignores additional transitions for a few milliseconds. This small addition prevents erratic direction changes.
Full Sketch with Comments
A complete Arduino sketch follows a standard structure. The table below outlines the essential sections:
- setup() — invoked once at program start (on power-on or reset); used to initialize variables, set pin modes (INPUT/OUTPUT/INPUT_PULLUP), start serial communication, load libraries, set initial states, and configure timers/interrupts.
- loop() — begins after setup() completes and runs repeatedly forever; used for actions that must happen continuously.
- Variable declaration scope — globals declared at the top are available everywhere; locals declared inside setup() or loop() are only accessible within that function. Rule of thumb: declare at the top (global) if the variable is needed in multiple places.
The same structure applies here in three ordered parts:
- Global Variable Declaration — placed at the very start of the sketch; used to define variables accessible throughout the entire program. May be left empty if no globals are needed.
- Initialization (setup()) — defined as
void setup() { ... }; runs exactly once when the program starts, before the main body executes. - Main Body (loop()) — defined as
void loop() { ... }; analogous tomain()in C; repeats continuously once started.
The sketch below implements every feature discussed above:
const int enA = 9, in1 = 6, in2 = 7;
const int potPin = A0, buttonPin = 4;
int motorSpeed = 0, lastButton = HIGH;
bool forward = true;
void setup() {
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
motorSpeed = map(analogRead(potPin), 0, 1023, 0, 255);
int reading = digitalRead(buttonPin);
if (reading == LOW && lastButton == HIGH) {
forward = !forward;
delay(200);
}
lastButton = reading;
digitalWrite(in1, forward ? HIGH : LOW);
digitalWrite(in2, forward ? LOW : HIGH);
analogWrite(enA, motorSpeed);
}
The sketch declares pin numbers as constants at the top. This practice makes the code easy to modify. The setup() function configures each pin mode. The loop() function reads the potentiometer, checks the button, and updates the outputs. The map() call converts the analog reading into a PWM value. The ternary operator sets the input pins based on the direction flag. The analogWrite() call sends the PWM signal to the enable pin. This single line controls the speed of the motor.
Engineers can adjust the delay value to change debounce timing. A larger value provides more stability but slower response. A smaller value feels more responsive but may register false presses. The 200ms value balances both concerns for typical hobby buttons.
Breaking Down the Code Line by Line
Setting Up Pins and Variables
The sketch begins with constant declarations. The enA pin connects to digital pin 9. The in1 and in2 pins connect to pins 6 and 7. The potentiometer uses analog pin A0. The button uses digital pin 4. These constants make the code easy to modify later.
The Arduino board reads analog voltages through a 10-bit analog-to-digital converter. This converter produces 2^10 = 1024 discrete levels. The analogRead() function returns an integer between 0 and 1023. A reading of 0 corresponds to 0V. A reading of 1023 corresponds to the reference voltage, typically 5V.
| ADC Resolution | Discrete Levels | analogRead() Range | Step Size (VREF = 5V) |
|---|---|---|---|
| 10-bit (Arduino Uno) | 2^10 = 1024 | 0 to 1023 | 5V ÷ 1024 ≈ 4.88 mV |
The setup() function configures each pin. The enable pin and input pins become outputs. The button pin becomes an input with the internal pull-up resistor enabled. This configuration holds the button pin HIGH when released.
Mapping Potentiometer Values to PWM
The loop() function reads the potentiometer first. The raw value spans 0 to 1023. The analogWrite() function accepts only 0 to 255. The map() function converts between these ranges.
analogWrite(11, map(sensorVal, 0, 1023, 0, 255));Here
sensorVal(range 0–1023) is mapped to an 8-bit PWM value (range 0–255).
int brightness = map(potValue, 0, 1023, 0, 255);This maps a potentiometer reading (
potValue) in the range 0–1023 to a PWM brightness value in the range 0–255.
This conversion sets the pwm output duty cycle. A mapped value of 0 produces a 0% duty cycle. A mapped value of 255 produces a 100% duty cycle. The motor speed responds directly to this pwm signal.
Writing to the Enable and Input Pins
The code writes to the input pins based on the direction flag. Setting in1 HIGH and in2 LOW drives the motor forward. Setting in1 LOW and in2 HIGH drives the motor backward. The digitalWrite() function produces a clean logic level on each pin.
| Logic Level | 5V Boards (UNO, Mega, Nano) | 3.3V Boards (Due, MKR series) |
|---|---|---|
| HIGH | 5V | 3.3V |
| LOW | 0V (GND) | 0V (GND) |
When
digitalWrite(13, HIGH)is executed, the pin is pulled to the board's supply voltage — 5V on the UNO. Connecting a voltmeter to pin 13 after this will show a reading of 5V.
The analogWrite() call sends the pwm signal to the enable pin. This single line controls the speed of the motor. The Arduino Uno provides 6 hardware PWM pins: 3, 5, 6, 9, 10, and 11. Pin 9 carries the pwm signal in this project. The enA pin receives this pwm signal and adjusts the motor speed. A second motor would use the enb pin with the same pattern. The input 1 and input 2 pins only change direction. They never affect speed. This separation lets engineers control the speed and direction independently. The pwm signal frequency stays constant while the duty cycle changes. Each pwm signal cycle delivers a precise amount of energy. The motor speed follows the duty cycle smoothly. Engineers can control the speed of the motor with fine resolution using this method.
Advanced Example: Joystick-Controlled Robot Car
Wiring Two Motors and a Joystick
The L298N module supports two independent motors. Engineers add Motor B with the remaining pins. The module uses ENB for speed control. IN3 and IN4 set the direction for Motor B. Motor A continues using ENA, IN1, and IN2. This configuration requires two pwm-capable pins.
Two pwm-capable pins are needed for independent motor control. One pin connects to ENA. The other connects to ENB.
Pins 9 and 10 provide the pwm signals.
A KY-023 joystick module provides analog input. The module outputs two voltage signals. The VRx pin corresponds to horizontal movement. The VRy pin corresponds to vertical movement. Connect VRx to analog pin A1. Connect VRy to analog pin A2 on the arduino board.
Joystick values don't centre at 512. Budget clone potentiometers often have a slight offset — the rest position may sit anywhere between 490 and 540. Use
map()or apply software calibration to compensate.
Engineers sample the joystick at rest and store that as the deadzone center. This prevents small wobbles from triggering unwanted movement.
Mixing Speed and Direction for Steering
A two-motor robot car uses differential steering. The L298N provides two pwm signals for independent wheel control. The pwm signal on ENA drives Motor A. The pwm signal on ENB drives Motor B. These signals determine the motor speed for each wheel.
Setting both motors to the same motor speed pushes the car straight. Varying the speed between the two motors turns the car. Engineers control dc motors with two distinct signals. The joystick X-axis controls steering. The Y-axis controls throttle. Mapping the joystick values to duty cycles translates analog readings into specific values for each motor.
The input pins set the direction for each motor. Engineers control the speed and direction independently. This method provides smooth and precise maneuvers. The system scales easily to a full robot car platform.
Troubleshooting Common L298N Problems
Motor Won't Spin or Only Buzzes
A motor that refuses to spin or emits only a buzzing sound often indicates a missing ground connection. The Arduino and the dc motor control module must share a common ground. Without this connection, the control signals cannot complete their circuit. Engineers should verify that the L298N GND connects to the Arduino GND. A buzzing motor sometimes means the supply voltage sits too low. The required motor speed determines the necessary supply voltage. Engineers must ensure the pwm duty cycle varies from 0 to 255. Checking the motor power supply with a multimeter confirms this condition. The enable pin must also receive a pwm signal. A constant HIGH or LOW on this pin prevents proper operation.
Speed Doesn't Change or Jumps
Erratic speed behavior usually stems from the pwm setup. Engineers sometimes connect the enable pin to a non-pwm-capable digital pin. The Arduino generates pwm on specific pins. Pin 9 provides the correct output for this application. A loose potentiometer connection causes the value to jump. Engineers should verify that the potentiometer center pin connects securely to analog pin A0. The outer pins must connect to 5V and GND. Dirty potentiometer tracks produce fluctuating readings. Wiping a potentiometer through its full range several times cleans the track. Insufficient debouncing on the button pin also creates unwanted speed changes. The code must detect button presses with a small delay to filter noise.
Direction Won't Reverse
A failure to reverse direction points to the input pin wiring or the button circuit. Engineers must confirm that in1 and in2 connect to separate Arduino pins. Both pins must respond to the digitalWrite commands in the code. A short circuit between in1 and in2 locks the motor in one direction. The button circuit requires the internal pull-up resistor. Without INPUT_PULLUP, the pin floats and registers false readings. Engineers should verify that the button connects between the pin and GND. The code also stores a variable for forward direction. A logic error in the button state detection prevents the variable from toggling. The motor maintains the same speed after the direction change. Adding a serial print statement checks this variable during operation.
The enable pins receive a pwm signal to set motor speed, while the input pins determine rotation direction. Engineers must connect the Arduino and L298N grounds together and use a separate motor supply for reliable operation. Experimenting with different pwm values helps users understand how duty cycle affects motor speed. Adding a second motor creates a full robot build. The same wiring and code pattern scales to larger projects such as robot cars and conveyor belts.
FAQ
Does the L298N need PWM pins on the Arduino?
Yes. The enable pins require a PWM signal to set motor speed. The Arduino Uno offers six PWM-capable pins: 3, 5, 6, 9, 10, and 11. A non-PWM pin only turns the motor fully on or fully off.
What supply voltage does the L298N motor driver need?
The module accepts 5V to 35V on the motor supply pin. Most hobby motors run well between 9V and 12V. The logic side needs 4.5V to 7V, which the onboard regulator often provides.
Can one L298N module control two DC motors at once?
Yes. The module contains two independent H-bridges. Motor A uses ENA, IN1, and IN2. Motor B uses ENB, IN3, and IN4. Each motor receives its own speed and direction signals.
Does the potentiometer have to be 10kΩ?
No. A 10kΩ potentiometer works well, but other values function too. The Arduino reads voltage ratios rather than absolute resistance. A 1kΩ to 100kΩ potentiometer typically performs fine.
Why does the motor whine at low PWM values?
The default PWM frequency on pin 9 sits near 490 Hz. This frequency falls within the audible range. Raising the PWM frequency above 20 kHz pushes the noise beyond human hearing, though switching losses increase.
Previous Page