Home » Electronics » GNU Radio and Gqrx SDR Receiver

GNU Radio and Gqrx SDR Receiver

grc logoIn my last post, I was using the RTL2832 TV tuner dongle to get a simple Software Defined Radio (SDR) operational.  I wanted to use the SDR# program as my receiver but found that the MS Windows tool would not work and so I targeted Gqrx as an alternative. Gqrx is dependent on the GNU Radio.  So in this post, I plan to get Gqrx and GNU Radio up and operational with the RTL-SDR dongle.  I spend some time with other tools to help further verify (with mixed success) that GNU Radio is working.

The contain here comes from multiple source and I attempt to list those sources below.  For a good video to get a sense of what your in for, check out this video. Also, this post covers many of the topics here.

GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software defined radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment. It is being used in hobbyist, academic, and commercial environments to support both wireless communications research and real-world radio systems. 

Gqrx is an experimental AM, FM and Single Side Band (SSB) software defined receiver implemented using GNU Radio and the Qt GUI toolkit. Currently it works on Linux and can use the RTL_SDR dongles as input source.

Also within this post, I venture out from gqrx to examine a few other tools.  I don’t cover much territory, nor have much success.  The insperation to examine these other tools comes mainly from the lengthy post “RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver“.  Also check out “Getting Started with GNU Radio and RTL-SDR (on Backtrack)“.

Build GNU Radio on Ubuntu

The GNU Radio web site has specific instructions and a build script for installing it on Ubuntu (I’m using version 13.04).  This process claims it may take 1-2 hours to do the install (for me it ran in 1 hour 14 minutes).  The steps are as follows:

cd ~/src
mkdir ~/gnuradio
cd ~/gnuradio
wget http://www.sbrac.org/files/build-gnuradio && chmod a+x ./build-gnuradio && ./build-gnuradio --verbose

When prompted, tell it to proceed and give it sudo privilege by typing “Y”. Because of the --verbose option, you will see a lot of text whizzing by as the build-gnuradio script does its thing. You’ll also see a percentage complete indicator as the script works its way down it tasks.

The GNU Radio build creates a large variety of tools which get installed into /usr/local/bin.  You also notice that tools not directly related to GNU Radio are also created. I’ll leave it for another time to understand and explain the GNU Radio environment.

The “Hello World” of GNU Radio

To verify that the software is working, best thing is to create the typical “Hello, World” program, just we might have done for our first foray into C++, Python, or other programming language.  In the world of GNU Radio, this program has come to be the phone dial tone. To do this, I followed the video The “Hello World” of GNU Radio: Dial Tone and the gnuradio.org.  I did this using the GNU Radio Companion (executable located at /usr/local/bin/gnuradio-companion).  GNU Radio Companion (GRC) is a graphical tool for creating signal flow graphical models and generating Python source code for the model created.

GRC’s generated flow and code for the “Hello, World” program is listed below. The Python code for the dial tone program was placed in the home directory, and in my case, it was called dail_tone.py. While it can be executed via the gnuradio-companion, it can also be executed via python dial_tone.py. The user interface for the GRC and the corresponding Python code it generated is listed below:

dial_tone.grc - -home-jeff - GNU Radio Companion_006

#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: Dial Tone
# Author: Jeff Irland
# Description: "Hello, World" program - produces phone dial tone
# Generated: Sat Jun 22 21:24:56 2013
##################################################

from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import window
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from gnuradio.wxgui import fftsink2
from gnuradio.wxgui import forms
from gnuradio.wxgui import scopesink2
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wx

