CyBot
Autonomous Navigation and Object Detection
A team mobile-robot project on a TM4C123 microcontroller: register-level C drivers for the robot's sensors, a 180° scan-and-detect pipeline, and a Python TCP client that plots scans live and lets you click on the map to send the robot there.
Source: GitHub repository (private, available on request)
Overview
CyBot is a mobile robot driven by a TI TM4C123. A servo sweeps an infrared sensor and an ultrasonic (ping) sensor across 180°. The firmware turns those readings into a list of detected objects with estimated widths, then turns using an IMU heading and drives while watching the bumpers and cliff sensors. A Python program on a laptop talks to the robot over TCP to show each scan and send movement commands.
I built the embedded C drivers and control logic and the Python TCP interface as part of a team; the repository has commits from several teammates. The LCD, timer, and Roomba Open Interface libraries were provided by the course, and the team wrote the rest.
How a scan becomes a move
Sweep and sample
The servo steps from 0° to 180° in 1° increments (181 points). At each angle the firmware averages two IR readings and two ping readings, converts the raw IR ADC value to centimeters with a fitted calibration curve (a sum of two exponentials), and sends an
angle,IR,pingline to the host.Detect object edges
An object starts or ends wherever the IR distance jumps by more than 30 cm compared with the reading two degrees earlier. Anything farther than 80 cm is ignored as background. Each object gets a start and end angle, and its distance comes from the ping sensor.
Estimate width
Each object's linear width is calculated with the law of cosines, using its two edge distances and the angle between them. The objects are then sorted from smallest to largest width with
qsort.Turn and approach
In autonomous mode, the robot points the sensors at the smallest object, measures its distance, turns to face it using the IMU heading, and drives until it is about 5 cm away.
Drivers
Ultrasonic ping
Sends a 10 µs trigger pulse on PB3, then switches the pin to Timer 3B input capture. An interrupt handler timestamps the rising and falling edges of the echo, and the pulse width is converted to distance in cm.
IR distance
Reads the analog IR sensor on PB4 / AIN10 with ADC0 sample sequencer 1 and returns the raw 12-bit value, which is then converted to cm with the calibration fit.
Scanning servo
Timer 1B in PWM mode on PB5 with a 20 ms period. Each robot gets per-unit calibration values for 0° and 180°, set with an on-board routine that uses the push buttons and LCD.
IMU heading
A BNO055 IMU connected over I2C1 on PA6/PA7 and put into its accelerometer-plus-gyroscope fusion mode. Turns track heading toward a target angle, handle the wrap-around at 360°, and stop within 0.2°.
Movement and safety
Forward and backward moves use the Roomba Open Interface and keep a running total of distance traveled. The robot stops on a left or right bumper hit, or when a cliff sensor reads very bright (above 2600) or very dark (below 700). Movement status streams to the host as it drives.
UART link
UART1 on PB0/PB1 at 115200 baud, with a printf-style send function and line-based receive for incoming commands.
Host interface
A Python program connects to the robot over a TCP socket and draws each scan on a live matplotlib plot in Cartesian coordinates, with the IR trace in red and the ping trace in cyan.
- Clicking a point on the plot converts it to an angle and distance and sends
goto <angle> <distance>, so the robot turns and drives to that spot. - Control buttons for Scan, Forward, Backward, Clockwise, Counter-clockwise, and Quit.
- Shift-click marks points of interest on the map, and Shift-scroll zooms the plot.
- After a scan command the program reads all 181 scan lines, and while the robot moves it shows the movement and sensor status the robot sends back.
Command protocol
| Command | Action on the robot |
|---|---|
n | Run a 180° scan and stream the readings |
h | Scan, pick the smallest object, turn toward it, and approach |
goto <angle> <distance> | Turn to an angle (0–360°) and drive the given distance |
w / s | Move forward or backward in small steps |
a / d | Turn 10° counter-clockwise or clockwise |
c | Print the four cliff-sensor readings (debugging) |