LFB Mark 2: ESP32 PID Line Follower With OLED Parameter Tuning
by Mr_AKN in Circuits > Robots
99 Views, 2 Favorites, 0 Comments
LFB Mark 2: ESP32 PID Line Follower With OLED Parameter Tuning
LFB Mark 2 is my attempt at building a faster and smarter line follower robot. MY goal was to move away from simple if-else line following and experiment with PID control, live parameter tuning, and a cleaner robot architecture.
The robot uses a 5-channel IR sensor array to detect the line and a TB6612 motor driver to control two N20 gear motors. An OLED display and three buttons were added to make PID tuning easier without connecting a laptop every time.
This project involved a lot of trial and error, debugging, redesigning, and unfortunately one fallen ESP32 along the way.
Supplies
Supplies
Electronics
- ESP32 Development Board
- TB6612FNG Dual Motor Driver
- TCRT5000L 5-Channel Line Tracking Sensor Module
- SSD1306 128×64 I2C OLED Display
- 3 × Push Buttons
- 2 × N20 12V 600 RPM Metal Gear Motors
- 2 × 18650 Li-ion Cells
- Battery Holders
- Power Switch
- Jumper Wires
- Perfboard / Prototype PCB
Mechanical Parts
- 3D Printed Chassis (Downloaded from Printables)
- 2 × N20 Motor Mounts
- Mounting Hardware (Screws, Nuts)
- 2 × 44mm MiniQ Robot Wheels
- Mini Ball Caster Wheel
Tools
- Soldering Iron
- Solder Wire
- Wire Cutter
- Screwdriver Set
- Double side tape/Hot Glue Gun (Optional)
Software
- Arduino IDE
- Adafruit GFX Library
- Adafruit SSD1306 Library
- ESP32 Board Package for Arduino IDE
- Ultimaker Cura (for slicing the 3D model)
Why Build Another Line Follower?
After building and experimenting with different robotics projects, I wanted to try a proper PID-based line follower. The main objective was to create a robot that could follow a line smoothly while allowing real-time tuning of parameters like Kp, Kd, Ki, and speed.
Printing the Chassis
Rather than designing a chassis from scratch, I used a 3D-printable line follower robot chassis from Printables - Line Follower Robot Chassis. The design already included mounting points for the N20 motors, caster wheel, batteries, and electronics, which helped speed up the development process. Full credit goes to the original designer.
Building the Chassis
With the chassis printed, it was time to start turning a piece of plastic into an actual robot.
The N20 motors were mounted on both sides and fitted with 44 mm MiniQ wheels. A caster wheel was added to keep the robot balanced while still allowing it to turn freely.
The battery holders were mounted as low as possible on the chassis. Keeping the batteries low helps lower the robot's center of gravity, making it more stable during fast turns and sudden corrections.
The 5-channel IR sensor array was mounted at the front of the robot. Placing the sensors ahead of the wheels allows the robot to detect changes in the line earlier, giving the PID controller more time to react and make smoother corrections.
Once the mechanical assembly was complete, the robot was ready for the electronics and wiring stage.
Electronics Assembly
The ESP32 acts as the brain of the robot, reading data from the sensor array and calculating the PID correction required to stay on the line. Motor control is handled by a TB6612FNG motor driver, which drives the two N20 gear motors.
To make tuning easier, I added a 128×64 OLED display along with three push buttons. This allows PID parameters and speed to be adjusted directly from the robot without connecting a laptop every time a change is needed.
The 5-channel IR sensor array is mounted at the front of the robot and provides digital line detection data for the PID controller.
After a lot of wiring, soldering, and checking connections multiple times, everything was assembled onto a perfboard to keep the wiring compact and reliable.
Final Pin Mapping
Sensors
S1 - GPIO19
S2 - GPIO18
S3 - GPIO5
S4 - GPIO17
S5 - GPIO16
OLED Display
SDA - GPIO21
SCL - GPIO22
Buttons
Increase - GPIO36
Decrease - GPIO39
Select - GPIO34
Button Pull-up Resistors
Since GPIO34, GPIO36, and GPIO39 do not support internal pull-up resistors, each button was connected with an external 10kΩ pull-up resistor to 3.3V.
When a button is pressed, the corresponding GPIO pin is pulled LOW. This keeps the button inputs stable and prevents false triggering due to floating inputs.
TB6612FNG Motor Driver
PWMA - GPIO13
AIN2 - GPIO14
AIN1 - GPIO27
STBY - GPIO26
BIN1 - GPIO25
BIN2 - GPIO33
PWMB - GPIO32
Power Connections
2S 18650 Battery Pack (+) - TB6612 VM
2S 18650 Battery Pack (-) - Common GND
TB6612 VCC - ESP32 3.3V
TB6612 GND - Common GND
ESP32 VIN - Battery Positive (through power switch)
ESP32 GND - Common GND
Sensor VCC - ESP32 3.3V
Sensor GND - Common GND
OLED VCC - ESP32 3.3V
OLED GND - Common GND
All grounds were connected together to create a common reference between the ESP32, motor driver, OLED display, and sensor module.
During development I initially tried using GPIO36 as an output before realizing it is input-only. This required rewiring part of the circuit and served as a reminder to always check ESP32 pin capabilities before finalizing a design.
Downloads
Programming the Robot
The software side of this project went through several revisions before reaching its current form.
Instead of making simple left-or-right decisions based on the sensor readings, I decided to use a weighted PID approach. Each sensor is assigned a weight, allowing the robot to estimate its position relative to the line and calculate how much correction is needed.
An OLED display and three buttons were added to make tuning easier. This allowed me to adjust Kp, Kd, Ki, and base speed directly from the robot without constantly reconnecting it to a computer.
Along the way, I experimented with different recovery methods, junction handling strategies, sensor weightings, and PID values. Some ideas worked surprisingly well, while others mostly taught me what not to do.
To make debugging easier, the robot also outputs sensor patterns, motor speeds, and PID information through the serial monitor during testing.
Debugging and Lessons Learned
This is actually the fun section.
Like most robotics projects, this one spent a lot more time being debugged than being photographed.
Another surprise came from the ESP32 PWM API. Some examples online used functions that were no longer supported in the version of the ESP32 core I was using, which meant parts of the motor control code had to be rewritten.
The robot also went through several different recovery strategies. Initially, the robot would stop completely whenever all sensors lost the line. While this was useful for debugging, it wasn't very practical on an actual track. After experimenting with different approaches, I settled on a recovery method that allows the robot to continue moving and reacquire the line more smoothly.
The button interface also required some attention. Without proper debouncing, a single button press could be detected multiple times, making parameter tuning frustrating.
The biggest challenge, however, was PID tuning. Small changes in Kp, Kd, and speed could completely change how the robot behaved. Finding a balance between stability and speed took many test runs and adjustments.
And finally, no project is complete without at least one unexpected casualty. During development, one ESP32 board unfortunately sacrificed itself for the advancement of the project.
Results
After multiple iterations and tuning sessions, the robot was able to follow the track using weighted PID control. The OLED interface allowed quick parameter adjustments, making testing much easier.
The final result is a compact line follower robot that is faster, smarter, and far more configurable than my earlier attempts.
Working video attached below.