Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

L298N motor driver with NodeMCU ESP8266 — wiring and code

Drive two DC motors from a NodeMCU ESP8266 through an L298N: PWM speed on D1/D5, direction pins chosen around the boot pins, battery wiring.

Arduino C++Verified — core esp8266 3.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

The L298N is the motor driver in nearly every Indian robot-car kit. It takes a direction signal on IN1–IN4 and a PWM speed signal on ENA/ENB, and switches the battery pack through to two DC motors.

With a NodeMCU, the work is in the pin choice: six control pins on a board whose boot pins (D3, D4, D8) you want to keep clear. This guide uses D1 and D5 for PWM speed, and D2, D0, D6, D7 for direction.

Wiring

NodeMCU ESP8266Only the pins used are shown · 3.3 V logic2× 18650 Li-ion pack (7.4 V)L298N dual H-bridge motor driver+-GNDD0D1D2D5D6D7IN1IN2IN3IN4ENAENB12VGND5V (not connected)OUT1 → Left motor (+)OUT2 → Left motor (−)OUT3 → Right motor (+)OUT4 → Right motor (−)
Every connection
NodeMCU ESP8266L298N dual H-bridge motor driverWireNotes
—OUT1—To Left motor (+) (not drawn)
—OUT2—To Left motor (−) (not drawn)
—OUT3—To Right motor (+) (not drawn)
—OUT4—To Right motor (−) (not drawn)
2× 18650 Li-ion pack (7.4 V) · +12VredMotor supply. Keep the 5V-EN jumper on (pack under 12 V) so the L298N makes its own 5 V logic supply.
2× 18650 Li-ion pack (7.4 V) · -GNDblack
GNDGNDblackCommon ground between the NodeMCU and the driver — the motors won’t respond without it.
D1ENAorangePWM speed, left motor. Pull the ENA jumper off first.
D2IN1yellow
D0IN2greenD0 (GPIO16) has no PWM, but a direction pin doesn’t need it.
D5ENBorangePWM speed, right motor. Pull the ENB jumper off first.
D6IN3blue
D7IN4purple

Motor supply 5–35 V on the 12V terminal; logic 5 V part, 3.3 V board. The L298N’s inputs see anything above about 2.3 V as HIGH, so 3.3 V boards drive IN1–IN4 and ENA/ENB directly. Always connect the board’s GND to the driver’s GND.

Board quirks

  • Two motors need six pins, and the NodeMCU has only five that are free and boot-safe (D1, D2, D5, D6, D7). The sixth comes from D0 (GPIO16): it can’t do PWM or interrupts, so it gets a direction input (IN2), never an enable. D3, D4 and D8 stay free so a driver input can’t upset booting.
  • On ESP8266 core 3.x analogWrite() takes 0–255 by default. Old core 2.x tutorials use 0–1023; on 3.x those values all mean full speed. Call analogWriteRange(1023) if you want the old scale.
  • The ESP8266 makes PWM in software. analogWriteFreq(1000) gives 1 kHz, which suits the slow bipolar L298N; much higher frequencies just make it run hot.
  • The L298N drops about 2 V inside, so a 7.4 V pack gives the motors roughly 5 V. That is why 6 V “BO” gear motors with a 2S pack are the usual Indian robot-kit combination.
  • Don’t power the NodeMCU from the L298N’s 5V pin while it is on USB. Run it from USB while testing; for a free-running robot, feed the L298N 5V into VIN with USB unplugged.

Code

l298n-nodemcu.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// L298N dual motor driver on a NodeMCU (ESP8266) — two DC motors, speed and direction.
// ENA → D1 (GPIO5, PWM), IN1 → D2, IN2 → D0, IN3 → D6, IN4 → D7, ENB → D5 (GPIO14, PWM), GND → GND.
// Motors on OUT1/OUT2 and OUT3/OUT4; battery pack on 12V/GND. Remove the ENA/ENB jumpers.
const uint8_t ENA = D1, IN1 = D2, IN2 = D0;  // left motor (D0 has no PWM, fine for a direction pin)
const uint8_t ENB = D5, IN3 = D6, IN4 = D7;  // right motor

// speed -255..255. On core 3.x analogWrite() takes 0–255 by default (core 2.x used 0–1023).
void motor(uint8_t en, uint8_t a, uint8_t b, int speed) {
  digitalWrite(a, speed > 0 ? HIGH : LOW);
  digitalWrite(b, speed < 0 ? HIGH : LOW);
  analogWrite(en, abs(speed));
}

void drive(const char* what, int left, int right) {
  Serial.printf("%-8s left %4d  right %4d\n", what, left, right);
  motor(ENA, IN1, IN2, left);
  motor(ENB, IN3, IN4, right);
}

void setup() {
  const uint8_t pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
  for (uint8_t p : pins) {
    digitalWrite(p, LOW);  // motors stopped before the pins become outputs
    pinMode(p, OUTPUT);
  }
  analogWriteFreq(1000);  // 1 kHz PWM suits the slow L298N
  Serial.begin(115200);
  Serial.println();
  Serial.println("L298N test: forward, reverse, turn, stop");
}

void loop() {
  drive("forward", 200, 200);
  delay(2000);
  drive("stop", 0, 0);
  delay(500);
  drive("reverse", -200, -200);
  delay(2000);
  drive("turn", 180, -180);
  delay(1000);
  drive("stop", 0, 0);
  delay(2000);
}

Expected serial output

Serial Monitor · 115200Output
L298N test: forward, reverse, turn, stop
forward  left  200  right  200
stop     left    0  right    0
reverse  left -200  right -200
turn     left  180  right -180
stop     left    0  right    0

Common errors

Motors run at full speed whatever the PWM value

The ENA/ENB jumpers are still on, so EN is tied to 5 V. Remove them and wire ENA to D1, ENB to D5.

NodeMCU resets when the motors start

Motor current is pulling the shared supply down. Run the board from USB or a separate supply, keep only GND common, and add a 100 nF capacitor across each motor.

One motor turns the wrong way

Swap that motor’s two wires on OUT1/OUT2 (or OUT3/OUT4).

↑↓ to move · Enter to open