The most effective starting point for robotics projects for beginners in 2026 is a 2WD differential-drive rover. While older tutorials default to the L298N motor driver, that chip is a thermal bottleneck that wastes battery life as heat. For a modern, efficient build, we pair the Arduino Uno R4 WiFi with a TB6612FNG dual MOSFET motor driver and an HC-SR04 ultrasonic sensor. This combination provides 95% power efficiency, native serial debugging, and enough processing headroom to add WiFi telemetry later.
Why the TB6612FNG Beats the L298N for Beginner Rovers
Most beginner kits ship with the L298N. It is cheap, robust, and completely inefficient. The L298N uses Bipolar Junction Transistors (BJTs) which inherently drop about 2.0V to 3.0V across the H-bridge. If you feed it 6V from a 4xAA battery pack, your motors only see 3.5V, resulting in sluggish movement and rapid battery drain. The TB6612FNG uses MOSFETs, dropping only about 0.5V at typical loads, keeping your motors running at full voltage.
| Driver IC | Architecture | Max Continuous Current | Logic/Motor Voltage | Efficiency / Voltage Drop | Best Use Case |
|---|---|---|---|---|---|
| L298N | BJT H-Bridge | 2.0A per channel | 5V-35V / 5V Logic | ~60% (Drops 2.0V - 3.0V) | High-voltage (12V+) heavy motors |
| TB6612FNG | MOSFET H-Bridge | 1.2A cont. (3.2A peak) | 2.5V-13.5V / 2.7V-5.5V Logic | ~95% (Drops ~0.5V) | 3V-6V TT gearmotors (Ideal for R4) |
| DRV8833 | MOSFET H-Bridge | 1.5A cont. (2.0A peak) | 2.7V-10.8V / No separate logic | ~90% (Drops ~0.8V) | Compact builds, low pin-count |
| DRV8871 | MOSFET H-Bridge | 3.6A cont. | 6.5V-45V / No separate logic | ~95% (Drops ~0.4V) | Single high-power motor (1 channel) |
For standard 130-size yellow TT gearmotors (which stall around 800mA), the TB6612FNG is the sweet spot. It handles the stall current safely while maximizing the runtime of a 2S LiPo or 4xAA NiMH pack.
Parts List and Pin Mapping for the 2WD Rover
Before wiring, verify you have the exact board variants listed below. The Arduino Uno R4 WiFi has a different pinout and PWM behavior compared to the older R3, and the TB6612FNG requires careful separation of motor power (VMOT) and logic power (VCC).
Bill of Materials (BOM)
- Microcontroller: Arduino Uno R4 WiFi (Part: ABX00087) — ~$27.50
- Motor Driver: TB6612FNG Dual Motor Driver Carrier (Pololu 713 or SparkFun ROB-14451) — ~$6.00
- Sensor: HC-SR04 Ultrasonic Distance Sensor (Standard 4-pin) — ~$2.00
- Actuators: 2x 130-size TT Gearmotors with 60x25mm wheels — ~$8.00/pair
- Servo: SG90 9g Micro Servo (for sensor panning) — ~$3.00
- Power: 2S 7.4V 1000mAh LiPo battery with XT60 connector, or 4xAA NiMH battery holder — ~$12.00
- Chassis: 2WD Acrylic or ABS rover chassis kit with castor wheel
Use 18 AWG silicone wire for the battery to TB6612FNG VMOT terminals to prevent voltage sag under stall conditions. Use 22 AWG solid-core wire for all logic connections to the Arduino R4 GPIO pins.
Pin Mapping Table
This mapping targets the Arduino Uno R4 WiFi. The R4 uses a Renesas RA4M1 processor, which maps PWM differently than the ATmega328P. Pins 3, 5, 6, and 9 are hardware PWM capable on the R4.
| Arduino R4 Pin | Direction | Target Module | Target Pin | Function / Notes |
|---|---|---|---|---|
| 5V | OUT | TB6612FNG | VCC | Logic power for the driver IC |
| GND | OUT | TB6612FNG | GND | Common ground (CRITICAL) |
| D5 (PWM) | OUT | TB6612FNG | PWMA | Speed control for Motor A (Right) |
| D4 | OUT | TB6612FNG | AIN1 | Direction control 1 for Motor A |
| D7 | OUT | TB6612FNG | AIN2 | Direction control 2 for Motor A |
| D6 (PWM) | OUT | TB6612FNG | PWMB | Speed control for Motor B (Left) |
| D8 | OUT | TB6612FNG | BIN1 | Direction control 1 for Motor B |
| D9 | OUT | TB6612FNG | BIN2 | Direction control 2 for Motor B |
| D2 | OUT | HC-SR04 | Trig | Ultrasonic trigger pulse |
| D3 | IN | HC-SR04 | Echo | Ultrasonic echo return (5V tolerant on R4) |
| D10 (PWM) | OUT | SG90 Servo | Signal | Pan servo for ultrasonic sensor |
Assembly Steps and Power Management
Follow this sequence to avoid ground loops and brownouts. The Arduino R4 WiFi has a strict 5V logic level, and the TB6612FNG must share a common ground with the microcontroller to read logic signals correctly.
- Mount the Motor Driver: Secure the TB6612FNG breakout to the chassis. Connect the battery positive (red) to VMOT and battery negative (black) to the driver's GND terminal. Do not connect the battery to the Arduino's VIN pin; the R4's onboard regulator will overheat at 7.4V with motors running.
- Establish Common Ground: Run a 22 AWG jumper wire from the TB6612FNG GND pin to any Arduino R4 GND pin. If you skip this, the driver will not recognize the HIGH/LOW signals from the GPIO pins.
- Wire Logic and PWM: Connect the VCC pin on the TB6612FNG to the Arduino's 5V pin. Connect the AIN/BIN and PWMA/PWMB pins according to Table 2.
- Install the Servo and Sensor: Mount the SG90 servo to the front of the chassis. Plug the servo's brown wire to GND, red to 5V, and orange to D10. Mount the HC-SR04 onto the servo horn.
- Power Verification: Before plugging in the Arduino USB, use a multimeter to measure voltage across the TB6612FNG VMOT and GND terminals. You should read between 7.2V and 8.4V for a fully charged 2S LiPo.
Complete Obstacle Avoidance Code (Arduino Uno R4 WiFi)
This code targets the Arduino Uno R4 WiFi. It uses raw pulseIn() timing for the HC-SR04 to avoid external library dependencies, and includes explicit timeout error handling. If the sensor fails to receive an echo (e.g., sound absorbs into soft fabric), the code catches the timeout, prints an exact error string to the serial monitor, and triggers a backup maneuver.
// Robotics Projects for Beginners: 2WD Obstacle Avoidance Rover
// Target Board: Arduino Uno R4 WiFi
// Motor Driver: TB6612FNG
#include
// --- Pin Definitions ---
#define PWMA 5
#define AIN1 4
#define AIN2 7
#define PWMB 6
#define BIN1 8
#define BIN2 9
#define STBY 11 // Standby pin on TB6612FNG (tie to 5V or control via GPIO)
#define TRIG_PIN 2
#define ECHO_PIN 3
#define SERVO_PIN 10
// --- Constants ---
const int MOTOR_SPEED = 200; // PWM value (0-255)
const int TURN_SPEED = 150;
const int SAFE_DISTANCE_CM = 25;
const unsigned long ECHO_TIMEOUT_US = 25000; // ~4.2 meters max range
Servo panServo;
void setup() {
Serial.begin(115200);
// Initialize Motor Pins
pinMode(PWMA, OUTPUT); pinMode(AIN1, OUTPUT); pinMode(AIN2, OUTPUT);
pinMode(PWMB, OUTPUT); pinMode(BIN1, OUTPUT); pinMode(BIN2, OUTPUT);
pinMode(STBY, OUTPUT);
digitalWrite(STBY, HIGH); // Take TB6612FNG out of standby mode
// Initialize Sensor Pins
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
panServo.attach(SERVO_PIN);
panServo.write(90); // Center servo
delay(500);
Serial.println("System Initialized: 2WD Rover Ready");
}
void loop() {
int distance = getDistance();
if (distance > SAFE_DISTANCE_CM || distance == -1) {
// Path is clear or sensor error (fail-safe: keep moving slowly or stop)
if (distance == -1) {
stopMotors();
delay(200);
} else {
driveForward(MOTOR_SPEED);
}
} else {
// Obstacle detected
stopMotors();
navigateObstacle();
}
}
// --- Sensor Function with Error Handling ---
int getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long duration = pulseIn(ECHO_PIN, HIGH, ECHO_TIMEOUT_US);
if (duration == 0) {
Serial.println("[ERR] HC-SR04 Echo Timeout > 25ms - Check Trig/Echo wiring or 5V rail");
return -1; // Return -1 to indicate error
}
int distance_cm = duration * 0.034 / 2;
return distance_cm;
}
// --- Navigation Logic ---
void navigateObstacle() {
panServo.write(20); // Look Right
delay(400);
int rightDist = getDistance();
panServo.write(160); // Look Left
delay(400);
int leftDist = getDistance();
panServo.write(90); // Center
delay(300);
if (rightDist > leftDist) {
turnRight(TURN_SPEED);
} else {
turnLeft(TURN_SPEED);
}
}
// --- Motor Control Functions ---
void driveForward(int speed) {
digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW);
digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW);
analogWrite(PWMA, speed); analogWrite(PWMB, speed);
}
void turnRight(int speed) {
digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); // Right motor backward
digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); // Left motor forward
analogWrite(PWMA, speed); analogWrite(PWMB, speed);
delay(400);
stopMotors();
}
void turnLeft(int speed) {
digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); // Right motor forward
digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); // Left motor backward
analogWrite(PWMA, speed); analogWrite(PWMB, speed);
delay(400);
stopMotors();
}
void stopMotors() {
digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW);
digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW);
analogWrite(PWMA, 0); analogWrite(PWMB, 0);
}
Debugging: Motor Jitters but Rover Won't Move
A common failure mode in beginner robotics is the 'humming rover'—the motors emit a high-pitch whine or jitter, but the wheels refuse to turn. If you see the serial monitor output [ERR] HC-SR04 Echo Timeout > 25ms alongside this hardware symptom, you have a power delivery or logic reference issue.
The First Three Things to Check When It Fails
- Measure VMOT Under Load: Connect your multimeter probes directly to the TB6612FNG VMOT screw terminals while the code is running. If the voltage drops below 2.5V when the motors attempt to spin, your battery cannot supply the stall current, or your wires are too thin (voltage sag). Upgrade to a higher C-rating LiPo or thicker 18 AWG wires.
- Verify Common Ground: Measure the resistance between the Arduino R4 GND pin and the TB6612FNG GND pin with the power disconnected. It must read less than 1 ohm. Without a shared ground, the 5V logic signals from the Arduino float relative to the driver, causing erratic MOSFET switching (the jitter).
- Check the STBY Pin: The TB6612FNG has a Standby (STBY) pin. If left floating, it can pick up EMI from the motors and randomly put the chip to sleep. The code above ties STBY to D11 and sets it HIGH. If you wired STBY directly to 5V, verify that solder joint is solid.
Extending and Simplifying the Build
Once the base rover is navigating reliably, you can adapt the project to match your skill level or specific goals.
How to Simplify
If the SG90 servo and panning logic are causing timing delays or mechanical failures, remove the servo entirely. Mount the HC-SR04 rigidly to the front chassis. Modify the navigateObstacle() function to simply reverse for 500ms, turn right 90 degrees, and resume driving. This eliminates the 1.1 seconds of delay caused by the servo sweeping left and right, resulting in a much faster, 'bump-and-run' style rover.
How to Extend
To transition this from a beginner project to an intermediate autonomous platform, integrate an MPU6050 IMU (Inertial Measurement Unit) via the I2C bus (SDA to A4, SCL to A5 on the R4). By fusing the accelerometer and gyroscope data, you can implement dead-reckoning. This allows the rover to track its exact X/Y coordinates on a 2D plane, enabling you to program waypoint navigation rather than simple reactive obstacle avoidance. You can also leverage the Arduino R4 WiFi's native ESP32-S3 coprocessor to stream the HC-SR04 distance data and MPU6050 telemetry over MQTT to a local dashboard.






