Build Difficulty: Intermediate | Time: 2-3 Hours | Target Board: Arduino Uno R3 (Rev3)

The Verdict: Which Arduino for Robot Builds?

For a standard 2WD or 4WD beginner-to-intermediate robot, the Arduino Uno R3 (or the newer R4 Minima) is the definitive choice. It offers the perfect balance of 5V logic compatibility, physical durability, and a massive ecosystem of motor shields. If your robot requires more than three ultrasonic sensors, a LiDAR module, or complex inverse kinematics calculations, you should step up to the Arduino Mega 2560 for its 54 digital I/O pins and 16KB SRAM.

According to the official Arduino Uno R3 documentation, the board's ATmega328P microcontroller provides 6 PWM channels, which is exactly what you need to control two DC motors with speed and direction while leaving pins open for servos and sensors. Avoid the Arduino Nano for primary chassis control unless you are using a custom PCB; the breadboard-friendly Nano is too fragile for the vibration and current spikes inherent in mobile robotics.

Hardware Spec Sheet & Parts List

This build assumes a standard 2WD acrylic chassis powered by a 2S Lithium-Ion pack. Do not power the motors directly from the Arduino's 5V regulator; it will brownout the microcontroller and potentially corrupt the bootloader.

ComponentExact Variant / ModelSpecs & NotesEst. Price (2026)
MicrocontrollerArduino Uno R3 (Rev3)ATmega328P, 14 digital I/O, 6 PWM$27.00
Motor DriverL298N Dual H-Bridge Module2A per channel, 5V logic. See STMicro L298 Datasheet$6.50
Chassis & Motors2WD Acrylic Kit with TT Motors3-6V DC, 200 RPM no-load, 1:48 gear ratio$15.00
RangefinderHC-SR04 Ultrasonic Sensor2cm-400cm range, 5V trigger/echo$3.00
Power Supply2x 18650 Battery Holder + Cells7.4V nominal (8.4V fully charged), 5000mAh$18.00
Wiring22 AWG Silicone Wire + DupontStranded for vibration resistance$8.00
Safety Warning: When using raw 18650 lithium cells, always include an inline fuse (5A) on the positive terminal and never mix cells with different capacities or charge states. A short circuit on an unprotected 2S pack can cause a thermal event.

Pin Mapping & Wiring Steps

Proper pin assignment is critical. The L298N requires PWM pins for speed control (ENA/ENB) and standard digital pins for logic direction (IN1-IN4).

Arduino Uno PinL298N / Sensor PinFunction
D5 (PWM)ENALeft Motor Speed
D6 (PWM)ENBRight Motor Speed
D8IN1Left Motor Direction A
D7IN2Left Motor Direction B
D4IN3Right Motor Direction A
D2IN4Right Motor Direction B
D9HC-SR04 TrigUltrasonic Trigger
D10HC-SR04 EchoUltrasonic Echo
GNDGND (L298N & Sensor)Common Ground (Critical)

Numbered Wiring Steps:

  1. Establish Common Ground: Connect the GND pin of the Arduino to the GND terminal on the L298N module. If you skip this, the logic signals will float and the motors will spin erratically or not at all.
  2. Power the Driver: Connect the positive terminal of your 2S 18650 pack (7.4V-8.4V) to the 12V terminal on the L298N. Leave the 5V jumper on the L298N in place; the module's onboard 7805 regulator will drop the battery voltage to 5V to power the Arduino via the L298N's 5V output pin.
  3. Wire the Motors: Connect the left TT motor to OUT1 and OUT2. Connect the right TT motor to OUT3 and OUT4. Polarity doesn't matter yet; we will fix reversed motors in software.
  4. Connect Logic Pins: Use female-to-male Dupont jumpers to connect the Arduino digital pins to the L298N IN1-IN4 and ENA/ENB pins as per the table above.
  5. Mount the Sensor: Wire the HC-SR04 VCC to the Arduino 5V, GND to GND, Trig to D9, and Echo to D10.

Compilable Motor Control Code

The following C++ code targets the Arduino Uno R3. It implements a basic obstacle-avoidance routine. It includes explicit error handling for the pulseIn() function, which can hang the microcontroller if the ultrasonic sensor fails to receive an echo (a common issue with soft or angled surfaces).

// Pin Definitions
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
const int ENA = 5;
const int IN1 = 8;
const int IN2 = 7;
const int ENB = 6;
const int IN3 = 4;
const int IN4 = 2;

// Constants
const int MOTOR_SPEED = 180; // PWM value (0-255)
const int STOP_DISTANCE_CM = 25;

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  
  Serial.begin(9600);
  stopMotors();
  Serial.println("Robot Initialized.");
}

