Skip to main content
All posts Workshop Recap

How We Built a Working Radar System with a $20 SDR Dongle and GNU Radio

Eighteen students, one afternoon, zero prior radar experience. Here's how we turned cheap hardware and open-source signal processing software into a working object detection system — and what we learned along the way.

Juhani Virtanen

Technical Officer

·9 min read
#sdr #gnu-radio #rf #python #workshop

Radar sounds like expensive defence industry hardware. For most of IEEE history, it was. But the combination of cheap software-defined radio hardware and mature open-source signal processing libraries has changed that equation completely — and our February workshop was proof.

In four hours, 18 students with no prior RF experience built a system that could reliably detect objects passing in front of an antenna. Here's how we did it, what broke, and what anyone can replicate at home for under €25.

Background & Motivation

The idea came from a throwaway comment at our December social: "could we actually build a radar with one of those TV dongles?". A few weeks of reading later, the answer was clearly yes — and the workshop was born.

The goal wasn't to build production-grade radar. It was to make the underlying physics and signal processing tangible. There's a specific moment when an abstract concept like Doppler shift becomes real — when you move your hand in front of an antenna and watch a frequency peak appear on a spectrum. That's what we were after.

"Understanding comes from doing. Reading about Doppler shift is fine; watching it appear in real-time on a spectrum analyser connected to hardware you built yourself is something else entirely."

The Hardware Stack

The full parts list per student station came to €23:

  • RTL-SDR v3 dongle (€18 from various suppliers)
  • Two cheap 2.4GHz patch antennas (€3 combined)
  • SMA to MCX adapter (€2)
  • Laptop with Ubuntu 22.04 or Debian 12

We ordered 10 dongles in bulk from a reliable supplier three weeks in advance. The antennas were repurposed from old WiFi routers — good enough for a demonstration, not for production.

RTL-SDR: What it Actually Is

The RTL-SDR is a USB device originally designed as a DVB-T TV tuner. In 2012, it was discovered that the chip inside (Realtek RTL2832U) could be put into a raw I/Q sampling mode, turning it into a wideband software-defined radio receiver. It covers roughly 24 MHz to 1.766 GHz with a tunable bandwidth of up to 3.2 MHz.

It can't transmit — it's receive-only. For a continuous-wave radar demonstration, this means we need a separate transmitter, which we handled with a second device running a simple signal generator in GNU Radio.

Setting Up GNU Radio

GNU Radio is the open-source toolkit that does the heavy lifting. It provides a visual programming environment (GRC — GNU Radio Companion) where you build "flowgraphs" by connecting signal processing blocks. It's Python under the hood, and every block can be extended or replaced with custom Python code.

Installation

On Ubuntu/Debian, the simplest path is:

# Install GNU Radio and the RTL-SDR source blocks
sudo apt update
sudo apt install gnuradio gr-osmosdr rtl-sdr

# Blacklist the kernel DVB driver so it doesn't grab the dongle
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee /etc/modprobe.d/blacklist-rtl.conf
sudo modprobe -r dvb_usb_rtl28xxu

# Verify the dongle is detected
rtl_test -t

Expected output from rtl_test:

Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 1.0 2.0 ...
Sampling at 2048000 S/s.
No E4000 tuner found, aborting.

Building the Flowgraph

The core radar flowgraph has four stages:

  1. RTL-SDR Source — tunes to our transmit frequency, outputs raw I/Q samples
  2. Multiply — mixes the received signal with a local oscillator copy (the Doppler processing step)
  3. Low-pass Filter — removes high-frequency mixing products, isolates the Doppler shift
  4. FFT Sink — displays the frequency spectrum in real time

In GRC, this looks like connecting four boxes with lines. The magic is that this simple graph implements the core of a continuous-wave Doppler radar.

# The equivalent Python (what GRC generates under the hood)
import numpy as np
from gnuradio import gr, blocks, filter, fft

class radar_flowgraph(gr.top_block):
    def __init__(self):
        super().__init__()

        samp_rate = 2.048e6  # 2.048 MS/s
        center_freq = 2.4e9  # 2.4 GHz (WiFi band, unoccupied channel)

        # RTL-SDR source
        self.rtlsdr_source = osmosdr.source()
        self.rtlsdr_source.set_sample_rate(samp_rate)
        self.rtlsdr_source.set_center_freq(center_freq)
        self.rtlsdr_source.set_gain(30)  # dB

        # Low-pass filter (isolate DC ± 10 kHz — Doppler range for walking speed)
        self.lpf = filter.fir_filter_ccf(
            decimation=1,
            taps=filter.firdes.low_pass(1, samp_rate, 10e3, 1e3)
        )

        # FFT display sink
        self.fft_sink = fft.logpwrfft_c(
            sample_rate=samp_rate,
            fft_size=1024,
            ref_scale=2,
            frame_rate=30,
            avg_alpha=0.5,
            average=True
        )

        # Wire it up
        self.connect(self.rtlsdr_source, self.lpf, self.fft_sink)

The Physics (Just Enough)

Continuous-wave radar works on the Doppler effect. When you transmit a continuous signal at frequency f and an object moves toward you at velocity v, the reflected signal comes back at a slightly shifted frequency:

The Doppler shift is: Δf = 2v·f / c

Where c is the speed of light. For a hand moving at 1 m/s toward a 2.4 GHz transmitter, the Doppler shift is about 16 Hz — small, but easily detectable with GNU Radio's FFT.

When you mix the received signal with the transmitted signal (the multiply block in our flowgraph), any reflected components appear at the Doppler frequency rather than at DC. Moving your hand shows up as a peak that drifts left or right depending on direction of motion. This is what made the workshop click for people — it's immediately intuitive once you see it.

Results & Limitations

The system reliably detected:

  • Hand movement at up to ~2 metres from the antenna
  • Directional motion (toward vs away from antenna)
  • Approximate speed (peak position in the FFT)

It could not detect:

  • Range (CW radar without chirp can't measure distance)
  • Multiple objects simultaneously (targets alias onto each other)
  • Slow-moving objects (below ~0.1 m/s lost in noise)

Some stations had issues with RF interference from the building's WiFi network at 2.4 GHz — we'll move to a less congested frequency for the next iteration. The original plan was 5.8 GHz, but we couldn't get the antennas in time.

Key Takeaways

A few things that surprised us running this workshop:

First, the bottleneck wasn't the hardware — it was the USB. Several laptops with USB 2.0 ports dropped samples under load, causing gaps in the spectrum display. Dedicated USB 3.0 ports fixed this. Worth checking before any workshop like this.

Second, GNU Radio Companion (GRC) is genuinely approachable. Students who had never touched signal processing connected a working flowgraph in under 30 minutes. The visual metaphor of signal flow maps well to how RF engineers think.

Third, and most importantly: the moment when the theory becomes real matters enormously. Multiple students said the Doppler workshop changed how they understood their antenna and wave propagation lectures. There's something irreplaceable about hardware that responds to you in real time.

We're planning a follow-up session on FMCW radar (the kind that can measure range) using a Raspberry Pi and a 24 GHz radar module. Watch the events page.