← back

Pocket Radar

A 180° ultrasonic radar built from drone parts after the original drone project failed to get off the ground. Sweeps, pings, draws.

how this happened

The original plan for EDES 301 was an autonomous agricultural drone that flew a field and surveyed crops. Then the supply chain happened: the LiPo we needed wouldn't ship, one of the ESCs we'd ordered was a different revision than the datasheet, and we ran out of weeks before we ran out of dependencies.

So we grounded the drone and rebuilt what we had into something that could still demo. The flight controller became a Linux board on a desk. The gimbal became a servo-driven scan head. The altitude sensor (ultrasonic) became the radar's range finder. Same parts, different problem.

what it does

A PocketBeagle drives two servos that sweep two ultrasonic sensors across a 180° arc. Each ping gets time-of-flight processed in software and turned into a (range, bearing) pair. A small Flask web server hosts an HTML5 canvas dashboard that draws the sweep in real time. There's a manual mode (slider to aim the head), an auto-scan mode (continuous sweep), and a tunable alarm threshold that flashes red when something crosses the range you set.

Pocket Radar build on a bench, dashboard visible on the laptop
the built radar with the canvas dashboard running.
HTML5 canvas radar dashboard with sweep, bearing, range, and controls
the dashboard: sweep trail, controls, alarm threshold, and a running log of detections.

hardware

ComputePocketBeagle
Ranging2× HC-SR04
Sweep2× SG90
InputGrove 12-ch touch

the voltage thing

The PocketBeagle's GPIO runs at 3.3 V. The HC-SR04 ultrasonic sensor needs 5.0 V on its supply and won't trigger reliably below that. The drone hardware happens to have a 5 V rail on pin P1_05 (VBUS), so the fix was a split-rail bus: 5 V to the sensors and servos, signal lines pulled down to 3.3 V on the GPIO side. Once that was sorted, the actual time-of-flight loop is the easy part.

Breadboard wiring with the PocketBeagle and Grove keypad
PocketBeagle, jumpers, and the Grove keypad on the bench.

time of flight

Fire a 10 µs pulse on TRIG, wait for the rising edge on ECHO, measure how long ECHO stays high. The pulse travels at the speed of sound (340 m/s in dry air, 343 with humidity), bounces off whatever it finds, and comes back. Distance to the object is half the round trip.

distance_cm = (echo_us * 34300) / 2 / 1_000_000

The /2 is because the wave goes out and comes back. The 34300 is just 343 m/s converted to cm/s. The sensor is rated to about 4 m before the return pulse drops below the threshold and you start getting timeouts.

software

Two threads. The first owns the radar: step the servo, fire a ping, wait for echo, calculate range, write to a shared buffer. The second is a Flask server that exposes the buffer over a websocket and serves the dashboard. The canvas takes (angle, range) tuples and draws them on a polar plot with a sweep trail.

The HC-SR04 Python libraries I could find all assumed Raspberry Pi GPIO and didn't work on the PocketBeagle, so the GPIO ended up as a thin userspace shim that reads and writes the sysfs files directly:

echo 1 > /sys/class/gpio/gpio59/value

Crude but works, and writing it from scratch took less time than fighting the libraries.

Drawing the sweep on the canvas is just polar-to-cartesian: each detection has a range r and a bearing θ, and the dashboard projects it onto pixel coordinates.

Polar to cartesian conversion: x = x_center + r·cos(θ), y = y_center − r·sin(θ)
canvas y is inverted, hence the minus sign.

what's left to fix