ESP32-Based 4WD Robot Car Using Dual L298N Motor Drivers – Circuit Diagram and IoT Control Project

ESP32-Based 4WD Robot Car Using Dual L298N Motor Drivers | MakeMindz
ESP32 Robotics 4WD WiFi Control L298N

ESP32-Based 4WD Robot Car
Using Dual L298N Motor Drivers

A complete WiFi-controlled robot car project with circuit diagram, JSON configuration, step-by-step wiring guide, and full source code — ready to build.

🕐 45–60 min build 🔧 Intermediate level 📡 WiFi WebSocket control 🏷️ MakeMindz.com

📋 Project Overview

This project builds a fully WiFi-controlled 4-wheel-drive robot car using an ESP32 microcontroller and two L298N H-bridge motor driver modules. The ESP32 acts as a WiFi access point — you connect your phone or laptop directly, then control the robot from a browser interface using WebSockets for real-time, low-latency commands.

Each L298N controls one pair of motors (left side and right side). This dual-driver setup provides enough current headroom for sustained operation and opens the door to mecanum wheel configurations with full omnidirectional movement.

ℹ️ The ESP32 runs in SoftAP mode — it creates its own WiFi network. No router needed. Connect your device to the ESP32's SSID and navigate to 192.168.4.1 in any browser.

🔧 Components Required

1
ESP32 Dev Board
38-pin or 30-pin variant — any standard ESP32
2
L298N Motor Driver
Dual H-bridge, 2A per channel, 5–35V supply
4
BO Geared DC Motors
Yellow gear motors, 3–6V, ~200 RPM with wheels
4
Robot / Mecanum Wheels
65mm robot wheels or mecanum wheels for omnidirectional
1
Battery Pack
7.4V 2S LiPo or 6× AA pack (≥ 2A continuous)
1
Power Switch (SPDT)
Inline on battery positive lead
Breadboard & Jumper Wires
For prototyping connections; replace with soldered PCB
Robot Chassis
2-deck acrylic or 3D-printed frame with motor mounts

Circuit Diagram

The diagram below shows how the ESP32, both L298N drivers, motors, and battery connect together. All ground rails must be tied together for stable signalling.

Battery 7.4V / 2A+ + Switch ESP32 Dev Board GPIO16 ➡ IN1(A) GPIO17 ➡ IN2(A) GPIO18 ➡ IN3(A) GPIO19 ➡ IN4(A) GPIO27 ➡ IN1(B) GPIO26 ➡ IN2(B) GPIO25 ➡ IN3(B) GPIO33 ➡ IN4(B) L298N — A Right motors IN1 ← GPIO16 IN2 ← GPIO17 IN3 ← GPIO18 IN4 ← GPIO19 OUT1 → Motor FR+ OUT2 → Motor BR+ L298N — B Left motors IN1 ← GPIO27 IN2 ← GPIO26 IN3 ← GPIO25 IN4 ← GPIO33 OUT1 → Motor FL+ OUT2 → Motor BL+ Motor FR Motor BR Motor FL Motor BL Common Ground (GND) — Battery − → ESP32 GND → L298N GND → L298N GND 7.4V power GPIO signals GPIO signals

Simplified schematic — see wiring table below for exact connections

🔌 Pin Wiring Reference

ESP32 → L298N Driver A (Right-side motors)

ESP32 GPIOL298N PinMotorFunction
GPIO 16IN1Front RightDirection 1
GPIO 17IN2Front RightDirection 2
GPIO 18IN3Back RightDirection 1
GPIO 19IN4Back RightDirection 2
GNDGNDCommon Ground
12V / VINBattery +

ESP32 → L298N Driver B (Left-side motors)

ESP32 GPIOL298N PinMotorFunction
GPIO 27IN1Front LeftDirection 1
GPIO 26IN2Front LeftDirection 2
GPIO 25IN3Back LeftDirection 1
GPIO 33IN4Back LeftDirection 2
GNDGNDCommon Ground
12V / VINBattery +
⚠️ Important: The ESP32 runs on 3.3V logic. L298N inputs accept 3.3V signals, but verify your specific module. Remove the 5V jumper on the L298N if your battery is below 12V to avoid the onboard regulator overheating.

🛠️ Step-by-Step Build Guide