// Returns distance in cm, or -1 if timeout/error occurs
long getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // 30000 microsecond timeout prevents infinite blocking
  long duration = pulseIn(ECHO_PIN, HIGH, 30000); 
  
  if (duration == 0) {
    Serial.println("Error: Ultrasonic timeout or out of range.");
    return -1; 
  }
  // Speed of sound is ~34.3 cm/ms -> 0.0343 cm/us
  return (duration * 0.0343) / 2; 
}

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

void stopMotors() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

void loop() {
  long distance = getDistance();
  
  // Error handling: if sensor fails (-1), stop to prevent collision
  if (distance == -1) {
    stopMotors();
    delay(500);
    return;
  }
  
  if (distance > STOP_DISTANCE_CM) {
    moveForward(MOTOR_SPEED);
  } else {
    stopMotors();
    delay(200); // Brief pause before next loop cycle
  }
}

Troubleshooting: When the Robot Won't Move

When your robot fails to operate, follow this decision path. Before diving into code rewrites, perform the First 3 Things to Check:

  1. The Common Ground: Use your multimeter in continuity mode. Place one probe on the Arduino GND pin and the other on the L298N GND screw terminal. It must read less than 1 ohm.
  2. Battery Voltage Under Load: Measure the 18650 pack voltage while the motors are stalled or trying to spin. If a 7.4V pack drops below 6.0V under load, the L298N's internal logic will brownout and shut down.
  3. PWM vs Digital Assignment: Verify that ENA and ENB are connected to pins with the tilde (~) symbol (D5, D6). If they are on standard digital pins, analogWrite() will just output a static 5V HIGH, giving you only 100% speed or 0% speed.

Common IDE Error Strings

Error 1: avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00

  • Cause A: The wrong COM port is selected in the Arduino IDE.
  • Cause B: The HC-SR04 Echo pin (D10) is shorted to ground, preventing the ATmega16U2 USB-Serial chip from resetting the main MCU during upload. Disconnect the sensor and try uploading again.

Error 2: exit status 1 paired with 'NewPing' was not declared in this scope

  • Cause: You copied code from a forum that relies on the NewPing library, but haven't installed it via the Library Manager. The code provided in this article uses raw pulseIn() specifically to avoid this dependency error.

Extending and Simplifying the Build

How to Simplify: If wiring the raw L298N module feels messy, swap it for the Adafruit Motor Shield V2. It stacks directly onto the Uno, handles up to 4 DC motors via I2C (freeing up your PWM pins), and includes built-in flyback diodes and thermal shutdown. It costs roughly $24, but saves an hour of wiring and debugging.

How to Extend: Once basic obstacle avoidance is working, add an MPU6050 IMU (Accelerometer/Gyroscope) via I2C on pins A4 (SDA) and A5 (SCL). This allows you to implement PID control to drive in a perfectly straight line, compensating for the manufacturing tolerances in cheap TT motors that usually cause the robot to veer to one side.

Arduino for Robot FAQ

Is an Arduino Nano powerful enough for a robot?

Electrically, the Arduino Nano has the exact same ATmega328P microcontroller as the Uno, meaning it runs the same code and handles the same logic. However, mechanically, it is a poor choice for a primary robot controller. The Nano relies on breadboards or fragile solder joints to interface with motor drivers, which will quickly vibrate loose on a moving chassis. Use the Nano only if you are designing a custom printed circuit board (PCB) where the Nano acts as a surface-mount daughterboard.

Why does my Arduino reset when the robot motors start?

This is caused by voltage sag and electromagnetic interference (EMI). When DC motors start, they draw a massive inrush current (often 5x their stall current). If your battery pack cannot supply this current, the voltage drops below the Arduino's brownout threshold (typically ~4.3V for the 5V regulator), causing a reset. Furthermore, the brushed TT motors generate severe EMI. To fix this, solder 0.1µF ceramic capacitors directly across the motor terminals, and ensure your battery pack has a high continuous discharge rating (at least 10A for a 2WD setup).

Can I use an ESP32 instead of an Arduino for robot control?

Yes, but with caveats. The ESP32 is vastly more powerful (240MHz dual-core vs 16MHz single-core) and includes native WiFi/Bluetooth. However, the ESP32 operates on 3.3V logic, while the standard L298N module and HC-SR04 sensor expect 5V logic. Connecting a 5V Echo pin directly to an ESP32 GPIO will permanently destroy the pin. If you choose the ESP32, you must use a logic level shifter for the ultrasonic sensor, or switch to 3.3V-compatible sensors like the VL53L0X Time-of-Flight LiDAR module.