Turn Your Raspberry Pi Pico into a Robot That Obeys Lines Like a Pro

by Shivank DanMay 23rd, 2025
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

A line follower is a type of autonomous robot that can detect and follow a line drawn on the floor, typically a black line. Raspberry Pi Pico can be used to make a line follower robot.

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Turn Your Raspberry Pi Pico into a Robot That Obeys Lines Like a Pro
Shivank Dan HackerNoon profile picture
0-item

Found your Raspberry PI Pico in a cupboard that you opened 2 years before… Get along with this project to make a line follower robot using Raspberry Pi Pico and a few other Stuff


What is a Line Follower Robot?

A line follower is a type of autonomous robot that can detect and follow a line drawn on the floor, typically a black line.

Components Required

Component

Quantity

Notes

Raspberry Pi Pico

1

Use the Pico H for easier pin access

BFD-1000 IR sensor array / any 5 array IR sensor Module

1

To detect the Black Line

L298N motor driver

1

To drive motors precisely

BO Motors (3–12V)

2

Preferably 12V ones :)

Bo motor Wheels

2

Wheels For Bo Motor

Caster wheel (free wheel)

1

To balance the front

LiPo Battery (12V)

1

Or any regulated 12V source

Wires, breadboard, etc.

As needed

For connections

Computer

1

For programming and debugging


Cooking the Pi🍳


The Software Part

1. Installing Thonny IDE

Thonny Website Page

  • Download it for your OS (Windows/Mac/Linux).

Link to install the Thonny IDE for windows only

  • Navigate to the Downloads folder after the .exe file has been downloaded in File Explorer

Download Folder

  • Then click on the .exe file (thonny-4.1.7.exe) to execute the application and click on next until you see that the thonny is being installed

    installation wizard

Flashing the pico with Micropython Firmware

If you have already flashed the micropython firmware the you can skip to next part

Plug in your Pico while holding the BOOTSEL button.

  1. It appears as a USB drive.
  2. Go to micropython.uf2 file download for Pico
  3. Download .uf2 the file and copy it to the Pico USB drive.
  4. Pico will reboot into MicroPython.