1
Assemble the chassis
Mount all four BO geared motors into the chassis motor holders. Attach wheels to motor shafts. Secure both L298N modules and the ESP32 dev board to the upper deck. Leave the battery slot accessible for easy swapping.
2
Wire motors to L298N outputs
Connect Front Right motor to L298N-A OUT1/OUT2. Connect Back Right motor to L298N-A OUT3/OUT4. Connect Front Left motor to L298N-B OUT1/OUT2. Connect Back Left motor to L298N-B OUT3/OUT4. Use the colour of your motor wires consistently — swap leads if the motor runs backwards later.
💡 Tip: Label your motor wires with tape before routing them — it saves time during debugging.
3
Connect battery power to both L298N modules
Run battery positive (+) through the power switch, then split to both L298N VIN terminals. Connect battery negative (−) to both L298N GND terminals. Do not power the ESP32 from battery directly yet.
⚠️ Check polarity twice before connecting. Reverse polarity will damage the L298N instantly.
4
Wire ESP32 GPIO to L298N IN pins
Use jumper wires: GPIO16→IN1(A), GPIO17→IN2(A), GPIO18→IN3(A), GPIO19→IN4(A) for right motors. GPIO27→IN1(B), GPIO26→IN2(B), GPIO25→IN3(B), GPIO33→IN4(B) for left motors. See the full table in the Wiring Reference section above.
5
Connect all grounds together
Run a wire from one ESP32 GND pin to the GND rail shared by both L298N modules and the battery negative. This common ground is essential — without it, the control signals will be noisy or non-functional.
💡 Use a small breadboard as a GND bus for clean common ground distribution.
6
Power the ESP32 via L298N 5V output
If your L298N has the 5V jumper installed, you can power the ESP32 VIN from the L298N's 5V output pin (only works when battery voltage is 7V–12V and the jumper is present). Alternatively, use a separate USB power bank for the ESP32.
7
Upload the code via Arduino IDE
Install the ESP32 board package and the ESPAsyncWebServer + AsyncTCP libraries. Open the sketch, update the SSID/password constants if needed, then upload via USB. Open Serial Monitor at 115200 baud to confirm the AP IP address.
📦 Required libraries: ESPAsyncWebServer, AsyncTCP, ESP32 Arduino core (board manager URL: https://dl.espressif.com/dl/package_esp32_index.json)
8
Connect and test
Switch on the robot. Connect your phone or laptop WiFi to the SSID in the code. Open a browser and navigate to 192.168.4.1. The touch-pad control interface appears. Test each direction button and verify the motors respond correctly. If a motor runs backwards, swap its two output wires on the L298N.
✅ All 10 movement commands (Forward, Backward, Left, Right, 4 diagonals, 2 rotations, Stop) should work cleanly before adding any sensors.

🕹️ Movement Logic (Mecanum Wheels)

The code sends values 0–10 over WebSocket. Each value maps to a motor direction pattern. For mecanum wheels, diagonal strafing is achieved by spinning specific wheels forward and others backward simultaneously.

CommandValueFRBRFLBL
Forward1FWDFWDFWDFWD
Backward2BWDBWDBWDBWD
Strafe Left3FWDBWDBWDFWD
Strafe Right4BWDFWDFWDBWD
Diagonal ↖5FWDSTOPSTOPFWD
Diagonal ↗6STOPFWDFWDSTOP
Diagonal ↙7STOPBWDBWDSTOP
Diagonal ↘8BWDSTOPSTOPBWD
Turn Left9FWDFWDBWDBWD
Turn Right10BWDBWDFWDFWD
Stop0STOPSTOPSTOPSTOP

💻 Full Source Code

Copy and paste into Arduino IDE. Update the SSID and password to match your desired network name. The WebSocket server handles all 10 movement commands plus auto-stop on disconnect.

ESP32_4WD_Robot.ino
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

// Movement command definitions
#define UP         1
#define DOWN       2
#define LEFT       3
#define RIGHT      4
#define UP_LEFT    5
#define UP_RIGHT   6
#define DOWN_LEFT  7
#define DOWN_RIGHT 8
#define TURN_LEFT  9
#define TURN_RIGHT 10
#define STOP       0

// Motor index definitions
#define FRONT_RIGHT_MOTOR 0
#define BACK_RIGHT_MOTOR  1
#define FRONT_LEFT_MOTOR  2
#define BACK_LEFT_MOTOR   3

#define FORWARD   1
#define BACKWARD -1

struct MOTOR_PINS { int pinIN1; int pinIN2; };

std::vector<MOTOR_PINS> motorPins = {
  {16, 17},  // FRONT_RIGHT_MOTOR
  {18, 19},  // BACK_RIGHT_MOTOR
  {27, 26},  // FRONT_LEFT_MOTOR
  {25, 33},  // BACK_LEFT_MOTOR
};

const char* ssid     = "MakeMindz-Robot";
const char* password = "robot12345";

AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

// ... (full HTML page and logic as shown below)

void rotateMotor(int motorNumber, int motorDirection) {
  if (motorDirection == FORWARD) {
    digitalWrite(motorPins[motorNumber].pinIN1, HIGH);
    digitalWrite(motorPins[motorNumber].pinIN2, LOW);
  } else if (motorDirection == BACKWARD) {
    digitalWrite(motorPins[motorNumber].pinIN1, LOW);
    digitalWrite(motorPins[motorNumber].pinIN2, HIGH);
  } else {
    digitalWrite(motorPins[motorNumber].pinIN1, LOW);
    digitalWrite(motorPins[motorNumber].pinIN2, LOW);
  }
}

void processCarMovement(String inputValue) {
  switch(inputValue.toInt()) {
    case UP:
      rotateMotor(FRONT_RIGHT_MOTOR, FORWARD);
      rotateMotor(BACK_RIGHT_MOTOR,  FORWARD);
      rotateMotor(FRONT_LEFT_MOTOR,  FORWARD);
      rotateMotor(BACK_LEFT_MOTOR,   FORWARD); break;
    case DOWN:
      rotateMotor(FRONT_RIGHT_MOTOR, BACKWARD);
      rotateMotor(BACK_RIGHT_MOTOR,  BACKWARD);
      rotateMotor(FRONT_LEFT_MOTOR,  BACKWARD);
      rotateMotor(BACK_LEFT_MOTOR,   BACKWARD); break;
    case LEFT:
      rotateMotor(FRONT_RIGHT_MOTOR, FORWARD);
      rotateMotor(BACK_RIGHT_MOTOR,  BACKWARD);
      rotateMotor(FRONT_LEFT_MOTOR,  BACKWARD);
      rotateMotor(BACK_LEFT_MOTOR,   FORWARD); break;
    case RIGHT:
      rotateMotor(FRONT_RIGHT_MOTOR, BACKWARD);
      rotateMotor(BACK_RIGHT_MOTOR,  FORWARD);
      rotateMotor(FRONT_LEFT_MOTOR,  FORWARD);
      rotateMotor(BACK_LEFT_MOTOR,   BACKWARD); break;
    // ... (UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT, TURN_LEFT, TURN_RIGHT)
    default:
      rotateMotor(FRONT_RIGHT_MOTOR, STOP);
      rotateMotor(BACK_RIGHT_MOTOR,  STOP);
      rotateMotor(FRONT_LEFT_MOTOR,  STOP);
      rotateMotor(BACK_LEFT_MOTOR,   STOP); break;
  }
}

void setup() {
  for (int i = 0; i < motorPins.size(); i++) {
    pinMode(motorPins[i].pinIN1, OUTPUT);
    pinMode(motorPins[i].pinIN2, OUTPUT);
    rotateMotor(i, STOP);
  }
  Serial.begin(115200);
  WiFi.softAP(ssid, password);
  Serial.print("AP IP: "); Serial.println(WiFi.softAPIP());
  ws.onEvent(onWebSocketEvent);
  server.addHandler(&ws);
  server.on("/", HTTP_GET, handleRoot);
  server.begin();
}

void loop() { ws.cleanupClients(); }
The full sketch including the embedded HTML web interface is available on the original project page.

🖥️ Run the Simulation

Open the project in one of these supported simulation platforms to test the circuit before building hardware:

🚀 Extensions & Next Steps

  • Add an HC-SR04 ultrasonic sensor for automatic obstacle detection and avoidance
  • Integrate IR line sensors under the chassis for line-following mode
  • Add a camera module (OV2640) for live FPV video streaming via the ESP32-CAM
  • Enable Bluetooth control using the ESP32's built-in BLE and a custom Android app
  • Replace breadboard wiring with a custom PCB for competition-ready builds
  • Add PWM speed control by enabling the ENA/ENB pins on the L298N with ledcWrite()

© 2026 MakeMindz.com · ESP32 4WD Robot Car Tutorial · All code MIT Licensed

Built for STEM learners, robotics enthusiasts & IoT developers.

Comments

try for free