MiniSLAM Robot
[Fall 2025] A Wi-Fi-controlled robot car system: While performing motion instructions, it transmits LiDAR scanning data in real time back to the host, and runs TinySLAM on the host end for online pose estimation and map construction, achieving "visual remote driving + real-time mapping".
- Suitable forB.Tech/B.E Embedded Systems students
- Build time4-6 weeks
- LevelBeginner
- Available atAjvika Labs, Kakinada
About this project
Toggle navigation
ECE 5730 Project
Introduction
High level design
Hardware
Software
Results
Conclusions
Work Distribution
Appendix
ECE5730 Project
Demonstration Video
Introduction
A Wi-Fi-controlled robot car system: While performing motion instructions, it transmits LiDAR scanning data in real time back to the host, and runs TinySLAM on the host end for online pose estimation and map construction, achieving "visual remote driving + real-time mapping".
Our robot car project is a “visual remote-control” system. The user opens a web control page on the host PC (personal computer). The user can control the car to move forward, backward, turn left, turn right, and change speed through Wi-Fi. At the same time, the page log shows LiDAR scan data from the car (angle + distance) in real time. To keep both “control” and “sensor feedback” stable, we split the system into two parts. PICO_B drives the stepper motor to rotate the TF-Luna for scanning. It reads distance data and packs the data, then sends it to PICO_A by UART. PICO_A receives the packet and forwards it to the host PC (personal computer) by UDP. It also receives motion commands from the host PC (personal computer) and drives two DC motors. In addition, it uses two photointerrupters as wheel encoders to count pulses. The main value of this project is a complete closed-loop remote driving experience. The operator is not only able to "press the button to move the vehicle", but also can simultaneously view the distance data, making remote control more intuitive and safer. In addition, we have integrated TinySLAM on the Host PC end, which fuses continuous LiDAR scanning data online into pose trajectories and occupation raster maps, and displays them in real time through the front-end interface, achieving a closed-loop experience of "visual remote control + real-time mapping".
High Level Design
1. Rationale
The reason why we designed this project is that in many mobile robot applications, merely achieving remote control is not enough: the operator also needs to continuously obtain information about the surrounding environment (such as distance data from different angles and the trend of obstacle positions) in order to make safe and reasonable driving decisions. For instance, in some dangerous or unsuitable scenarios for personnel entry (such as basements, narrow pipe galleries, spaces with heavy smoke, dust or odors, etc.), it is inconvenient for people to enter the site, but small vehicles can be used as substitutes for entry. The operator can perform remote control from a safe position and rely on sensor information to judge the environmental conditions at the same time.
From the perspective of user experience, we hope to upgrade "control" to "visual control". If there is only button remote control, the operator is "blind" to environmental information and is prone to misoperation or collision. When the system can display the ranging result of “angle + distance" in real time, it is equivalent to providing a clear perceptual feedback layer for the car, making the operation more intuitive, explainable and safer.
Our project idea comes from both course materials and real-world needs. Our implementation was mainly inspired by the course-provided RP2040 examples and infrastructure from
V. Hunter Adams' RP2040 demos
We also reviewed robot-style control and reporting patterns from
Cornell ECE final projects from previous years
to guide our system integration and webpage-style monitoring.
For hardware bring-up and parameter settings, we referenced the official datasheets for
the RP2040, TF-Luna LiDAR, 28BYJ-48 stepper motor, TB6612FNG motor driver, and ULN2003A driver IC.
2. Background Math
This project is mainly about system integration and real-time communication, but it still relies on a few basic math ideas.
The key topics are PWM duty cycle and PWM frequency, wheel encoder pulse counting (for speed/odometry estimation), and fixed-point (Q15) number representation for reliable UART data transfer.
(1) PWM frequency and duty cycle (DC motor speed control)
PICO_A uses the RP2040 PWM hardware to drive the motor driver with a speed signal. PWM is a square wave with a fixed period.
The motor speed is controlled by the duty cycle, which is the ratio of “high” time in one period. A larger duty cycle means a higher average voltage to the motor, so the motor spins faster.
On RP2040, the PWM frequency can be approximated as:
In our code, WRAPVAL=5000, CLKDIV=125, and f
clk
≈125 MHz, so the PWM frequency is about 200 Hz.
The duty cycle is set by level/WRAPVAL. A larger level means a larger duty cycle and higher speed.
(2) Encoder pulse counting (for speed / distance estimation, extendable)
Each wheel has a photointerrupter that outputs pulses. PICO_A counts pulses using GPIO rising-edge interrupts.
If the encoder has N pulses per revolution (PPR), and we measure a pulse increase ΔC within a time window Δt,
we can estimate wheel speed as:
With wheel radius r, the linear speed can be estimated by:
The total pulse count can also be used to estimate distance.
In this project, encoder counting is mainly used for debugging and future closed-loop control.
(3) Fixed-point (Q15) representation for UART packets
To transmit the scan angle with a stable and compact format, we encode the angle using Q15 fixed-point.
Q15 means we multiply a real value by 2
and store it as an integer. In our code we use float2fix15(x)=x×32768,
and on the receiver side we convert it back with fix2float15(x)=x/32768.
This avoids directly sending floats over UART and makes the packet format simple and consistent.
3. Logic Structure
Our system has two closed loops that run at the same time: a sensing uplink (LiDAR scan data to the host PC)
and a control downlink (host PC commands to the robot). We split the work across two Pico W boards so that the
real-time scan pipeline is not slowed down by Wi-Fi and UDP delays.
(1) Sensing uplink: TF-Luna → PICO_B → PICO_A → host PC
First, the TF-Luna LiDAR outputs a continuous UART byte stream. On PICO_B, Core 1 reads and parses the TF-Luna frames
and updates the latest distance value. In parallel, the stepper motor provides the scan angle reference.
We tie angle sampling to real step events (PIO-assisted stepping and interrupts), so each sample has a consistent
“angle + distance” pair. Then PICO_B packs the data into a compact UART packet (fixed header + angle field + distance field)
and sends the packet to PICO_A through UART0. On PICO_A, a small UART receive FSM finds the packet header, reads the payload,
reconstructs angle and distance, and sets a ready flag. Finally, PICO_A sends the decoded scan data to the host PC using Wi-Fi/UDP,
so the PC can display the real-time scan messages.
(2) Control downlink: host PC → PICO_A → motor driver → DC motors
The host PC provides a simple control panel in a web page. When the user presses a button (Forward/Back/Left/Right/Stop)
or changes the speed slider, the browser sends a short command through WebSocket. A Python UDP-WebSocket bridge on the host PC
receives the WebSocket message, converts it into a UDP command string, and sends it to PICO_A over the local network.
On PICO_A, the UDP receive callback parses the direction and speed, clamps the speed to a safe range, and updates shared command variables.
The motor control thread on the other core reads the updated command and outputs direction pins and PWM duty cycle to the motor driver (TB6612FNG),
which drives the two DC motors for motion execution.
(3) Concurrency and data consistency
To keep the system stable, we use clear producer-consumer handshakes between tasks.
On the sensing path, the scan producer and the network sender are separated by “ready” flags, so we do not send half-updated data.
On the control path, UDP command parsing and motor output are separated by an “update” flag, so motor output changes only when a new command arrives.
We also keep interrupt handlers short and use volatile shared variables for cross-core visibility. This structure lets us stream scan data
while still keeping motor control responsive.
4. Hardware/Software Trade-offs
(1) One Pico W vs. two Pico W boards (system partition)
At the beginning, we tried to use only one Pico W to do everything: stepper rotation, TF-Luna UART reading and parsing, Wi-Fi/UDP networking, and DC motor PWM output. After integration, we saw clear timing jitter because the Wi-Fi/UDP stack and memory operations can introduce unstable delays. However, UART parsing and motor control are real-time tasks and should not miss cycles. To improve stability, we moved to a two-board design. PICO_B focuses on scanning (stepper + TF-Luna + packet packing), and PICO_A focuses on networking and motion execution (UART receive + UDP forward + motor control). This makes the system more stable and easier to debug, but it adds extra wiring and one more UART link.
(2) Stepper angle timing: PIO interrupt (hardware-assisted) vs. main-loop timing (software)
For the scanning angle, we update the step counter and the sampling timing inside the PIO interrupt handler,
instead of using a software timer in the main loop. The key idea is to let PIO generate step events with stable timing,
and then let the CPU ISR update the step counter based on real hardware step events. In our design, each step event is
tied to the motor output sequence, so the angle update and the TF-Luna distance sample are more consistent in time.
This reduces drift caused by scheduling delays or Wi-Fi workload on the main loop.
The trade-off is higher code complexity. We must keep the ISR short and we must carefully manage shared variables
across interrupts and cores.
Figure 1. PIO + DMA stepper motor control architecture (adapted from V. Hunter Adams's RP2040 motor library).
DMA streams the phase sequence and timing parameters into P
ECE 5730 Project
Introduction
High level design
Hardware
Software
Results
Conclusions
Work Distribution
Appendix
ECE5730 Project
Demonstration Video
Introduction
A Wi-Fi-controlled robot car system: While performing motion instructions, it transmits LiDAR scanning data in real time back to the host, and runs TinySLAM on the host end for online pose estimation and map construction, achieving "visual remote driving + real-time mapping".
Our robot car project is a “visual remote-control” system. The user opens a web control page on the host PC (personal computer). The user can control the car to move forward, backward, turn left, turn right, and change speed through Wi-Fi. At the same time, the page log shows LiDAR scan data from the car (angle + distance) in real time. To keep both “control” and “sensor feedback” stable, we split the system into two parts. PICO_B drives the stepper motor to rotate the TF-Luna for scanning. It reads distance data and packs the data, then sends it to PICO_A by UART. PICO_A receives the packet and forwards it to the host PC (personal computer) by UDP. It also receives motion commands from the host PC (personal computer) and drives two DC motors. In addition, it uses two photointerrupters as wheel encoders to count pulses. The main value of this project is a complete closed-loop remote driving experience. The operator is not only able to "press the button to move the vehicle", but also can simultaneously view the distance data, making remote control more intuitive and safer. In addition, we have integrated TinySLAM on the Host PC end, which fuses continuous LiDAR scanning data online into pose trajectories and occupation raster maps, and displays them in real time through the front-end interface, achieving a closed-loop experience of "visual remote control + real-time mapping".
High Level Design
1. Rationale
The reason why we designed this project is that in many mobile robot applications, merely achieving remote control is not enough: the operator also needs to continuously obtain information about the surrounding environment (such as distance data from different angles and the trend of obstacle positions) in order to make safe and reasonable driving decisions. For instance, in some dangerous or unsuitable scenarios for personnel entry (such as basements, narrow pipe galleries, spaces with heavy smoke, dust or odors, etc.), it is inconvenient for people to enter the site, but small vehicles can be used as substitutes for entry. The operator can perform remote control from a safe position and rely on sensor information to judge the environmental conditions at the same time.
From the perspective of user experience, we hope to upgrade "control" to "visual control". If there is only button remote control, the operator is "blind" to environmental information and is prone to misoperation or collision. When the system can display the ranging result of “angle + distance" in real time, it is equivalent to providing a clear perceptual feedback layer for the car, making the operation more intuitive, explainable and safer.
Our project idea comes from both course materials and real-world needs. Our implementation was mainly inspired by the course-provided RP2040 examples and infrastructure from
V. Hunter Adams' RP2040 demos
We also reviewed robot-style control and reporting patterns from
Cornell ECE final projects from previous years
to guide our system integration and webpage-style monitoring.
For hardware bring-up and parameter settings, we referenced the official datasheets for
the RP2040, TF-Luna LiDAR, 28BYJ-48 stepper motor, TB6612FNG motor driver, and ULN2003A driver IC.
2. Background Math
This project is mainly about system integration and real-time communication, but it still relies on a few basic math ideas.
The key topics are PWM duty cycle and PWM frequency, wheel encoder pulse counting (for speed/odometry estimation), and fixed-point (Q15) number representation for reliable UART data transfer.
(1) PWM frequency and duty cycle (DC motor speed control)
PICO_A uses the RP2040 PWM hardware to drive the motor driver with a speed signal. PWM is a square wave with a fixed period.
The motor speed is controlled by the duty cycle, which is the ratio of “high” time in one period. A larger duty cycle means a higher average voltage to the motor, so the motor spins faster.
On RP2040, the PWM frequency can be approximated as:
In our code, WRAPVAL=5000, CLKDIV=125, and f
clk
≈125 MHz, so the PWM frequency is about 200 Hz.
The duty cycle is set by level/WRAPVAL. A larger level means a larger duty cycle and higher speed.
(2) Encoder pulse counting (for speed / distance estimation, extendable)
Each wheel has a photointerrupter that outputs pulses. PICO_A counts pulses using GPIO rising-edge interrupts.
If the encoder has N pulses per revolution (PPR), and we measure a pulse increase ΔC within a time window Δt,
we can estimate wheel speed as:
With wheel radius r, the linear speed can be estimated by:
The total pulse count can also be used to estimate distance.
In this project, encoder counting is mainly used for debugging and future closed-loop control.
(3) Fixed-point (Q15) representation for UART packets
To transmit the scan angle with a stable and compact format, we encode the angle using Q15 fixed-point.
Q15 means we multiply a real value by 2
and store it as an integer. In our code we use float2fix15(x)=x×32768,
and on the receiver side we convert it back with fix2float15(x)=x/32768.
This avoids directly sending floats over UART and makes the packet format simple and consistent.
3. Logic Structure
Our system has two closed loops that run at the same time: a sensing uplink (LiDAR scan data to the host PC)
and a control downlink (host PC commands to the robot). We split the work across two Pico W boards so that the
real-time scan pipeline is not slowed down by Wi-Fi and UDP delays.
(1) Sensing uplink: TF-Luna → PICO_B → PICO_A → host PC
First, the TF-Luna LiDAR outputs a continuous UART byte stream. On PICO_B, Core 1 reads and parses the TF-Luna frames
and updates the latest distance value. In parallel, the stepper motor provides the scan angle reference.
We tie angle sampling to real step events (PIO-assisted stepping and interrupts), so each sample has a consistent
“angle + distance” pair. Then PICO_B packs the data into a compact UART packet (fixed header + angle field + distance field)
and sends the packet to PICO_A through UART0. On PICO_A, a small UART receive FSM finds the packet header, reads the payload,
reconstructs angle and distance, and sets a ready flag. Finally, PICO_A sends the decoded scan data to the host PC using Wi-Fi/UDP,
so the PC can display the real-time scan messages.
(2) Control downlink: host PC → PICO_A → motor driver → DC motors
The host PC provides a simple control panel in a web page. When the user presses a button (Forward/Back/Left/Right/Stop)
or changes the speed slider, the browser sends a short command through WebSocket. A Python UDP-WebSocket bridge on the host PC
receives the WebSocket message, converts it into a UDP command string, and sends it to PICO_A over the local network.
On PICO_A, the UDP receive callback parses the direction and speed, clamps the speed to a safe range, and updates shared command variables.
The motor control thread on the other core reads the updated command and outputs direction pins and PWM duty cycle to the motor driver (TB6612FNG),
which drives the two DC motors for motion execution.
(3) Concurrency and data consistency
To keep the system stable, we use clear producer-consumer handshakes between tasks.
On the sensing path, the scan producer and the network sender are separated by “ready” flags, so we do not send half-updated data.
On the control path, UDP command parsing and motor output are separated by an “update” flag, so motor output changes only when a new command arrives.
We also keep interrupt handlers short and use volatile shared variables for cross-core visibility. This structure lets us stream scan data
while still keeping motor control responsive.
4. Hardware/Software Trade-offs
(1) One Pico W vs. two Pico W boards (system partition)
At the beginning, we tried to use only one Pico W to do everything: stepper rotation, TF-Luna UART reading and parsing, Wi-Fi/UDP networking, and DC motor PWM output. After integration, we saw clear timing jitter because the Wi-Fi/UDP stack and memory operations can introduce unstable delays. However, UART parsing and motor control are real-time tasks and should not miss cycles. To improve stability, we moved to a two-board design. PICO_B focuses on scanning (stepper + TF-Luna + packet packing), and PICO_A focuses on networking and motion execution (UART receive + UDP forward + motor control). This makes the system more stable and easier to debug, but it adds extra wiring and one more UART link.
(2) Stepper angle timing: PIO interrupt (hardware-assisted) vs. main-loop timing (software)
For the scanning angle, we update the step counter and the sampling timing inside the PIO interrupt handler,
instead of using a software timer in the main loop. The key idea is to let PIO generate step events with stable timing,
and then let the CPU ISR update the step counter based on real hardware step events. In our design, each step event is
tied to the motor output sequence, so the angle update and the TF-Luna distance sample are more consistent in time.
This reduces drift caused by scheduling delays or Wi-Fi workload on the main loop.
The trade-off is higher code complexity. We must keep the ISR short and we must carefully manage shared variables
across interrupts and cores.
Figure 1. PIO + DMA stepper motor control architecture (adapted from V. Hunter Adams's RP2040 motor library).
DMA streams the phase sequence and timing parameters into P
Technologies used
Hardware components
- RP2040
- stepper motor
- DC motor
- IMU
- motor driver
Software & tools
- Python
Project demo video
What you get
- Working project / hardware kit, tested before delivery
- Complete source code with explanation
- Project demo and guidance for your viva
- Project report, PPT and IEEE paper support (on request)
Delivery & Payment
Delivery takes a minimum of two weeks from the date your inquiry is confirmed.
Payment is in two parts:
• 50% advance to start the project
• Remaining 50% before delivery
Note:
• Documentation and PPT are not included by default
• If you need documentation/PPT, it can be arranged for extra time and cost
We'll confirm the exact timeline and cost with you after reviewing your requirements.