Difficulty: Beginner-Intermediate | Time: 45 mins | Cost: ~$15 USD

The L298N is a dual full-bridge motor driver capable of handling two DC motors simultaneously, or one stepper motor, at up to 2A per channel (3A peak). If you are wiring an L298N Arduino setup, the most critical electrical reality to understand upfront is the voltage drop: because the L298N uses older bipolar junction transistor (BJT) technology rather than modern MOSFETs, it drops approximately 2V across its internal switching elements. If you feed it a 12V supply, your motor will only see about 10V at full speed. Knowing this prevents the most common beginner mistake—under-powering motors and blaming the code.

This guide targets the Arduino Uno R3 (ATmega328P) and the newer Arduino Uno R4 Minima/WiFi. The code and wiring apply identically to both, as they share the same standard digital/PWM pinout and 5V logic levels.

Hardware Spec Sheet & Parts List

Before stripping wires, verify your module variant. This guide assumes the standard, widely available "red board" L298N module (commonly sold by HiLetgo, Elegoo, or generic brands), which includes the onboard 7805 5V voltage regulator and integrated flyback diodes.

L298N Module Electrical Specifications (Source: STMicroelectronics L298N Datasheet)
ParameterSymbolValue / RangePractical Note
Motor Supply VoltageVs5V to 35V DCKeep under 12V if using the onboard 5V regulator to avoid thermal shutdown.
Logic Supply VoltageVss5V to 7V DCUsually fed by the Arduino's 5V pin or the onboard regulator.
Max Continuous CurrentIo2A per channelRequires the included heatsink for >1A continuous loads.
Peak Current (Non-repetitive)Ipm3A (per channel)Acceptable only for motor startup stall currents lasting <10ms.
Saturation Voltage DropVce(sat)~2.0V typicalSubtract this from your supply voltage to find actual motor voltage.

Required Parts:

  • Microcontroller: Arduino Uno R3 or Uno R4 Minima.
  • Driver Module: L298N Dual H-Bridge (Red PCB variant with screw terminals).
  • Power Supply: 12V 2A DC wall adapter or a 3S LiPo battery (11.1V nominal). Do not use 9V alkaline batteries; they cannot supply the required stall current and will cause brownouts.
  • Motors: 2x 3V-12V DC gear motors (e.g., standard yellow TT motors, though they run optimally at 6V, they will spin fast at 10V via the L298N).
  • Wiring: 22 AWG solid core for breadboard/headers, 18 AWG stranded for motor and power terminals.

Pin Mapping & Wiring Sequence

Proper grounding is where 90% of L298N Arduino projects fail. The Arduino, the L298N logic circuit, and the high-current motor power supply must share a common ground.

L298N to Arduino Uno R3/R4 Pin Mapping
L298N PinArduino PinFunction
12V (Vs)Power Supply +Main motor power input (up to 12V recommended for onboard 5V reg).
GNDGND (Arduino) + Power Supply -Critical: Must tie all three grounds together.
5V (Vss)5V (Arduino) OR UnconnectedIf Vs > 12V, remove jumper and feed 5V here from Arduino. If Vs < 12V, leave jumper ON to power Arduino.
ENAPin 5 (PWM)Speed control for Motor A. Remove physical jumper cap.
IN1Pin 4Direction logic for Motor A.
IN2Pin 7Direction logic for Motor A.
ENBPin 6 (PWM)Speed control for Motor B. Remove physical jumper cap.
IN3Pin 8Direction logic for Motor B.
IN4Pin 9Direction logic for Motor B.
Bench Tip: Always leave the physical jumper caps on ENA and ENB during your very first power-on test. This forces the motors to run at 100% hardware speed, bypassing your code. If the motors spin, your power wiring is correct. Remove them only when you are ready to test PWM speed control via code.

Compilable Arduino Code (Uno R3/R4 Target)

