Ferris Goes Vroom
A fast autonomous line-following car
Author: Sorana-Ioana Ulmeanu \
GitHub Project Link: https://github.com/UPB-PMRust-Students/acs-project-2026-soranaulm
Description
Ferris Goes Vroom is an autonomous line-following car that tracks a black line on a white surface. The car uses a 5-channel IR sensor module mounted under the chassis to detect the line position, and adjusts the two DC motors to stay on track. A small OLED display shows real-time information such as line detection state and speed. An MPU6050 accelerometer estimates the current speed by integrating acceleration over time. What sets this project apart is the use of Rust with the Embassy async framework on an STM32 microcontroller — an uncommon choice in the embedded world, but one that brings memory safety and high performance. A set of colored LEDs provides real-time visual feedback about the system state: line detected, line lost, or maximum speed reached.
Motivation
Growing up, I always wanted a remote control car. I loved watching them speed around and dreamed of having one of my own. So when this project came along, I saw the perfect opportunity to finally get my car, just built by my own hands this time.
What makes this project special to me is how interactive and alive it feels. Watching a small car zoom along a track on its own, reacting to the world around it in real time, feels almost like it has a personality. There is something deeply satisfying about building something that moves, that responds, that feels human in its own little way.
Architecture
The system is organized into four main modules that run concurrently as Embassy async tasks:
Sensor Subsystem: A TCRT5000 5-channel IR sensor module is put in front of the chassis. Each channel reads surface reflectivity — black surfaces absorb IR (digital LOW) and white surfaces reflect it (digital HIGH). The combined pattern of S1–S5 readings determines the line position relative to the car center.
PID Control Engine: The control engine receives the error value from the sensor subsystem every few milliseconds and computes a correction using proportional, integral, and derivative terms. This correction is applied differentially to the two motors: if the car drifts right, the left motor speeds up and the right motor slows down, and vice versa. The three PID constants (Kp, Ki, Kd) are tuned experimentally on the real track.
Motor Drive Subsystem: An L298N dual H-bridge driver receives PWM signals from two STM32 timer channels (TIM2_CH3 and TIM3_CH1) and independently drives the two DC motors. Speed is controlled differentially — when turning, the outer motor runs at 100% duty cycle while the inner motor runs at 50%, allowing smooth cornering. For sharp corrections, one motor stops completely.
LED Feedback Module: Three 5mm LEDs indicate the current system state: red lights when no line is detected and the car is stopped, blue lights when the line is detected and tracking is active, and green lights when the car is moving forward on the line.
Display & Speed Module: A 0.96 SSD1306 OLED display connected via I2C shows real-time line detection state. An MPU6050 accelerometer, also connected via I2C, estimates speed by integrating the X-axis acceleration (ax) over time with dt = 50ms.
Block Diagram
Communication Protocols
| Protocol | Usage |
|---|---|
| GPIO Input | Reading IR sensors, computing line position |
| GPIO Output | Controlling LEDs |
| PWM (TIM) | Controlling motor speed via L298N ENA/ENB |
| ADC | Reading analog IR sensor values for precise line position |
| PWM (TIM) | Controlling motor speed via L298N |
Log
Week 1
Defined the project concept and architecture. Researched and selected the hardware components needed for the build. Started working on the project documentation.
Week 2
Verified each component one by one. Assembled the hardware — mounted the chassis, connected the TCRT5000 sensor module, L298N motor driver, OLED display, MPU6050, LEDs, and LiPo battery.
Week 3
Wrote test code to verify all components working together — sensor readings, motor control, LED feedback, OLED display, and MPU6050 speed estimation.
Week 4
Finalized the project software with complete line-following logic. Finalized documentation and assembled all components in their final positions on the car.
Hardware
The project is built around the STM32 Nucleo-U545RE-Q, featuring an ARM Cortex-M33 core running at 160MHz with 256KB of SRAM and 2MB of Flash, and an integrated ST-LINK/V3E debugger for easy flashing and RTT logging from Rust.
A TCRT5000 5-channel IR sensor module is mounted under the front of the chassis is mounted in a row under the front of the chassis. Each sensor emits infrared light and reads back the reflection — black surfaces absorb IR (digital LOW) and white surfaces reflect it (digital HIGH). The combined pattern of readings is used to compute the signed error of the line position relative to the car center.
A L298N dual H-bridge motor driver receives PWM signals from two STM32 timer channels and independently drives the two DC motors with gearboxes. The speed difference between the motors is the steering mechanism — no servo is needed.
Three 5mm LEDs (green, red, blue) with 220Ω current-limiting resistors are connected to GPIO output pins: red lights when no line is detected and the car stops, blue lights when the center sensors are aligned on the line, and green lights when the motors are running.
A 0.96" SSD1306 OLED display is connected via I2C and shows real-time data: current speed, system state, and lap time.
A LiPo 7.4V battery powers the system autonomously. A HW-286 step-down regulator converts the 7.4V battery voltage to 5V to power the STM32 Nucleo, while the motors are driven directly from the battery voltage through the L298N.
The car chassis is either a commercial kit that holds all components in a compact and balanced layout. All components are connected on a breadboard with jumper wires.

Schematics

Bill of Materials
| Device | Usage | Price |
|---|---|---|
| STM32 Nucleo-U545RE-Q | Main microcontroller | Provided by university |
| TCRT5000 5-channel IR module | Line detection | 16.99 RON |
| L298N Motor Driver | Dual DC motor control | 11.99 RON |
| OLED Display SSD1306 0.96 | Real-time info display | 18.98 RON |
| LED 5mm x3 (green, red, blue) | Visual feedback | 0.9 RON |
| Resistors 220Ω x3 (kit) | LED current limiting | 15.16 RON |
| LiPo Battery 7.4V | Autonomous power supply | 61.35 RON |
| 2WD Car chassis kit | Mechanical strcuture | 41.21 RON |
| Breadboard 400 | Prototyping connections | 6.99 RON |
| Jumper wires | Prototyping connections(M-M, T-T, M-T) | 22.97 RON |
| XT60 pigtail cable, male-female, 20cm | Battery connector | 27.39 RON |
| Black electrical tape | Track line for car | 6.49 RON |
| M3 screws + nuts set | Chassis assembly | ~2 RON |
| Double-sided adhesive tape | Component mounting | 19.98 RON |
| HW-286 Step-down regulator | Voltage regulation 7.4V to 5V | 28.29 RON |
Software
| Library | Description | Usage |
|---|---|---|
embassy | Async runtime for embedded Rust | Task management and async executor |
embassy-stm32 | Embassy HAL for STM32 | GPIO, PWM (TIM), I2C control |
embassy-time | Timer abstractions | Delays and PID loop timing |
embassy-sync | Async synchronization primitives | Coordinating sensor, PID, display and LED tasks |
embedded-hal | Hardware Abstraction Layer | Generic hardware interfaces |
ssd1306 | OLED display driver | Drawing text and graphics on the SSD1306 via I2C |
embedded-graphics | 2D graphics library | Rendering text and shapes on the OLED display |
defmt | Efficient embedded logging | Debugging via RTT |
cortex-m | Low-level ARM Cortex-M utilities | Low-level control |
cortex-m-rt | Runtime for ARM Cortex-M | Entry point and interrupt setup |