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
- Visit: thonny’s Website
- Download it for your OS (Windows/Mac/Linux).
- Navigate to the Downloads folder after the .exe file has been downloaded in File Explorer
-
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
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.
- It appears as a USB drive.
- Go to micropython.
uf2
file download for Pico - Download
.uf2
the file and copy it to the Pico USB drive. - Pico will reboot into MicroPython.
Set up Thonny
-
Open Thonny
-
Go to Run > Select Interpreter > MicroPython (Raspberry Pi Pico)
-
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)
Click on 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
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
-
Run your line follower code in Thonny.
-
You should see values being printed in the following format corresponding to each sensor:-
Sensors: [x, x, x, x, x]
-
Place the bot on a white surface. You should see:
[1, 1, 1, 1, 1]
(white reflects IR = HIGH). -
Move the centre sensor over the black line. You should see:
[1, 1, 0, 1, 1]
(black absorbs IR = LOW). -
Slide the bot side to side across the line. All sensors should detect black (
0
) when over a line. -
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