Set up Thonny

  • Open Thonny

  • Go to Run > Select Interpreter > MicroPython (Raspberry Pi Pico)

    Port Selection

  • Select the right port.

  • Paste the following MicroPython code into the script area

    Get code here or paste the code below

      
    from machine import Pin, PWM
    import time
    
    # Motor Pins
    in1 = Pin(2, Pin.OUT)
    in2 = Pin(3, Pin.OUT)
    in3 = Pin(4, Pin.OUT)
    in4 = Pin(5, Pin.OUT)
    
    ena = PWM(Pin(6))
    enb = PWM(Pin(7))
    ena.freq(1000)
    enb.freq(1000)
    
    # Sensor Pins
    sensors = [Pin(i, Pin.IN) for i in range(8, 13)]
    
    # Speed Settings
    BASE_SPEED = 35000  # Slow and safe for normal movement
    MAX_SPEED = 40000   # Max PWM limit
    TURN_SPEED = 25000  # Slower speed for turning
    
    # PID Settings
    Kp = 8000  # Proportional gain, tune this as per your bot
    Ki = 0     
    Kd = 0     
    
    # PID Variables
    previous_error = 0
    integral = 0
    
    # Motor control functions
    def set_motor_speed(left_speed, right_speed):
        left_speed = max(0, min(MAX_SPEED, left_speed))
        right_speed = max(0, min(MAX_SPEED, right_speed))
    
        if left_speed == 0:
            in1.low()
            in2.low()
        else:
            in1.high()
            in2.low()
    
        if right_speed == 0:
            in3.low()
            in4.low()
        else:
            in3.high()
            in4.low()
    
        ena.duty_u16(left_speed)
        enb.duty_u16(right_speed)
    
    def stop():
        in1.low()
        in2.low()
        in3.low()
        in4.low()
        ena.duty_u16(0)
        enb.duty_u16(0)
    
    # Read sensor values
    def read_sensors():
        return [s.value() for s in sensors]
    
    # Calculate position (PID error calculation)
    def calculate_error(sensor_values):
        weights = [-2, -1, 0, 1, 2]
        total = 0
        count = 0
        for i in range(5):
            if sensor_values[i] == 0:  # Line detected (assuming black line)
                total += weights[i]
                count += 1
        if count == 0:
            return None  # Line lost
        return total / count
    
    # PID controller
    def pid_control(error):
        global previous_error, integral
    
        if error is None:
            return 0, 0  # No correction needed if line is lost
    
        integral += error
        derivative = error - previous_error
        correction = int(Kp * error + Ki * integral + Kd * derivative)
    
        previous_error = error
    
        return correction, correction
    
    # Smart Search with PID
    def smart_search():
        global previous_error, integral  # Reset PID variables for search
        previous_error = 0
        integral = 0
    
        for attempt in range(5):
            print("Search attempt", attempt+1)
    
            # Turn left (using PID control)
            in1.low()
            in2.high()
            in3.high()
            in4.low()
            ena.duty_u16(TURN_SPEED)
            enb.duty_u16(TURN_SPEED)
            time.sleep(0.5)
            stop()
            time.sleep(0.1)
            sensor_values = read_sensors()
            error = calculate_error(sensor_values)
            left_correction, right_correction = pid_control(error)
    
            if 0 in sensor_values:
                print("Found line after left turn")
                return
    
            # Turn right (using PID control)
            in1.high()
            in2.low()
            in3.low()
            in4.high()
            ena.duty_u16(TURN_SPEED)
            enb.duty_u16(TURN_SPEED)
            time.sleep(1.0)
            stop()
            time.sleep(0.1)
            sensor_values = read_sensors()
            error = calculate_error(sensor_values)
            left_correction, right_correction = pid_control(error)
    
            if 0 in sensor_values:
                print("Found line after right turn")
                return
    
        print("Failed to find line after searching.")
    
    # Main loop
    while True:
        sensor_values = read_sensors()
        print("Sensors:", sensor_values)
    
        error = calculate_error(sensor_values)
    
        if error is None:
            print("Line lost, starting search")
            stop()
            smart_search()
        else:
            correction = int(Kp * error)
    
            left_speed = BASE_SPEED - correction
            right_speed = BASE_SPEED + correction
    
            set_motor_speed(left_speed, right_speed)
       
        time.sleep(0.01)
    

    Script Area

Click on the save icon The SAVE icon

  • You will get a Prompt stating:-

    Where do you want to save

    1)Raspberry Pi Pico

    2)To this PC

  • Choose Pico and save the file as main.py otherwise it will not auto-run on when powered on


The Hardware part

Connections

Here is a link for the line follower connections:- Click Here

Wiring Diagram

Connection Table

L298N to Pico

L298N Pin

Connects To

IN1

Pico GP2

IN2

Pico GP3

IN3

Pico GP4

IN4

Pico GP5

ENA

Pico GP6 (PWM)

ENB

Pico GP7 (PWM)

VCC

12V from the battery

GND

Pico GND & battery GND

5V

V_Sys pin

BFD 1000 to Pico

IR Sensor Pin

Connects To (Pico Pin)

Function

OUT1

GP8

Left-most sensor

OUT2

GP9

Left sensor

OUT3

GP10

Center sensor

OUT4

GP11

Right sensor

OUT5

GP12

Right-most sensor

VCC

5V

Power

GND

GND

Ground


IR Sensor Calibration

  1. Run your line follower code in Thonny.

  2. You should see values being printed in the following format corresponding to each sensor:-

    Sensors: [x, x, x, x, x]

  3. Place the bot on a white surface. You should see: [1, 1, 1, 1, 1] (white reflects IR = HIGH).

  4. Move the centre sensor over the black line. You should see: [1, 1, 0, 1, 1] (black absorbs IR = LOW).

  5. Slide the bot side to side across the line. All sensors should detect black (0) when over a line.

  6. Adjust potentiometers (if needed) on the IR sensor for reliable 0/1 switching.


Test Run Video

Drive Link:-https://drive.google.com/file/d/1ODuU0T4gvLMk8YIl7x5UDorZBtHX7OeK/view?usp=sharing

That’s all, folks, for this project

Meet you in another tutorial like this

Thanks,

Shivank Dan


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks