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,

FM Radio

I've been writing DSP code outside of gnuradio the past several years but in 2021 am again using gnuradio. 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 on Ubuntu: I add to the above in some small but hopefully interesting ways:

Comments, additions and recommendations are welcome. I plan to replace a PSK Demod block for RDS demodulation with newer blocks that aren't deprecated. Every now and then I'll replace the flowgraph here with updates.

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

Sample output on my Ubuntu 20.10 machine. I have gr-fosphor installed for the nice RTSA-like RF spectrum display. Unfortunately, you can't interact at all with the Fosphor display like a real RTSA. I hope more functionality is added in future.

A view of the spectrum where a user can click to change frequency is shown here. This is the most useful tab. A disadvantage is that the slider for frequency is completely independent of the far right orange display of frequency. This is not desirable, but I can't figure out a way around it. I like the slider to quickly move across the band, but I also like to click to change stations. At the moment, these cannot be tied together in gnuradio.

I recommend using Max Hold to more easily see where to double-click to change stations.

If you want a simple radio player without signal graphing, maybe you prefer this (flowgraph fm.grc):

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 compenstate for my up-converter, I also find it necessary to fine tune.

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

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


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!