class dial_tone(grc_wxgui.top_block_gui):

	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Dial Tone")
		_icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
		self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

		##################################################
		# Variables
		##################################################
		self.samp_rate = samp_rate = 32000
		self.noise_slider = noise_slider = .005

		##################################################
		# Blocks
		##################################################
		_noise_slider_sizer = wx.BoxSizer(wx.VERTICAL)
		self._noise_slider_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_noise_slider_sizer,
			value=self.noise_slider,
			callback=self.set_noise_slider,
			label='noise_slider',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._noise_slider_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_noise_slider_sizer,
			value=self.noise_slider,
			callback=self.set_noise_slider,
			minimum=0,
			maximum=.1,
			num_steps=1000,
			style=wx.SL_VERTICAL,
			cast=float,
			proportion=1,
		)
		self.Add(_noise_slider_sizer)
		self.wxgui_scopesink2_0 = scopesink2.scope_sink_f(
			self.GetWin(),
			title="Scope Plot",
			sample_rate=samp_rate,
			v_scale=0,
			v_offset=0,
			t_scale=0,
			ac_couple=False,
			xy_mode=False,
			num_inputs=1,
			trig_mode=gr.gr_TRIG_MODE_AUTO,
			y_axis_label="Counts",
		)
		self.Add(self.wxgui_scopesink2_0.win)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_f(
			self.GetWin(),
			baseband_freq=0,
			y_per_div=10,
			y_divs=10,
			ref_level=0,
			ref_scale=2.0,
			sample_rate=samp_rate,
			fft_size=1024,
			fft_rate=15,
			average=False,
			avg_alpha=None,
			title="FFT Plot",
			peak_hold=False,
		)
		self.Add(self.wxgui_fftsink2_0.win)
		self.blocks_add_xx_0 = blocks.add_vff(1)
		self.audio_sink_0 = audio.sink(32000, "pulse", True)
		self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, .1, 0)
		self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, .1, 0)
		self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, noise_slider, 0)

		##################################################
		# Connections
		##################################################
		self.connect((self.blocks_add_xx_0, 0), (self.wxgui_scopesink2_0, 0))
		self.connect((self.blocks_add_xx_0, 0), (self.audio_sink_0, 0))
		self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx_0, 2))
		self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx_0, 1))
		self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx_0, 0))
		self.connect((self.blocks_add_xx_0, 0), (self.wxgui_fftsink2_0, 0))

	def get_samp_rate(self):
		return self.samp_rate

	def set_samp_rate(self, samp_rate):
		self.samp_rate = samp_rate
		self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
		self.analog_sig_source_x_1.set_sampling_freq(self.samp_rate)
		self.wxgui_fftsink2_0.set_sample_rate(self.samp_rate)
		self.wxgui_scopesink2_0.set_sample_rate(self.samp_rate)

	def get_noise_slider(self):
		return self.noise_slider

	def set_noise_slider(self, noise_slider):
		self.noise_slider = noise_slider
		self.analog_noise_source_x_0.set_amplitude(self.noise_slider)
		self._noise_slider_slider.set_value(self.noise_slider)
		self._noise_slider_text_box.set_value(self.noise_slider)

if __name__ == '__main__':
	parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
	(options, args) = parser.parse_args()
	tb = dial_tone()
	tb.Run(True)

When the GRC flow execution button is pressed, the scope and FFT plots are are created as shown below:

Dial Tone_005

The build for GNU Radio also installs the RTL-SDR software, so it would be wise to test GNU Radio with the RTL_SDR hardware and make sure everything is operating as expected.  I want to make a simple FM receiver, comparable to what was done via rtl_fm in RTL-SDR – Software Defined Radio (SDR) for $20. Something equivalent to:

rtl_fm -W -f 99.5M | play -r 32k -t raw -e signed-integer -b 16 -c 1 -V1 -

Using the following postings as a guide:

I had sufficient success to convince myself that GNU Radio was work.

Building Gqrx on Ubuntu

Gqrx is a software defined AM, FM and SSB software defined radio receiver for RTL-SDR based dongles (as well as the Universal Software Radio Peripherals and Osmo SDR devices).  It features a  Qt GUI.  As a QT program, you’ll need to make sure you have QT4 installed (version 5 will not work) and that you have the qtcreator tool is installed:

sudo apt-get install qt4-default
sudo apt-get install phonon-backend-gstreamer

Now download the source for Gqrx via its page on GitHub  and extract it into your target directory. The posting Getting Started With RTL-SDR and the README on the GitHub site where useful in understanding how to do the install.  I did the following:

cd ~/src
git clone git://github.com/csete/gqrx.git
cd gqrx
qmake gqrx.pro
make

At this point, you should find the gqrx executable in ~/src/gqrx directory.  Start up via ./gqrx and you’ll get the screen below (or set your values to equal this):

Configure I-O devices_001

Click “OK” and the screen below will pop up.  Make sure you have the RTL-SDR dongle plugged in and select the button on the top left to start processing data.  I have tuned the radio to a local FM station at 85.7MHz and listen to Washington Nationals vs. Phillies baseball!

Gqrx 0.0 - rtl=0_004

Building Multimode Radio Receiver

This radio receiver is capable of demodulating muitiple modes, specifically AM, FM, USB, LSB , WFM. TV-FM, PAL-FM. It’s easy to use and  has an automated scanning and spectral zoom features where clicking on the spectrogram or panorama to tune to the frequency of interest.

