User:Duggabe: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
(completed draft)
(first draft)
Line 1: Line 1:
<!-- AM_tutorial.mediawiki -->
<p><b>This page is my working space while editing Wiki pages.</b></p>
The first section of this tutorial explains how an Amplitude Modulated (AM) signal can be created. Rather than using any real hardware for transmission, the signal is sent via a socket to the second section of the tutorial which explains how to demodulate the received signal. The only actual hardware involved is the computer's microphone input and speaker output. In the case of a Raspberry Pi computer, which has no microphone input, an alternative is presented.
<hr>
<!- Guided_Tutorial_Hardware_Considerations -->
== Prerequisites ==
 
* [[SuggestedReading|Our Suggested Reading list]]
* Tutorials:
** [[Guided_Tutorial_Introduction|'''A brief introduction to GNU Radio, SDR, and DSP''']]
** [[Guided_Tutorial_GRC|'''Intro to GR usage: GRC and flowgraphs''']]
** [[Sample_Rate_Tutorial|'''Understanding sample rate''']]
 
== Introduction ==
 
One of the great strengths of GNU Radio is how easy it is to move from simulation to real-world operation. In this tutorial, we will build on what you have learned so far and create a complete FM radio receiver that you can use to listen to your local FM radio stations. Along the way, we will discuss a number of considerations that come into play when working with real-world radio hardware.
 
== What Will I Need? ==
 
If you don't have an actual radio to work with, this tutorial is still useful. You can simply use a recording from an actual radio, with nothing done to the data. We have provided a recording, which you can find [https://github.com/gnuradio/gr-tutorial/blob/master/examples/tutorial6/fm_101.8MHz_1Msps.cfile in the gr-tutorials repository]. You can use this in your flowgraph to simulate hardware passing you samples.
 
This tutorial will be most useful, though, if you have a piece of radio hardware that you can use with GNU Radio. There is a large and growing number of vendors that provide hardware with GNU Radio drivers, and they span from very cheap $20 receivers to very high-performance tens-of-thousands-of-dollars sort of systems.
 
The entirety of this tutorial is possible with a simple, low-bandwidth, half-duplex radio. Most of the tutorial is possible if you have a radio that can only receive, assuming it can tune to the FM bands. Most countries allot between ~87 MHz and ~108 MHz to FM broadcast radio, with some slight variations on the floor and ceiling of the range.
 
== Using UHD Blocks ==
 
