When browsing robot project ideas, the most expensive mistake makers make is picking the wrong microcontroller for the payload. A Raspberry Pi 5 is massive overkill for a simple line follower, while an Arduino Uno lacks the SRAM and clock speed for simultaneous SLAM mapping and motor control. You end up either starving your robot of compute or drowning in unnecessary Linux overhead.

This guide provides a concrete decision path to select your board, followed by a complete, debug-ready build for one of the most versatile robot project ideas: an ESP32 BLE-controlled Mecanum wheel rover. We will cover exact part numbers, wiring pitfalls specific to the ESP32 architecture, and the exact firmware needed to keep the motors running without triggering a watchdog panic.

Decision Matrix: Matching Robot Project Ideas to the Right Brain

Before buying parts, run your concept through this decision tree. The goal is to match your sensor payload and control loop requirements to the silicon that handles it natively.

Project Type Compute / I/O Need Best Board Variant Why This Board Wins
Line Follower / Sumo Bot Low (IR sensors, simple PID) Arduino Nano V3 (ATmega328P) Deterministic loop times, simple 5V logic, no RTOS overhead.
BLE/WiFi Rover / Robot Arm Medium (Telemetry, PWM, IMU) ESP32-WROOM-32 DevKit v1 Dual-core 240MHz, native BLE/WiFi, 520KB SRAM, $6 price point.
Vision / ROS2 Autonomous Nav High (OpenCV, LiDAR, SLAM) Raspberry Pi 5 (4GB) + ESP32 bridge Linux environment, Python/C++ ROS2 nodes, hardware video decode.
The Decision Path:
  • If your robot needs heavy vision processing or ROS2 nodes → Pick the Raspberry Pi 5.
  • If your robot is purely reactive (no wireless telemetry, just IR/ultrasonic) → Pick the Arduino Nano V3.
  • If your robot needs wireless control, telemetry, and strict real-time motor PWM → Pick the ESP32-WROOM-32 DevKit v1.

Concrete Default: For 80% of intermediate robot project ideas, the ESP32-WROOM-32 DevKit v1 is the undisputed winner. It bridges the gap between bare-metal microcontrollers and single-board computers.

The Build: ESP32 BLE Mecanum Rover (Parts & Specs)

For this build, we are using a 4-wheel Mecanum drivetrain. Mecanum wheels allow holonomic movement (strafing sideways, spinning in place) which is excellent for learning inverse kinematics. We are deliberately avoiding the ubiquitous L298N motor driver. The L298N uses a BJT H-bridge that drops 2V to 3V across the IC. On a 7.4V LiPo, your 6V motors will only see ~4.5V under load. Instead, we use the TB6612FNG, which uses MOSFETs and drops only ~0.5V.

Spec-Sheet & Parts List

Component Exact Variant / Model Est. Cost Key Specification
Microcontroller ESP32-WROOM-32 DevKit v1 (30-pin) $6.00 Dual-core 240MHz, 520KB SRAM, BLE 4.2
Motor Driver TB6612FNG Dual Motor Driver (SparkFun/Pololu) $4.50 1.2A continuous, 3.2A peak, 0.5V dropout
Motors & Wheels 4x N20 6V 300RPM Gear Motors + 48mm Mecanum Wheels $22.00 1:150 gear ratio, 6V nominal
Power 2S 7.4V 1000mAh LiPo (e.g., Zippy Compact) $11.00 20C discharge rate (20A max burst)
IMU MPU-6050 Breakout (GY-521) $3.00 3-axis gyro, 3-axis accel, I2C

Wiring and Pin Mapping

The ESP32 has a notorious quirk: ADC2 pins conflict with the WiFi/BLE radio. If you use an ADC2 pin for PWM while BLE is active, the radio will silently fail or the pin will output garbage. Furthermore, you must avoid strapping pins (GPIO 0, 2, 12, 15) which dictate boot modes. The mapping below uses only BLE-safe, non-strapping pins.