The following C++ sketch includes explicit pin definitions, serial debugging, and a safety timeout. If the serial connection drops or the microcontroller hangs, a watchdog-style timer stops the motors after 3 seconds of inactivity to prevent a runaway robot or bench fire.


// Target: Arduino Uno R3 (ATmega328P) / Uno R4 Minima
// L298N Dual H-Bridge Motor Controller with Serial Safety Timeout

// --- PIN DEFINITIONS ---
#define ENA 5   // PWM Motor A
#define IN1 4   // Dir Motor A
#define IN2 7   // Dir Motor A
#define ENB 6   // PWM Motor B
#define IN3 8   // Dir Motor B
#define IN4 9   // Dir Motor B

// --- SAFETY CONFIG ---
const unsigned long SAFETY_TIMEOUT_MS = 3000; // Stop motors if no serial cmd for 3s
unsigned long lastCommandTime = 0;

void setup() {
  // Initialize serial for debugging
  Serial.begin(115200);
  
  // Set all motor control pins as outputs
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  
  // Ensure motors are stopped on boot
  stopAllMotors();
  
  Serial.println("L298N Arduino Controller Ready.");
  Serial.println("Commands: F=Forward, B=Backward, L=Left, R=Right, S=Stop");
  lastCommandTime = millis();
}

void loop() {
  // 1. Handle Serial Commands
  if (Serial.available() > 0) {
    char cmd = Serial.read();
    lastCommandTime = millis(); // Reset safety timer
    
    switch(cmd) {
      case 'F': case 'f':
        moveForward(200); // PWM 0-255
        Serial.println("State: FORWARD");
        break;
      case 'B': case 'b':
        moveBackward(200);
        Serial.println("State: BACKWARD");
        break;
      case 'L': case 'l':
        turnLeft(150);
        Serial.println("State: LEFT");
        break;
      case 'R': case 'r':
        turnRight(150);
        Serial.println("State: RIGHT");
        break;
      case 'S': case 's':
        stopAllMotors();
        Serial.println("State: STOPPED");
        break;
    }
  }
  
  // 2. Safety Timeout Check (Error Handling)
  if (millis() - lastCommandTime > SAFETY_TIMEOUT_MS) {
    // Only print once when timeout triggers to avoid serial flood
    static bool timeoutTriggered = false;
    if (!timeoutTriggered) {
      stopAllMotors();
      Serial.println("ERROR: Safety Timeout - Motors Stopped.");
      timeoutTriggered = true;
    }
  } else {
    // Reset flag when commands are flowing
    static bool timeoutTriggered = false; 
    timeoutTriggered = false;
  }
}

// --- MOTOR CONTROL FUNCTIONS ---
void moveForward(int speed) {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, speed);
  analogWrite(ENB, speed);
}

void moveBackward(int speed) {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  analogWrite(ENA, speed);
  analogWrite(ENB, speed);
}

void turnLeft(int speed) {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, speed);
  analogWrite(ENB, speed);
}

void turnRight(int speed) {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  analogWrite(ENA, speed);
  analogWrite(ENB, speed);
}

void stopAllMotors() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}

Debugging: First 3 Things to Check When It Fails

When an Arduino motor circuit fails, the issue is almost always power delivery or logic grounding. Before rewriting your code, check these three physical layer faults.

  1. Verify the Common Ground: Use your multimeter in continuity mode (beep test). Place one probe on the Arduino GND pin and the other on the L298N GND screw terminal. It must read < 1 ohm. If they aren't tied together, the Arduino's 5V logic signals have no reference point, and the L298N will ignore your HIGH/LOW commands.
  2. Check the 5V Logic Jumper: Look at the 3-pin header next to the 12V/GND/5V terminals. If your motor supply is under 12V, the jumper must bridge the 5V and Vss pins to power the L298N's internal logic chip. If your supply is over 12V, the jumper must be removed, or the onboard 7805 regulator will overheat and shut down.
  3. Remove ENA/ENB Jumper Caps for PWM: If your motors run at full speed but refuse to change speed via analogWrite(), you likely left the physical plastic jumper caps on the ENA and ENB pins. These caps hardwire the enable pins to 5V, overriding your Arduino PWM signals. Pull them off with pliers.
