Gnuradio Mini Projects

This page presents a few miniature projects I've used to learn gnuradio. The gnuradio tutorials are first rate, but there's nothing like learning by creating something yourself.

Mike Markowski, mike.ab3ap@gmail.com

FM Radio

I've been writing DSP code outside of gnuradio the past several years but in 2021 again started using gnuradio at work. To brush the dust off my gnuradio skills, meager at best anyway!, I decided to tackle the old favorite and make myself an FM stereo receiver. While Googling, I came across a well written article, FM Reception with the GNU Radio Companion. Mine is only a very little bit different. While the author of that article has space constraints, I don't have those concerns and am able to expand flowgraphs for the sake of learning. I duplicate his work with small changes to make it work under gnuradio 3.8 (edit, updated to 3.10) on Ubuntu: I add to the above in some small but hopefully interesting ways:

Comments, additions and recommendations are welcome.

The flow graph: fmRadio.grc and embedded python block code: fmRadio_epy_block_0.py and fmRadio_epy_block_1.py.

I use gnuradio-companion from an Ubuntu apt install, though expect to compile from source to support out of tree modules. I have gr-fosphor installed for the nice RTSA-like RF spectrum display. You can click on it to change frequency easily. Python blocks will snap to nearest FM station, based on N. American channel spacing.

A view of the spectrum is shown below, and you can again click to tune. I recommend using Max Hold to more easily see where to double-click to change stations. (You can click on this tab or on the gr-fosphor display.) The screenshots shown here are a little out of date, but differences are minimal.

If you want a simple radio player without signal graphing, maybe you prefer the one below (flowgraph fm.grc). If you are new to gnuradio, looks at this flowgraph before tackling the one above which has a lot more going on in the gui.

AM Radio

You can't have a broadcast FM receiver without one for AM! I wish I could combine them into one program and GUI, but (I think?) there's no way to combine the GUIs using gnuradio components.

My SDR's lowest frequency is 70 MHz. As a result, I bought a NooElec up-converter that up-converts 0 to 65 MHz to start at 125 MHz. You'll notice a variable in the flowgraph referencing that. If you're luckier than me and don't need it, just set it to zero. Here is a screenshot. No coincidence that looks similar to the FM one. :-)

I find it important to decrease RF gain for noisy stations. To compensate for my up-converter, I also find it necessary to fine tune.

The flow graph: amRadio.grc and embedded python block code: amRadio_epy_block_0.py and amRadio_epy_block_1.py.

The second tab, shown below, is handy to double click in the frequency display. Python Blocks will snap the arbitrarily chosen frequency to the nearest AM station. Keep in mind that the code uses North American spacing and must be changed for regions with different spacing.

As with FM, here is the same thing but without signal plotting. I prefer this in the corner of my screen while working. It should be easy to combine this and the small FM one.

Here is the flowgraph, am.grc.

And a screenshot:

Gnuradio Official Tutorials

Be sure to run through the nice set of gnuradio tutorials. They're really a great introduction. I find it challenging to follow flow graphs that wind around, and some of my re-created flowgraphs might be easier to follow if you're like me. Here are my versions. sometimes small modifications, like fading for bpsk, but overall nothing new.

Gaussian Noise

Using arbs (arbitrary waveform generators) in the lab, it is often useful to play one or more bands of noise against a desired signal. It's helpful to generate noise by specifying sample rate to coincide with the desired signal, number of samples, center frequencies of noise, and corresponding AWGN band bandwidths.


Additive white Gaussian noise flow graph

And sample output not mixed to center frequency:


Generated noise

After using an import block, the vector source simply calls a function in the imported code. If you're interested in this,

Gaussian Noise, Take Two

A purely gnuradio solution is to create Gaussian noise and throw some filters downline from it.


Multi-band AWGN flow graph

And sample output:


Multi-band AWGN

Chirp

Like noise, it is sometimes useful to play a chirp signal against a receiver. One of the gnuradio tutorials does this in a clean way using a probe. The probe follows a triangle wave level and modifies a sine wave's frequency with that value. As a learning exercise, I wanted to incorporate custom code in gnuradio. If you don't use the audio source in the flow graph, be sure to use a throttle block. Also, I have no idea why, but without the ratio resampler the frequency and waterfall sinks don't update as often. The rational resampler is not at all needed mathematically, but is a poor hack so that the GUI updates more smoothly. Maybe someone can explain that to me.


Chirp flow graph

And sample output:


Generated chirp

After using an import block, the vector source, like in the noise example, calls a function in the imported code. Feel free download,

Morse Code Decoding

(Update in 2021: since writing this in 2015 I realize that if the thresholding yields a good signal, a custom block can complete the cw-to-text. However, a trained neural network will easily do a much better job but that requires recording or creating many examples...and I'm not quite motivated enough! Just like text recognition CNNs find both characters and words, a CW demod can be designed almost identically but in the audio realm.)

A more ambitious mini project currently has me stumped. I reached a point where I believe I can't use existing gnuradio blocks but must write my own demodulation block.

I used the following flowgraph

which resulted in this output where I added the yellow highlights and decoded text, which is my amateur radio callsign.

To decode I need to use timing of waveform edges, making me think now I must learn to write an out of tree block. This example shows a signal with no noise, no fading, no interference and perfect CW weighting - and I can't even handle that currently. :-) Advice is welcome!