The author is using an [https://kb.ettus.com/B200/B210/B200mini/B205mini Ettus Research USRP B200], which uses the [https://github.com/EttusResearch/uhd USRP Hardware Driver (UHD)]. Thus, the hardware sources &amp; sinks used in this tutorial will be [https://github.com/gnuradio/gnuradio/tree/master/gr-uhd/grc gr-uhd] blocks.
 
If you are using a different piece of hardware, you should use the blocks suggested by your hardware vendor. Another set of popular HW blocks, for example, is [http://sdr.osmocom.org/trac/wiki/GrOsmoSDR gr-osmosdr].
 
In order to use UHD blocks, you must have UHD installed. There are a number of ways to install UHD, which you can read about [http://code.ettus.com/redmine/ettus/projects/uhd/wiki here]. If you built GNU Radio from source, you should have seen '''gr-uhd''' in the list of components being built in the CMake output. If GNU Radio successfully found your UHD installation, you should see a group of UHD blocks in the GNU Radio Companion:
 
[[File:grc_uhd_blocks.png|250px|]]
 
== Building an FM Radio Receiver ==
 
In this section, we will build a working FM radio receiver that you can use to listen to your local FM broadcast stations. This content is based on the tutorial slide series prepared by Balint Seeber, available here: [http://files.ettus.com/tutorials/ files.ettus.com/tutorials]
 
=== Creating a Software Radio Spectrum Analyzer ===
 
One of the more basic (but also incredibly useful) things you can do in GNU Radio with a receiver is simply plot a real-time FFT of what your receiver sees. It's a software radio spectrum analyzer. This is also a great first step because it will verify that your hardware is working correctly, and we can use it to identify broadcast stations in your area that we will tune to later on.
 
Create a new flowgraph. Drop a 'UHD: USRP Source' and 'QT GUI Sink' into the canvas. In the previous section, we used static variables for frequency and gain. Here, let's make them changeable on-the-fly. Find the 'QT GUI Range', and add two of them to your flowgraph. Open each of them, and fill out the following fields as appropriate for your hardware. Mine are filled out, below, to match the capabilities of the USRP B200:
 
'''''QT GUI Range 1:'''''
 
* '''ID:''' freq
* '''Label:''' freq
* '''Default Value:''' 1e9
* '''Start:''' 70e6
* '''Stop:''' 6e9
* '''Step:''' 10e6
 
'''''QT GUI Range 2:'''''
 
* '''ID:''' gain
* '''Label:''' gain
* '''Default Value:''' 0
* '''Start:''' 0
* '''Stop:''' 74
* '''Step:''' 1
 
Change your 'samp_rate' variable block value to something interesting. I set mine to 32 MSps. Now, open up the properties for the 'UHD: USRP Source'. Just as we used our variable blocks in the previous section for our radio parameters, we will do the same here. Use the 'ID's from the 'range blocks', above, to set the 'UHD Source' parameters:
 
* '''Samp Rate (Sps):''' samp_rate
* '''Ch0: Center Freq (Hz):''' freq
* '''Ch0: Gain (dB):''' gain
* '''Ch0: Antenna:''' &quot;TX/RX&quot;
* '''Ch0: Bandwidth (Hz):''' samp_rate
 
When you are done, your flowgraph should look something like this:


This tutorial can be performed with either GNU Radio (GR) version 3.7 or 3.8 (and later). The Graphical User Interface gnuradio-companion (GRC) is used to create a flowgraph for each section.
[[File:simple_spec_an.png|500px|]]


== Prerequisites ==
You can also [https://raw.githubusercontent.com/gnuradio/gr-tutorial/master/examples/tutorial6/gr-tutorial-simple-spec-an.grc download this flowgraph if you want the reference file].
 
You should be all set!
 
=== Using Your Software Radio Spectrum Analyzer ===
 
Go ahead and run your flowgraph. You should see your received spectrum in real-time. Play with the sliders and values, and you should see everything update in real-time, as well. The default GNU Radio QT FFT sink has a number of useful features, such as averaging and peak-hold. Take some time to get familiar with them, now.
 
=== Building a Broadcast FM Receiver ===
 
Now that you have a basic receiver application running with a real-time display of your received data, let's build a useful application! Leave your current flowgraph in place. We will simply add more functionality into the flowgraph rather than replacing what is already there.
 
First, as you might have guessed, we will need to add a few more blocks to the flowgraph. Locate and add the following blocks:
 
* 1x Rational Resampler
* 1x WBFM Receiver
* 1x Audio Sink
* 2x Variable
 
Our flow of data will be the USRP Source -> Rational Resampler -> WBFM Receiver --> Audio Sink. Go ahead and connect the blocks together in that order. GNU Radio will likely highlight a lot of fields in red, indicating errors. We will now go through and configure the parameters, which will resolve these.
 
First, let's set-up those two new variable blocks you added. Create the following two variables with them:
 
'''''Variable:'''''
 
* '''ID:''' audio_interp
* '''Value:''' 4
 
'''''Variable:'''''
 
* '''ID:''' audio_rate
* '''Value:''' 48e3
 
Let's also go back and tune our sample rate variable, which we had previously. Change that variable to '''250e3''' (250 kHz).
 
'''''Variable:''''' samp_rate
 
* '''ID:''' samp_rate
* '''Value:''' 250e3


* [[Guided_Tutorial_GRC|'''Intro to GR usage: GRC and flowgraphs''']]
Now, let's configure your other three new blocks.
* [[Sample_Rate_Tutorial|'''Understanding sample rate''']]


== AM transmitter ==
'''''Audio Sink'''''<br />
This block is fairly straight-forward. It takes a stream of samples and plays them through your speakers. This block is installed with the ''gr-audio'' library, which is part of the core GNU Radio distribution. There are a few common / default rates that sound cards use - one of the most common is 48 kHz, which is what we will use, here (hence your configuration of the 'audio_rate' variable, above).


Using gnuradio-companion (GRC) and the following Block descriptions, build this flowgraph of the transmitter section:<br>
Open up the parameters of the Audio Sink. Make the following changes:


[[File:AM_transmit_fg.png|900px]]
* '''Sample Rate:''' audio_rate
* '''OK to Block:''' &quot;No&quot;


=== Block descriptions ===
Now, we just need to turn the samples from your hardware into something that you can play through your speakers! Let's go two blocks back up the chain, next.


* The Options block identifies the filename for the flowgraph, a title, author, etc.
'''''Rational Resampler'''''<br />
** id: AM_transmit
The USRP Source is streaming at a rate of 'samp_rate', which we just set to 250e3. The Audio Sink is configured for a sample (consumption) rate of 'audio rate', which is 48e3. But, we have a problem: our source sample rate isn't an integer multiple of the audio rate: 250000 / 48000 = 5.208. To fix this problem, we will 'resample' the stream. Think of resampling here as impedance-matching. We have to convert from the rate of the input stream to the rate of the output stream.
** Click on File -> Save As&nbsp;&nbsp;Use the file name 'AM_transmit'. the extension '.grc' is added automatically
* The microphone input is defined by an Audio Source block. The parameters are:
** Sample rate: set to 48khz (use the pull-down)
** Device name: for most microphone jacks built into the computer, the Device name can be left blank; for other cases, see [[Audio_Source#Device_Name]]
* For the remainder of the flowgraph, a sample_rate of 768khz is used. This value was chosen to give the 48khz carrier frequency 16 samples per cycle (48000 x 16 = 768000).
** Variable block
*** id: samp_rate
*** value: 768000
* To boost the 48khz sample rate of the audio input to the 768khz sample rate, a Repeat block with an Interpolation value of 16 is used.
* The QT GUI Range block defines an Audio gain (volume) control
** id: volume
** default value: 1.2
** start: 0
** stop: 10.0
** step: 0.1
** Widget: choose whatever you like
* The value of the volume control is used as a multiplier in the Multiply Const block.
** Constant: volume
* To create an AM signal, the carrier signal is multiplied by the audio signal plus one. The constant 1 creates the carrier when no audio is present.
** Add Const block
*** Constant: 1.0
* The carrier signal (in this example is 48khz) is generated by the Signal Source block.<br>
** Note: there is no correlation between the audio sample rate and the carrier signal frequency.
** Sample Rate: samp_rate
** Frequency: 48000
** Amplitude: 0.5
* The QT GUI Time Sink gives a visual representation of the transmitted signal.
** Number of Points: 4096
** Sample Rate: samp_rate
** Number of Inputs: 2
* For a real radio transmitter, the output of the Multiply block would be fed to band-pass filters and then to Radio Frequency (RF) hardware. For this tutorial, we are sending the transmit signal to a ZMQ PUB Sink data socket connected to the receiver section.
** Address: tcp://127.0.0.1:50001


=== Note for Raspberry Pi ===
The rational resampler block allows you to adjust the rate of a data stream. It does this by interpolating or decimating to achieve a desired sample rate. Open up the properties of this block, and let's tune the parameters.


Since a Raspberry Pi has no audio input jack, there are two alternatives:
Set the 'Type' to 'Complex-&gt;Complex', thus telling the block to use complex taps. Now we need to tune the actual rates. There is some intelligence built into this block - if we give it the different non-divisable sample rates, the code will calculate the GCD and make it all 'just work' for us. We know the incoming rate is 250 kSps, so let's enter that into 'Decimation'. But, this parameter must be an integer, and our 'samp_rate' is a float. Thus, we need to use the Python function 'int()' to convert it.


# use a USB audio dongle as is shown in the flowgraph.
Now we need to set the 'Interpolation' rate. There is a 'gotcha' here, because the WBFM block further down our chain will actually perform an additional decimation-by-four, so we need to actually tell this block to output a rate four times what we want. We know what we actually want is 'audio_rate', so use your 'audio_interp' variable to set the actual rate.
# replace the Audio Source block with a Signal Source block (frequency: 600) and a Throttle block.


=== Test transmitter section ===
At this point, you should have made these settings:


To test the transmitter, generate and run the flowgraph. Speaking into the microphone should show a change in the pattern on the QT GUI Time Sink. The level of modulation can be adjusted with the volume control.
* '''Type:''' Complex-&gt;Complex (Complex Taps)
* '''Interpolation:''' audio_rate * audio_interp
* '''Decimation:''' int(samp_rate)


== AM receiver ==
By leaving the 'Taps' parameter blank, we tell the block that we want it to compute the taps automatically. The 'Fractional BW' parameter affects the shape of the low-pass filter that is generated when no filter taps are supplied. By leaving this set to zero, we will just use a reasonable default.


Using gnuradio-companion (GRC) and the following Block descriptions, build this separate flowgraph of the receiver section:<br>
'''Note:''' Depending on the accuracy of the clock references in your hardware, you may need to tune the ''Interpolation'' field, above. This is one of the many hardware impairments that you may need to deal with. When I first ran this flowgraph, I heard a lot of noise. I then tuned that ''Interpolation'' rate, and it cleaned up. My final numbers were:


[[File:AM_receive_fg.png|900px]]
* '''Interpolation:''' int(1.05 * (audio_rate * audio_interp))
* '''Decimation:''' int(samp_rate)


=== Block descriptions ===
Now, let's configure our last block!


* The Options block identifies the filename for the flowgraph, a title, author, etc.
'''''WBFM Receiver'''''<br />
** id: AM_receive
At this point, configuring our last block is pretty simple. Open up the block's parameters. There are only two parameters to set: the rate of incoming samples, and the decimation rate. Well, we know both of these. We just configured the output rate of the rational resampler, and we know that rate divided-by-four equals our 'audio_rate'. Thus, you want:
** Click on File -> Save As&nbsp;&nbsp;Use the file name 'AM_receive'. the extension '.grc' is added automatically
* The signal from the transmitter section is received by the ZMQ SUB Source. It is a 48khz carrier with a sample rate of 768khz.
** Address: tcp://127.0.0.1:50001
* A Variable block defines the sample rate.
** id: samp_rate
** value: 768000
* Another Variable block defines the decimation factor. Since the Audio Sink (speaker) uses a sample rate of 48khz, we will reduce (decimate) the incoming sample rate by a factor of 16.
** id: decim
** value: 16
* The Frequency Xlating FIR Filter performs three functions: frequency translation, filtering, and decimation. See [[Frequency_Xlating_FIR_Filter]] for more detail.
** Type: Float->Complex (Real Taps)
** Decimation: decim
** Taps: firdes.low_pass(1,samp_rate,samp_rate/(2*decim), 2000)
** Center Frequency: 48000
** Sample Rate: samp_rate
* The Automatic Gain Control (AGC) block adjusts the input signal to the given reference level (1.0).
** The default settings should be used.
* The Complex to Mag block calculates the magnitude of the complex samples which produces the original modulation signal.
* The Band Pass Filter filters the signal between the low and high cutoff frequencies.
** FIR Type: Float->Float (Real Taps)(Decim)
** Decimation: 1
** Gain: 1
** Sample Rate: int(samp_rate/decim)
** Low Cutoff Freq: 500
** High Cutoff Freq: 6000
** Transition Width: 400
* The QT GUI Range block defines an Audio gain (volume) control
** id: volume
** default value: 0.3
** start: 0
** stop: 1.0
** step: 0.05
** Widget: choose whatever you like
* The value of the volume control is used as a multiplier in the Multiply Const block.
** Constant: volume
* The QT GUI Time Sink gives a visual representation of the received signal.
** Number of Points: 256
** Sample Rate: int(samp_rate/decim)
** Number of Inputs: 1
* The speaker output is defined by an Audio Sink block. The parameters are:
** Sample rate: set to 48khz (use the pull-down)
** Device name: for most speakers (or headphone jacks) built into the computer, the Device name can be left blank; for other cases, see [[Audio_Sink#Device_Name]]


=== Testing ===
* '''Quadrature Rate:''' audio_rate * audo_interp
* '''Audio Decimation:''' audio_interp


When using GRC, doing a Generate and/or Run creates a Python file with the same name as the .grc file. You can execute the Python file without running GRC again. For testing this system we will use two processes, so we will need two terminal windows.
=== A Working Software Radio Broadcast FM Receiver ===


Terminal 1:
And that should be it! You should now no longer see any red in your flowgraph, and you should be able to build your flowgraph without errors. The final result should look like this:
* since you just finished building the AM_receive flowgraph, you can just do a Run. After a few seconds, a GUI window will open with the Volume control and the GUI Time Sink.


Terminal 2:
[[File:broadcast_fm_rx_flowgraph.png|600px|]]
Open another terminal window.
* change to whatever directory you used to generate the flowgraph for AM_transmit
* execute the following command:
    python3 -u AM_transmit.py
* After a few seconds, a GUI window will open with the Volume control and the GUI Time Sink.


Speaking into the microphone should show a change in the pattern on both QT GUI Time Sinks. You should hear your voice from the speakers. The speaker volume can be adjusted with the receive volume control. The level of modulation can be adjusted with the transmit volume control. Note that increasing the transmit volume beyond 100% modulation causes distortion.
You can also [https://raw.githubusercontent.com/gnuradio/gr-tutorial/master/examples/tutorial6/gr-tutorial-broadcast-fm-rx.grc download this flowgraph, for reference].


To terminate each of the processes cleanly, click on the 'X' in the upper corner of the GUI rather than using Control-C.
Executing your flowgraph should bring up a GUI that looks something like what you see below. Changing the frequency and tuning to a local broadcast FM station should play the demodulated radio through your computer speakers.


== What do to next ==
[[File:broadcast_fm_running.png|600px|]]<br />


Now that you have a working system, you can experiment:
[[Category:Guided Tutorials]]
* change filter parameters
* replace the Audio Source block with a Signal Source block (frequency: 600) and a Throttle block (if you haven't already done that)
* change the carrier frequency - remember that you have to change Interpolation and Decimation factors too!
* use an AM Demod block instead of a Complex to Mag block. See [[AM_Demod]] for the details.
<b>Note:</b> Any time you make a change to a flowgraph, you must do a Generate to rebuild the Python file.

Revision as of 21:52, 13 April 2020

This page is my working space while editing Wiki pages.


<!- Guided_Tutorial_Hardware_Considerations -->

Prerequisites

Introduction

One of the great strengths of GNU Radio is how easy it is to move from simulation to real-world operation. In this tutorial, we will build on what you have learned so far and create a complete FM radio receiver that you can use to listen to your local FM radio stations. Along the way, we will discuss a number of considerations that come into play when working with real-world radio hardware.

What Will I Need?

If you don't have an actual radio to work with, this tutorial is still useful. You can simply use a recording from an actual radio, with nothing done to the data. We have provided a recording, which you can find in the gr-tutorials repository. You can use this in your flowgraph to simulate hardware passing you samples.

This tutorial will be most useful, though, if you have a piece of radio hardware that you can use with GNU Radio. There is a large and growing number of vendors that provide hardware with GNU Radio drivers, and they span from very cheap $20 receivers to very high-performance tens-of-thousands-of-dollars sort of systems.

The entirety of this tutorial is possible with a simple, low-bandwidth, half-duplex radio. Most of the tutorial is possible if you have a radio that can only receive, assuming it can tune to the FM bands. Most countries allot between ~87 MHz and ~108 MHz to FM broadcast radio, with some slight variations on the floor and ceiling of the range.

Using UHD Blocks

The author is using an Ettus Research USRP B200, which uses the USRP Hardware Driver (UHD). Thus, the hardware sources & sinks used in this tutorial will be gr-uhd blocks.

If you are using a different piece of hardware, you should use the blocks suggested by your hardware vendor. Another set of popular HW blocks, for example, is gr-osmosdr.

In order to use UHD blocks, you must have UHD installed. There are a number of ways to install UHD, which you can read about here. If you built GNU Radio from source, you should have seen gr-uhd in the list of components being built in the CMake output. If GNU Radio successfully found your UHD installation, you should see a group of UHD blocks in the GNU Radio Companion:

Grc uhd blocks.png

Building an FM Radio Receiver

In this section, we will build a working FM radio receiver that you can use to listen to your local FM broadcast stations. This content is based on the tutorial slide series prepared by Balint Seeber, available here: files.ettus.com/tutorials

Creating a Software Radio Spectrum Analyzer

One of the more basic (but also incredibly useful) things you can do in GNU Radio with a receiver is simply plot a real-time FFT of what your receiver sees. It's a software radio spectrum analyzer. This is also a great first step because it will verify that your hardware is working correctly, and we can use it to identify broadcast stations in your area that we will tune to later on.

Create a new flowgraph. Drop a 'UHD: USRP Source' and 'QT GUI Sink' into the canvas. In the previous section, we used static variables for frequency and gain. Here, let's make them changeable on-the-fly. Find the 'QT GUI Range', and add two of them to your flowgraph. Open each of them, and fill out the following fields as appropriate for your hardware. Mine are filled out, below, to match the capabilities of the USRP B200:

QT GUI Range 1:

  • ID: freq
  • Label: freq
  • Default Value: 1e9
  • Start: 70e6
  • Stop: 6e9
  • Step: 10e6

QT GUI Range 2:

  • ID: gain
  • Label: gain
  • Default Value: 0
  • Start: 0
  • Stop: 74
  • Step: 1

Change your 'samp_rate' variable block value to something interesting. I set mine to 32 MSps. Now, open up the properties for the 'UHD: USRP Source'. Just as we used our variable blocks in the previous section for our radio parameters, we will do the same here. Use the 'ID's from the 'range blocks', above, to set the 'UHD Source' parameters:

  • Samp Rate (Sps): samp_rate
  • Ch0: Center Freq (Hz): freq
  • Ch0: Gain (dB): gain
  • Ch0: Antenna: "TX/RX"
  • Ch0: Bandwidth (Hz): samp_rate

When you are done, your flowgraph should look something like this:

Simple spec an.png

You can also download this flowgraph if you want the reference file.

You should be all set!

Using Your Software Radio Spectrum Analyzer

Go ahead and run your flowgraph. You should see your received spectrum in real-time. Play with the sliders and values, and you should see everything update in real-time, as well. The default GNU Radio QT FFT sink has a number of useful features, such as averaging and peak-hold. Take some time to get familiar with them, now.

Building a Broadcast FM Receiver

Now that you have a basic receiver application running with a real-time display of your received data, let's build a useful application! Leave your current flowgraph in place. We will simply add more functionality into the flowgraph rather than replacing what is already there.

First, as you might have guessed, we will need to add a few more blocks to the flowgraph. Locate and add the following blocks:

  • 1x Rational Resampler
  • 1x WBFM Receiver
  • 1x Audio Sink
  • 2x Variable

Our flow of data will be the USRP Source -> Rational Resampler -> WBFM Receiver --> Audio Sink. Go ahead and connect the blocks together in that order. GNU Radio will likely highlight a lot of fields in red, indicating errors. We will now go through and configure the parameters, which will resolve these.

First, let's set-up those two new variable blocks you added. Create the following two variables with them:

Variable:

  • ID: audio_interp
  • Value: 4

Variable:

  • ID: audio_rate
  • Value: 48e3

Let's also go back and tune our sample rate variable, which we had previously. Change that variable to 250e3 (250 kHz).

Variable: samp_rate

  • ID: samp_rate
  • Value: 250e3

Now, let's configure your other three new blocks.

Audio Sink
This block is fairly straight-forward. It takes a stream of samples and plays them through your speakers. This block is installed with the gr-audio library, which is part of the core GNU Radio distribution. There are a few common / default rates that sound cards use - one of the most common is 48 kHz, which is what we will use, here (hence your configuration of the 'audio_rate' variable, above).

Open up the parameters of the Audio Sink. Make the following changes:

  • Sample Rate: audio_rate
  • OK to Block: "No"

Now, we just need to turn the samples from your hardware into something that you can play through your speakers! Let's go two blocks back up the chain, next.

Rational Resampler
The USRP Source is streaming at a rate of 'samp_rate', which we just set to 250e3. The Audio Sink is configured for a sample (consumption) rate of 'audio rate', which is 48e3. But, we have a problem: our source sample rate isn't an integer multiple of the audio rate: 250000 / 48000 = 5.208. To fix this problem, we will 'resample' the stream. Think of resampling here as impedance-matching. We have to convert from the rate of the input stream to the rate of the output stream.

The rational resampler block allows you to adjust the rate of a data stream. It does this by interpolating or decimating to achieve a desired sample rate. Open up the properties of this block, and let's tune the parameters.

Set the 'Type' to 'Complex->Complex', thus telling the block to use complex taps. Now we need to tune the actual rates. There is some intelligence built into this block - if we give it the different non-divisable sample rates, the code will calculate the GCD and make it all 'just work' for us. We know the incoming rate is 250 kSps, so let's enter that into 'Decimation'. But, this parameter must be an integer, and our 'samp_rate' is a float. Thus, we need to use the Python function 'int()' to convert it.

Now we need to set the 'Interpolation' rate. There is a 'gotcha' here, because the WBFM block further down our chain will actually perform an additional decimation-by-four, so we need to actually tell this block to output a rate four times what we want. We know what we actually want is 'audio_rate', so use your 'audio_interp' variable to set the actual rate.

At this point, you should have made these settings:

  • Type: Complex->Complex (Complex Taps)
  • Interpolation: audio_rate * audio_interp
  • Decimation: int(samp_rate)

By leaving the 'Taps' parameter blank, we tell the block that we want it to compute the taps automatically. The 'Fractional BW' parameter affects the shape of the low-pass filter that is generated when no filter taps are supplied. By leaving this set to zero, we will just use a reasonable default.

Note: Depending on the accuracy of the clock references in your hardware, you may need to tune the Interpolation field, above. This is one of the many hardware impairments that you may need to deal with. When I first ran this flowgraph, I heard a lot of noise. I then tuned that Interpolation rate, and it cleaned up. My final numbers were:

  • Interpolation: int(1.05 * (audio_rate * audio_interp))
  • Decimation: int(samp_rate)

Now, let's configure our last block!

WBFM Receiver
At this point, configuring our last block is pretty simple. Open up the block's parameters. There are only two parameters to set: the rate of incoming samples, and the decimation rate. Well, we know both of these. We just configured the output rate of the rational resampler, and we know that rate divided-by-four equals our 'audio_rate'. Thus, you want:

  • Quadrature Rate: audio_rate * audo_interp
  • Audio Decimation: audio_interp

A Working Software Radio Broadcast FM Receiver

And that should be it! You should now no longer see any red in your flowgraph, and you should be able to build your flowgraph without errors. The final result should look like this:

Broadcast fm rx flowgraph.png

You can also download this flowgraph, for reference.

Executing your flowgraph should bring up a GUI that looks something like what you see below. Changing the frequency and tuning to a local broadcast FM station should play the demodulated radio through your computer speakers.

Broadcast fm running.png