Exact Error String: "Arduino brownout reset (Pin 13 LED flashes exactly when motor engages)"
Ranked Causes:
1. Voltage Sag on Shared Rail: If powering the Arduino via the L298N 5V output, the motor's startup stall current (often 1.5A+) pulls the voltage down, resetting the ATmega328P. Fix: Power the Arduino via USB or a separate 5V buck converter.
2. Missing Back-EMF Protection: While the red L298N module has built-in flyback diodes, cheap counterfeit boards sometimes omit them. Inductive kickback resets the Arduino. Fix: Solder 1N4007 diodes across the motor terminals.
3. USB Cable Voltage Drop: A low-quality USB cable cannot supply the transient current needed when the motor kicks in, causing the Arduino's USB voltage to dip below 4.5V. Fix: Use a shorter, thicker USB cable or an external power jack.

Extending and Simplifying the Build

The L298N is a legacy chip (designed in the 1990s). It is excellent for learning and high-voltage (24V+) applications, but it is inefficient due to the 2V heat dissipation.

How to Simplify (Downgrade): If you only need to drive a single motor and are running on a 1S or 2S LiPo (3.7V - 7.4V), ditch the L298N. Use a DRV8871 or TB6612FNG module. These use MOSFETs, dropping only ~0.2V, meaning your 6V motor actually gets 5.8V instead of 4V. They also require fewer Arduino pins (no separate enable pins needed).

How to Extend (Upgrade): To turn this into a closed-loop robotics platform, add quadrature rotary encoders to the back shafts of your DC motors. Wire the encoder A/B pins to Arduino hardware interrupt pins (Pins 2 and 3 on the Uno). Use the Encoder library to track exact wheel rotations, and implement a PID controller in your code to ensure both motors spin at the exact same RPM, correcting for physical friction differences.

FAQ: L298N Arduino Long-Tail Questions

Why is my L298N Arduino motor humming but not spinning?

A humming motor usually indicates that the PWM frequency is too low for the motor's inductance, or the duty cycle is below the motor's mechanical stall threshold. The Arduino Uno's default PWM frequency on pins 5 and 6 is ~980Hz, which is generally fine. However, if you are sending a PWM value below 80 (out of 255), the motor may not have enough torque to overcome internal static friction. Increase your analogWrite() value to at least 120 to get it moving, then throttle down. Also, ensure you aren't trying to run a 12V motor on a 5V USB supply through the L298N; the voltage drop will leave the motor with only 3V, which is insufficient for most 12V rated coils.

Can I power the Arduino directly from the L298N 5V output?

Yes, but with strict conditions. The red L298N module features an onboard 78M05 linear voltage regulator. If your motor supply (Vs) is between 7V and 12V, and the 5V jumper cap is installed, the module will output a regulated 5V on the third screw terminal. You can wire this to the Arduino's "5V" pin (bypassing the Arduino's own USB regulator). Warning: The 78M05 can only safely supply about 500mA. If your Arduino is powering sensors, an OLED screen, and a WiFi module (like an ESP8266 attached via UART), you will exceed this limit and cause a thermal shutdown. In that case, remove the jumper and power the Arduino independently.

How do I control L298N Arduino motor speed without PWM pins?

If you have run out of hardware PWM pins (pins with the ~ symbol), you cannot use analogWrite(). However, you can implement "software PWM" by rapidly toggling a standard digital pin HIGH and LOW using delayMicroseconds(). For example, looping a pin HIGH for 500 microseconds and LOW for 500 microseconds yields a 50% duty cycle. The major drawback is that software PWM blocks the CPU, meaning your Arduino cannot read sensors or handle serial commands while the motor is running. For multi-tasking, consider using an I2C PWM driver like the PCA9685 to offload the signal generation.