Callout Tip: Never power the motors through the ESP32's onboard 5V regulator. The AMS1117 on the DevKit will overheat and shut down at ~800mA. Wire the LiPo directly to the TB6612FNG VM pin, and use a separate buck converter (or the DevKit's USB) for the ESP32 logic power.
ESP32 GPIO TB6612FNG Pin Function Notes
GPIO 25PWMALeft Motor SpeedADC1 safe, BLE safe
GPIO 26PWMBRight Motor SpeedADC1 safe, BLE safe
GPIO 27AIN1 / BIN1Direction Control 1Digital Out
GPIO 14AIN2 / BIN2Direction Control 2Digital Out
3.3VVCC & STBYLogic & StandbySTBY must be HIGH to enable
GNDGNDCommon GroundMust share ground with LiPo

Note: For a 4-wheel Mecanum setup, you will daisy-chain the left-front and left-rear motors to Channel A, and the right-front and right-rear to Channel B. Ensure the wheel rollers form an 'X' pattern when viewed from above.

Firmware: BLE Motor Control with Watchdog Error Handling

This code targets the ESP32 Dev Module (ESP32-WROOM-32) board variant in the Arduino IDE. It uses the ESP32's LEDC peripheral for hardware PWM and implements a Task Watchdog Timer (TWDT) to ensure the motors stop if the BLE stack hangs.

/*
 * Target Board: ESP32 Dev Module (ESP32-WROOM-32)
 * Core: Espressif Systems ESP32 Arduino Core v2.x or v3.x
 * Project: BLE Mecanum Rover Base
 */

#include 
#include 

// --- Pin Definitions (BLE/ADC1 Safe) ---
const int PIN_PWM_A = 25;
const int PIN_PWM_B = 26;
const int PIN_DIR_1 = 27;
const int PIN_DIR_2 = 14;
const int PIN_STBY  = 32; // Additional GPIO to control STBY if needed

// PWM Configuration
const int PWM_FREQ = 1000;
const int PWM_RES  = 8;   // 0-255

BluetoothSerial SerialBT;

// Watchdog timeout in seconds
#define WDT_TIMEOUT 3

void setup() {
  Serial.begin(115200);
  
  // Initialize Task Watchdog Timer
  esp_task_wdt_init(WDT_TIMEOUT, true); // Panic if WDT triggers
  esp_task_wdt_add(NULL); // Add current thread to WDT

  // Configure Motor Pins
  pinMode(PIN_DIR_1, OUTPUT);
  pinMode(PIN_DIR_2, OUTPUT);
  pinMode(PIN_STBY, OUTPUT);
  
  // LEDC setup for PWM
  ledcAttach(PIN_PWM_A, PWM_FREQ, PWM_RES);
  ledcAttach(PIN_PWM_B, PWM_FREQ, PWM_RES);
  
  digitalWrite(PIN_STBY, HIGH); // Take TB6612FNG out of standby
  
  // Start BLE
  SerialBT.begin("FluxRover");
  Serial.println("BLE Started. Waiting for connection...");
}

void loop() {
  // Reset Watchdog Timer
  esp_task_wdt_reset();

  if (SerialBT.available()) {
    char cmd = SerialBT.read();
    
    // Simple UART protocol: 'F'wd, 'B'wd, 'L'eft, 'R'ight, 'S'top
    switch(cmd) {
      case 'F': drive(200, 200); break;
      case 'B': drive(-200, -200); break;
      case 'L': drive(-100, 100); break;
      case 'R': drive(100, -100); break;
      case 'S': drive(0, 0); break;
      default: drive(0, 0); break; // Failsafe
    }
  } else {
    // If BLE disconnects, SerialBT.available() might not catch it immediately.
    // A robust build would check SerialBT.hasClient() and stop motors if false.
    if(!SerialBT.hasClient()) {
      drive(0, 0);
    }
  }
  
  delay(20); // Yield to RTOS
}

