The Python power at your disposal in GNU Radio Companion is great, and you can create neat scripts that automatizes measurement tasks – by wrapping the auto-generated scripts, or by doing the necessary adjustments to get access to convenient features like command line arguments directly in the auto-generated file.
Creating first a simple flowgraph in GNU Radio Companion which just outputs IQ samples to file, as a generic example:
GNU Radio Companion then autogenerates the Python script
iq_to_file.py with the flowgraph implemented in the class
Any defined variables will have convenient access functions defined:
In https://www.la1k.no/2018/09/05/overflow-rectification-for-recorded-gnu-radio-samples/, we recorded different IQ files at various frequencies and sample rates. This was rather tiresome to do manually, so my approach here was to modify the generated Python file to take input arguments that set the frequency and samplerate, systematically loop through the various parameter choices, define a convenient output filename, and set it up to measure for a pre-defined amount of time. However, editing something that is autogenerated is not necessarily a very good approach – what if you want to autogenerate it again?
Luckily, you don’t actually have to edit the generated file. The autogenerated Python file is implemented in such a way that it can safely be imported by a different Python file due to the
if __name__ == '__main__' clause.
It is then pretty convenient to just import the autogenerated module:
And dependent on the desired outcome, either just do whatever else is necessary to do before calling the flowgraph and call the wrapped main()-function directly,
or create a flowgraph explicitly in order to manipulate its variables and then kick it off:
#create and start flowgraph flowgraph = iq_to_file.iq_to_file() flowgraph.set_filename(output_filename) flowgraph.start() #collect data for 10 seconds time.sleep(10) flowgraph.stop() flowgraph.wait()
This blog post was originally going to be about this wrapping business, and the fact that you then can take in and parse command line arguments in the wrapper script and pass them on to the GRC-generated Python module. It turns out, however, that GNU Radio Companion already has support for CLI argument parsing out of the box! No need for wrapping in this case.
Taking all variables
and changing them to parameters
then makes GNU Radio Companion automatically add argument parsing to the auto-generated Python script, which is pretty neat.
We could then have output samples to a named file by running e.g.
python iq_to_file.py --filename very_nice_samples.iq.
This might be enough for most purposes. Even if it has to be called from an other script due to additional manipulations to the arguments, arguments can be passed through the
options flag. We then don’t even have to re-create the flowgraph from the wrapper script. Minimizing code duplication is always a nice thing.
One use case is the measurement of antenna patterns. During our long antenna pattern measurement journey two years ago [1, 2, 3, 4, 5, 6, 7], we had this rather bulky setup of having to kick off a generic GNU Radio flowgraph to collect samples, then another Python script to collect (az, el) from rotctld. Both output to rather generic filenames which we (alright, which I horribly and with great effort) manually moved to manually named folders. Kicking off angle collection and GNU Radio IQ sample collection automatically, at the same time, would be much more convenient. Generating the same base filename for both would exceed all hopes and dreams we have in this dark world.
We therefore wrote a small collection of Python scripts that does just this: kicking off GNU Radio sampling, and simultaneously logging antenna angles to filenames with the same prefixes. Arguments are parsed, rotctld angle collection is started, GNU Radio IQ sampling is started, and everything writes to appropriately and conveniently named files. The argument object generated by
argparse is passed on to the GNU Radio flowgraph directly.
By running the script as
python measurement.py --center-freq=144400000 --samp-rate=500000 --record-angles=la1k-rotors.local:4535 2m_arr
and turning the rotor, we get some data in nicely named files:
2m_arr_freq_144400000.0_rate_500000.0_2020-02-24T1305_antenna_angles.dat 2m_arr_freq_144400000.0_rate_500000.0_2020-02-24T1305.iq 2m_arr_freq_144400000.0_rate_500000.0_2020-02-24T1305.iq.hdr
Utilizing the clusterfuck of antenna pattern extraction code outlined in our previous antenna pattern blog posts linked above, we could extract a nice antenna pattern by measuring the CW signal from LA2VHF.
This wraps up the script wrapping for today. The reason for the resurgence of antenna pattern measurements we did two years ago is that we’ve been wanting to exploit signals from geostationary satellites to automatically find the offset of our parabolic dish. First for calibration and to check if we can get any nice unexpected results by calibrating against multiple sources, but also to automatize the debugging of an interesting issue we might have found in one of our rotors (or not, not sure until we’ve systematically investigated it). Stay tuned! The code is available on GitHub.