DIY 2WD robot car chassis kit with yellow TT gear motors, wheels, battery box, ESP32-S3 and TB6612FNG driver

Intermediate

Build a Two-Wheel Robot Car

RoboticsMotorsMotion

Turn code into motion -- wire up a real motor driver and chassis and watch your program actually drive something.

6 real parts included

Total for this kit: 1,568.00 ฿

Doesn't include any order discount you may get at checkout.

What you'll need

Project Goal

This project turns a robot chassis into something that actually drives under your own code, combining a controller, a motor driver, and two DC motors into one coordinated machine. It's the first project in the robotics track because it introduces motor control specifically -- an output type that's fundamentally different from switching a light or driving a display.

What the Controller Does

The controller decides where the robot should go and translates that decision into signals the motor driver understands -- a direction for each wheel and a speed for each wheel, updated continuously as the program runs. An ESP32-S3 is used here rather than a smaller board like the ESP32-C3 specifically for its extra GPIO headroom: a motor driver alone needs several pins, and leaving room for a future sensor upgrade (like the line-following project's sensor array) matters from the start.

What the Motor Driver Does

The TB6612FNG sits between the controller and the motors and does the actual work of driving them. It's a MOSFET-based driver, which is genuinely more power-efficient than an older linear driver design like the L298N -- less energy wasted as heat, which matters directly on a battery-powered chassis. The controller never drives the motors' higher-current supply directly; it only ever sends the driver low-power logic signals.

What the Chassis and Motors Do

The chassis holds the two DC gear motors, wheels, and battery box in a fixed physical layout, and translates each motor's rotation into the robot's actual movement -- turning by running each wheel at a different speed or in different directions rather than through any separate steering mechanism.

Motor Driver Wiring Basics

Each motor channel on the TB6612FNG needs two things from the controller: a direction signal (which way should this wheel turn) and a PWM speed signal (how fast). Just as important is what's wired separately: the motor supply -- the 18650 battery pack -- powers the motors themselves, while the controller's own logic power comes from its USB connection. Keeping motor power and logic power on separate rails is standard practice; it protects the controller's more sensitive logic pins from the electrical noise a motor's current draw can create.

Software and Library Concepts

Most motor driver libraries expose a simple function per motor: set a direction and a speed value, and the library handles the underlying PWM and direction-pin logic for you. Start by getting each motor spinning independently and confirm both directions work before writing any higher-level driving logic (forward, turn, stop) on top.

Testing and Troubleshooting

  • Motors don't turn at all -- check the battery and driver wiring before assuming it's a code bug; a driver with no motor power will accept commands silently and do nothing.
  • One motor spins the wrong direction -- either swap that motor's two leads at the driver, or flip the direction logic for that motor in code; both fixes are equally valid.
  • Movement is erratic or weak -- check the battery's charge level and voltage; insufficient power is a very common cause that gets mistaken for a code problem.
  • Robot drives in a curve instead of straight -- confirm both motors are actually receiving the same speed value, since even small differences between two DC motors can pull a two-wheel chassis off a straight line.

Optional Future Upgrade: Line-Following Robot

This exact chassis and TB6612FNG driver are reused directly in the Line-Following Robot project, which adds a line-sensor array on top of the same drive base -- once you're comfortable with basic motor control here, that's a natural next step rather than a restart.

Wiring

  • TB6612FNG VM → 18650 battery holder (+) — through the holder's power switch — motor supply, kept separate from logic power
  • TB6612FNG GND → battery holder (−) AND ESP32-S3 GND — common ground is required across battery, driver, and controller
  • TB6612FNG VCC → ESP32-S3 3V3 — logic-level supply for the driver chip
  • TB6612FNG STBY → ESP32-S3 GPIO7 — must be driven HIGH to take the driver out of standby
  • TB6612FNG AIN1 → ESP32-S3 GPIO4 — motor A direction
  • TB6612FNG AIN2 → ESP32-S3 GPIO5 — motor A direction
  • TB6612FNG PWMA → ESP32-S3 GPIO6 — motor A speed/enable
  • TB6612FNG BIN1 → ESP32-S3 GPIO15 — motor B direction
  • TB6612FNG BIN2 → ESP32-S3 GPIO16 — motor B direction
  • TB6612FNG PWMB → ESP32-S3 GPIO17 — motor B speed/enable
  • TB6612FNG A01/A02 → left DC gear motor (chassis kit) — two wires, either polarity (swap if it spins the wrong way)
  • TB6612FNG B01/B02 → right DC gear motor (chassis kit)
  • ESP32-S3 Dev Board → USB-C cable → computer (programming only; run untethered from the battery holder once flashed)

GPIO numbers above are generic safe choices — ESP32-S3 dev boards vary by vendor, so confirm each pin against your specific board's pinout diagram and avoid any pin marked as reserved for flash/PSRAM (typically GPIO26-32 on boards with octal PSRAM) or USB (GPIO19/20 on many S3 boards). This starter code drives PWMA/PWMB pins fully HIGH for constant full-speed motion rather than variable-speed PWM, keeping the example simple and avoiding ambiguity between different ESP32 Arduino core PWM APIs — swap in `ledcAttach()`/`ledcWrite()` speed control once you're ready to go beyond on/off. STBY must be HIGH before the motors will respond at all, and it's worth wiring/testing that pin first when bringing up the driver. Adding a remote input (BLE or Wi-Fi) or a line-sensor add-on (see the line-following-robot project) are natural next steps once this pattern runs reliably.

Wiring Diagram

VM GND VCC → 3V3 STBY → GPIO7 AIN1 → GPIO4 AIN2 → GPIO5 PWMA → GPIO6 BIN1 → GPIO15 BIN2 → GPIO16 PWMB → GPIO17 A01/A02 B01/B02 ESP32-S3 TB6612FNG USB-C cable 18650 battery holder battery holder left DC gear motor right DC gear motor

Starter Code

// Two-Wheel Robot Car — ESP32-S3 + TB6612FNG
// Basic starter: runs a fixed forward/stop/turn test pattern on loop.

// --- Pins — adjust to match your specific ESP32-S3 dev board's pinout ---
#define STBY 7
#define AIN1 4
#define AIN2 5
#define PWMA 6
#define BIN1 15
#define BIN2 16
#define PWMB 17

void motorA(bool forward, bool run) {
  digitalWrite(AIN1, run ? (forward ? HIGH : LOW) : LOW);
  digitalWrite(AIN2, run ? (forward ? LOW : HIGH) : LOW);
  digitalWrite(PWMA, run ? HIGH : LOW); // full speed when running
}

void motorB(bool forward, bool run) {
  digitalWrite(BIN1, run ? (forward ? HIGH : LOW) : LOW);
  digitalWrite(BIN2, run ? (forward ? LOW : HIGH) : LOW);
  digitalWrite(PWMB, run ? HIGH : LOW);
}

void stopMotors() {
  motorA(true, false);
  motorB(true, false);
}

void driveForward() {
  motorA(true, true);
  motorB(true, true);
}

void turnLeft() {
  // Left motor reverse/stopped, right motor forward = pivot left
  motorA(false, true);
  motorB(true, true);
}

void turnRight() {
  motorA(true, true);
  motorB(false, true);
}

void setup() {
  pinMode(STBY, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(PWMB, OUTPUT);

  digitalWrite(STBY, HIGH); // take the driver out of standby
  stopMotors();
}

void loop() {
  driveForward();
  delay(1500);

  stopMotors();
  delay(500);

  turnRight();
  delay(600);

  stopMotors();
  delay(500);

  turnLeft();
  delay(600);

  stopMotors();
  delay(1000);
}

Not sure about a step? Ask us