When tackling autonomous raspberry pi robot projects, the gap between a bench prototype and a rover that actually navigates a room usually comes down to three things: power delivery, logic-level matching, and sensor polling rates. The Raspberry Pi 5 (8GB) is the current baseline for edge-compute robotics in 2026, offering enough PCIe and USB 3.0 bandwidth to handle simultaneous LIDAR sweeps and motor control without dropping packets.

This guide walks through building a 2-wheel drive (2WD) autonomous rover using a Pi 5, a Slamtec RPLiDAR A1M8, and a high-efficiency TB6612FNG motor driver. We will cover the exact bill of materials, hardware pin mapping, and provide a complete, copy-pasteable Python script using gpiozero and the rplidar library.

Hardware Spec Sheet & Bill of Materials

Before cutting wires, verify your components. The most common failure in Pi-based robots is browning out the compute module when motors draw stall current. The BOM below assumes a 3S LiPo power architecture with isolated 5V regulation for the Pi.

Component Exact Model / Variant Key Specification Est. Cost (2026)
Compute Raspberry Pi 5 (8GB) Quad-core Cortex-A76, 2.4GHz, 3.3V logic $80.00
Motor Driver Pololu TB6612FNG Dual 1.2A continuous per channel, 3.3V VCC compatible $12.50
LIDAR Sensor Slamtec RPLiDAR A1M8 360° sweep, 8000 samples/sec, 115200 baud UART $99.00
Drive Motors JGB37-520 12V 30RPM 150mA no-load, 1.2A stall, metal gear $24.00 (pair)
Main Battery Zeee 3S 11.1V 2200mAh LiPo 50C discharge, XT60 connector $28.00
Step-Down Regulator Pololu D24V50F5 5V 5A output, 7-38V input (Powers Pi 5 & LIDAR) $16.00
Pi 5 Power Caveat: The Raspberry Pi 5 requires a 5V/5A USB-C PD power supply to enable full 1.2A downstream USB current. If you use a standard 5V/3A buck converter, the Pi will throttle USB current to 600mA, which will cause the RPLiDAR motor to stall during spin-up. The Pololu D24V50F5 wired directly to the Pi's GPIO 5V and GND pins bypasses the USB-C PD negotiation entirely, delivering a clean 5A rail.

Pin Mapping & Power Distribution

The TB6612FNG is a MOSFET-based driver, vastly superior to the ancient L298N bipolar junction transistor drivers that waste 2V-3V as heat. Because the Pi 5 operates at 3.3V logic, the TB6612FNG is ideal: its VCC pin accepts 2.7V to 5.5V for logic thresholds. Wire VCC to the Pi's 3.3V pin (Pin 1).

Note: The Raspberry Pi 5 routes hardware PWM to specific GPIO pins. We use GPIO 12 and 13 for motor speed control to avoid the latency of software PWM. (Reference: Raspberry Pi Hardware Documentation).

TB6612FNG Pin Wired To (Pi 5 GPIO / Power) Function
VCC Pi Pin 1 (3.3V) Logic level reference
GND Pi Pin 6 (GND) Common ground
PWMA Pi GPIO 12 (Pin 32) Left Motor Speed (Hardware PWM0)
AIN1 / AIN2 Pi GPIO 23 / GPIO 24 Left Motor Direction
PWMB Pi GPIO 13 (Pin 33) Right Motor Speed (Hardware PWM1)
BIN1 / BIN2 Pi GPIO 25 / GPIO 8 Right Motor Direction
STBY Pi 3.3V (Tied High) Keeps driver active permanently
VMOT 3S LiPo Positive (via XT60) Motor power (11.1V - 12.6V)

Python Motor Control & LIDAR Sweep Code

This script targets the Raspberry Pi 5 (8GB) running Raspberry Pi OS (64-bit, Bookworm or newer). It uses the gpiozero library for motor abstraction and the rplidar package for sensor polling. The logic implements a basic "bang-bang" obstacle avoidance: if a mass of points is detected within 400mm in the forward 90-degree arc, the rover halts and pivots.

Prerequisites: Run sudo apt install python3-gpiozero python3-rplidar and ensure your user is in the dialout group for serial access.

import time
import signal
import sys
from gpiozero import Motor
from rplidar import RPLidar

# --- Hardware Pin Definitions (Raspberry Pi 5 40-pin header) ---
# Left Motor (Channel A)
LEFT_FWD = 23
LEFT_BWD = 24
LEFT_EN  = 12  # Hardware PWM0

# Right Motor (Channel B)
RIGHT_FWD = 25
RIGHT_BWD = 8
RIGHT_EN  = 13  # Hardware PWM1

# Initialize Motors
left_motor = Motor(forward=LEFT_FWD, backward=LEFT_BWD, enable=LEFT_EN)
right_motor = Motor(forward=RIGHT_FWD, backward=RIGHT_BWD, enable=RIGHT_EN)