Multimode documentation is sparse to non existent. The posts “Using the Realtek RTL2832 USB “dongle” as a gnuradio multimode receiver” and “RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver” and “Getting Started with GNU Radio and RTL-SDR (on Backtrack)” gave some important hints on how to install multimode and get it operational.  I did the following:

cd ~
svn co https://www.cgran.org/svn/projects/multimode/trunk/ ~/src/multimode
make install

When I executed multimode.py, it didn’t product a display.  I suspect its some subtle Python code problem, or more likely.  incompatibility with the latest GNU Radio libraries.  For now, I’m going to abandon this.

GNU Radio Signal Scanner

gr-scan is a program  built upon GNU Radio, rtl-sdr, and the OsmoSDR Source Block.  This receiver constantly changes frequencies in a set order looking for a frequency that has someone transmitting. It is intended to scan a range of frequencies and print a list of discovered signals.  Installation involved the following steps:

cd ~./src
mkdir gr-scan
cd gr-scan

with your browser, download: http://www.techmeology.co.uk/gr-scan/gr-scan-2012082301.tar.gz
gzip -d gr-scan-2012082301.tar.gz
tar -xvvf gr-scan-2012082301.tar
cd gr-scan-2012082301
make

When I attempted to do the make, it complained about missing Gun Radio files.  I suspect the GNU Radio libraries and include files are layed out differently since the time gr-scan was designed (August of 2012).  I’m leaving fixing this to another time.

What’s Next

In this and the previous SDR posts, I focused on getting a taste of the technology without committing myself to much of an effort.  I really need to study and understand the tools that I have assembled. I still need to do a great deal more studying of  the radio spectrum itself … I feel like I’m wondering in the dark most of the time.

Also, I feel that I’m very limited by the antenna I’m presently using (the pitiful dipole that came with the RTL dongle).  I’m thinking of building a better antenna.  Maybe try to pickup a NOAA weather satellites, with its distinctive audio signal when demodulated, and decode one of its satellite weather photos …. maybe.

Another problem with the RTL-SDR is that its internal oscillator is cheap  and drifts, resulting in clock errors with  many kHz of frequency display error in SDR – depending on a band you’re listening to.  This is very annoying if you use your dongle as a radio scanner – what’s the point of knowing frequency of a transmitter if it’s almost random on your SDR?   This frequency error is linear across the spectrum, and can be adjusted in most SDR programs by entering a PPM (parts per million) offset value.  So I need to calculate this error offset so I can  calibrate the SDR software.


7 Comments

  1. […] GNU Radio and Gqrx SDR Receiver July 8, 2013 […]

  2. jeanB says:

    Hey nice how-to but since last release of gqrx or package in sbrac script, compilation of gqrx failed (cause name of some *.h in gnu radio changed).

  3. Widget says:

    You can calibrate the error by searching for GSM basestations and calibrating off them, like GSM phones do.
    https://github.com/steve-m/kalibrate-rtl

  4. adsicks says:

    You didn’t miss much with Multimode, GQRX has the same features and seems to work better. I had to export the path where the multimode_helper.py was into my PYTHONPATH variable which was unset on my system to get multimode to work. I couldn’t get SDR# to work with my dongle because I guess SDR# doesn’t play nice with the 820T chip and the sample rates.

    What is limiting about all of this SDR stuff on Linux (besides the software being new and hence buggy) is there is no v4l interface to use these with K or Gnome Radio, so aside from the remote, the kernel module seems kind of worthless. The osmosdr stuff can’t run at the same time as the kernel drive with the loaded remote control kernel module. I don’t know if it is a hardware limit or why the driver can’t expose raw input and outputs that can be used my osmosdr.

    But hey, I have had alot of fun and have learned quite a bit playing around with this stuff. Not bad for $12.

  5. Pud says:

    Nice tutorial. Didn’t do the GQRX build, instead did an apt-get on my ubuntu. Not having a clue what I’m doing so I just set the configuration to what you provided and bingo – got reception right off the bat!
    Just what I wanted – $25 delivered and good enough for now for learning purposes.

    Big thanks

  6. Martin says:

    What’s the repository for qt4?

    sudo apt-get install qt4-default
    E: Unable to locate package qt4-default

  7. This indicates that the small blind functions first before flop and functions final in succeeding rounds. I’ve arrive to realize that almost nobody’s primary purpose for playing is strictly to make money.

Leave a comment