void drive(int speedA, int speedB) {
  // Motor A (Left)
  if (speedA >= 0) {
    digitalWrite(PIN_DIR_1, HIGH);
    ledcWrite(PIN_PWM_A, speedA);
  } else {
    digitalWrite(PIN_DIR_1, LOW);
    ledcWrite(PIN_PWM_A, abs(speedA));
  }
  
  // Motor B (Right)
  if (speedB >= 0) {
    digitalWrite(PIN_DIR_2, HIGH);
    ledcWrite(PIN_PWM_B, speedB);
  } else {
    digitalWrite(PIN_DIR_2, LOW);
    ledcWrite(PIN_PWM_B, abs(speedB));
  }
}

Debugging: First Three Things to Check When It Fails

When your rover fails to move or the ESP32 reboots mid-drive, do not guess. Check these three specific failure modes in order.

1. The Brownout Reboot Loop

Exact Error String: Brownout detector was triggered (followed by a stack trace and reboot).

Cause: When four N20 motors start simultaneously from a dead stop, they draw a stall current of >2.5A. This causes a massive voltage sag on the LiPo. If the ESP32's VCC drops below ~2.4V even for a microsecond, the internal brownout detector triggers a hardware reset.

Fix:

  • Solder a 470µF electrolytic capacitor directly across the ESP32's 5V and GND pins on the DevKit.
  • Ensure your LiPo's C-rating is adequate (a 1000mAh 20C battery can deliver 20A bursts).
  • Implement soft-start in code (ramp PWM from 0 to 200 over 200ms) to limit inrush current.

2. The Watchdog Panic

Exact Error String: Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)

Cause: The ESP32 runs FreeRTOS. By default, Arduino code runs on Core 1, alongside the WiFi/BLE stack. If your motor control loop or I2C IMU reads block for too long, the BLE stack starves, and the Interrupt Watchdog Timer (IWDT) panics and reboots the chip to prevent a total lockup.

Fix: Keep your loop() function non-blocking. Never use delay() for more than a few milliseconds. If you are reading an MPU-6050 over I2C, ensure you are not waiting indefinitely for the data-ready interrupt. Add esp_task_wdt_reset() in your main loop as shown in the code above.

3. Motors Hum but Do Not Spin

Symptom: The TB6612FNG gets warm, motors vibrate, but no rotation.

Cause: The TB6612FNG STBY (Standby) pin is floating or pulled LOW. Unlike the L298N, the TB6612FNG requires the STBY pin to be pulled HIGH to enable the H-bridges.

Fix: Wire the STBY pin directly to the ESP32's 3.3V pin, or assign it to a GPIO and set it HIGH in setup(). Verify with a multimeter that STBY reads >3.0V relative to GND.

Scaling the Build: Extend or Simplify

Once the base rover is navigating your workbench, you will inevitably want to modify it. Here is how to scale the hardware based on your next iteration.

Simplify (Budget / Education)

Drop the Mecanum wheels for standard rubber traction wheels. Swap the TB6612FNG for an L298N module if you already have one in your parts bin, but be aware you will need to step up to a 3S (11.1V) LiPo to overcome the 2.5V voltage drop across the BJT H-bridges. Use a standard Arduino Nano if you decide to strip out BLE and rely purely on HC-SR04 ultrasonic sensors for obstacle avoidance.

Extend (Advanced / ROS2)

Upgrade the microcontroller to the ESP32-S3-WROOM-1. The S3 variant includes vector instructions for AI acceleration and native USB, making it ideal for running micro-ROS over WiFi to a Raspberry Pi host. Swap the MPU-6050 for a BNO085 IMU, which features an onboard Cortex-M0+ that handles sensor fusion, outputting clean quaternions over I2C without bogging down the ESP32's CPU.

By matching your microcontroller to the actual compute requirements of your robot project ideas, you eliminate the friction of underpowered hardware and bloated software stacks. Wire it cleanly, respect the ESP32's pin constraints, and your rover will be strafing across the floor in an afternoon.