# Initialize LIDAR (Assuming USB adapter maps to /dev/ttyUSB0)
LIDAR_PORT = '/dev/ttyUSB0'
lidar = RPLidar(LIDAR_PORT)

def clean_shutdown(signum, frame):
    """Safely stop motors and LIDAR on Ctrl+C or system kill."""
    print("\n[!] Shutdown signal received. Stopping rover...")
    left_motor.stop()
    right_motor.stop()
    lidar.stop_motor()
    lidar.disconnect()
    sys.exit(0)

signal.signal(signal.SIGINT, clean_shutdown)
signal.signal(signal.SIGTERM, clean_shutdown)

def navigate():
    """Main control loop: process LIDAR scans and adjust motor vectors."""
    print("[*] Starting LIDAR sweep and motor control...")
    
    # Base speed (0.0 to 1.0)
    base_speed = 0.45 
    
    try:
        for scan in lidar.iter_scans():
            obstacle_detected = False
            
            # scan returns list of tuples: (quality, angle, distance)
            for _, angle, distance in scan:
                # Check forward arc (315° to 360° and 0° to 45°)
                if (angle >= 315 or angle <= 45) and distance < 400:
                    obstacle_detected = True
                    break
            
            if obstacle_detected:
                # Halt and pivot right to avoid
                left_motor.forward(base_speed * 0.8)
                right_motor.backward(base_speed * 0.5)
            else:
                # Drive forward
                left_motor.forward(base_speed)
                right_motor.forward(base_speed)
                
    except Exception as e:
        print(f"[X] Runtime Error: {e}")
        clean_shutdown(None, None)

if __name__ == '__main__':
    navigate()

Debugging: First Three Things to Check When It Fails

Robotics code rarely fails on the first compile; it fails in the physical layer. If your rover is dead on arrival, run through these three checks before rewriting your Python logic.

1. The Serial Permission Denial

Exact Error String: serial.serialutil.SerialException: [Errno 13] Permission denied: '/dev/ttyUSB0'

Ranked Causes:

  1. User not in dialout group: The Pi defaults to restricting serial ports. Fix: sudo usermod -a -G dialout $USER, then reboot.
  2. USB Cable is charge-only: The RPLiDAR USB pigtail lacks data lines. Swap to a verified data-sync micro-USB cable.
  3. Port mapped to ttyUSB1: Unplug and replug the LIDAR, then run dmesg | grep tty to verify the exact node.

2. The PWM Pin Mismatch

Exact Error String: gpiozero.exc.PinPWMUnsupported: Pin 18 does not support PWM

Ranked Causes:

  1. Using non-hardware PWM pins without pigpiod: If you changed GPIO 12/13 to GPIO 18, gpiozero tries to use software PWM. You must start the daemon: sudo systemctl enable pigpiod && sudo systemctl start pigpiod.
  2. Pin physically shorted: A stray strand of copper from the motor direction wires is bridging the PWM pin to 5V, triggering the Pi's internal protection and disabling the pin block.

3. The LIDAR Body Size Exception

Exact Error String: rplidar.rplidar.RPLidarException: Wrong body size

Ranked Causes:

  1. Baud rate mismatch: The A1M8 defaults to 115200. If your USB-to-Serial adapter is hardcoded to 9600, the Python library reads garbage bytes and throws a size error. Verify adapter specs.
  2. Insufficient 5V current to LIDAR motor: The A1M8 internal motor draws ~150mA on spin-up. If powered from a Pi USB port that is current-limited (due to non-PD power supply), the motor stutters, corrupting the UART data stream mid-packet.

Extending vs. Simplifying the Build

Not every project needs a $250 BOM, and some need significantly more compute. Here is how to scale this architecture based on your actual goals.

Simplify the Build (Target: <$120)
Drop the RPLiDAR and swap the Pi 5 for a Raspberry Pi Zero 2 W. Replace the LIDAR with an HC-SR04 ultrasonic sensor mounted on an SG90 micro servo. You will need a logic level converter (like a BSS138 MOSFET bi-directional board) to step the Pi Zero's 3.3V GPIO up to the HC-SR04's 5V trigger requirement, and step the 5V echo down to 3.3V for the Pi. This setup is perfect for basic line-following or maze-solving where mapping isn't required.

Extend the Build (Target: Advanced SLAM & Vision)
If you want to move from simple obstacle avoidance to true Simultaneous Localization and Mapping (SLAM), integrate ROS 2 Jazzy running on Ubuntu 24.04 Server. Add an OAK-D Lite spatial camera connected via USB 3.0 for depth perception and object classification. You will need to upgrade the motor driver to a RoboClaw 2x15A to handle the heavier chassis and implement quadrature encoder feedback from the JGB37-520 motors for precise odometry. (Reference: Pololu TB6612FNG Datasheet & Alternatives).