Forum: GNU Radio Wideband Spectrum Analyzer

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
36d6b4ceb15343f9e412cc17be319902?d=identicon&s=25 Santi Ortega (Guest)
on 2008-10-14 16:30
(Received via mailing list)
Hi!
I need help to modify the usrp_fft.py file to show the spectrum of a
input
range (for example from 2.3GHz to 2.9GHz)
C0ba64b9e5a62ed77295b79b63ab87c0?d=identicon&s=25 Dimitris Symeonidis (Guest)
on 2008-10-14 17:03
(Received via mailing list)
santi, such a wide frequency range is not possible due to limitations
in the bandwidth between the usrp and the host
currently you give usrp_fft a center frequency and a decimation rate,
and from that it calculates the start and end frequencies...

Dimitris Symeonidis
"If you think you're too small to make a difference, try sleeping with
a mosquito!" - Amnesty International
36d6b4ceb15343f9e412cc17be319902?d=identicon&s=25 Santi Ortega (Guest)
on 2008-10-14 17:08
(Received via mailing list)
Yes, but I think we can take the spectrum of every 8MHz band and put it
into
the computer so it can memorize and show it.

Sorry for my english...


2008/10/14 Dimitris Symeonidis <azimout@gmail.com>
3d593de8acbe2510722af740d8668352?d=identicon&s=25 Firas Abbas (Guest)
on 2008-10-14 17:50
(Received via mailing list)
Hi,


> Santi Ortega <santiortega2000@gmail.com> wrote:
>
> Yes, but I think we can take the spectrum of every 8MHz band and put it into the
> computer so it can memorize and show it.


See usrp_spectrum_sense.py, it implements this technique to scan the
entire spectrum available to each USRP daughter board.


Regards,

Firas
36d6b4ceb15343f9e412cc17be319902?d=identicon&s=25 Santi Ortega (Guest)
on 2008-10-14 17:53
(Received via mailing list)
ok, but this program doesn't show you anything... just uOuOuO...

2008/10/14 Firas Abbas <firasmail2000@yahoo.com>
79723aa1b24981dcec2dbf7fd59403c1?d=identicon&s=25 Brian Padalino (Guest)
on 2008-10-14 17:55
(Received via mailing list)
On Tue, Oct 14, 2008 at 11:33 AM, Santi Ortega
<santiortega2000@gmail.com> wrote:
> ok, but this program doesn't show you anything... just uOuOuO...

Please reference:

    http://gnuradio.org/trac/wiki/UsrpFAQ/Gen#OUuainoutput

Brian
36d6b4ceb15343f9e412cc17be319902?d=identicon&s=25 Santi Ortega (Guest)
on 2008-10-14 17:57
(Received via mailing list)
ok, so I have to modify this program to show in a Frame the results I
want,
haven't I?

2008/10/14 Brian Padalino <bpadalino@gmail.com>
3d593de8acbe2510722af740d8668352?d=identicon&s=25 Firas A. (Guest)
on 2008-10-14 18:29
(Received via mailing list)
Hi,

>  Santi Ortega wrote :
>
> ok, so I have to modify this program to show in a Frame the results I
> want, haven't I?

Yes, OR, you can wait for me to write a detailed explanation (may be in
two
weeks) about "usrp_spectrum_sense.py".

I think the understanding of this program is very important to every
gnuradio user (practical FFT implementation + FSM control in its cpp
code
and weird Python commands in its .py!!!!)

Best regards,

Firas



--
View this message in context:
http://www.nabble.com/Wideband-Spectrum-Analyzer-t...
Sent from the GnuRadio mailing list archive at Nabble.com.
36d6b4ceb15343f9e412cc17be319902?d=identicon&s=25 Santix (Guest)
on 2008-11-05 16:23
(Received via mailing list)
Hi everybody!

I have modified usrp_spectrum_sense.py to plot the results with gnuplot.
There are two files: widespectrum.py and plot.p
I would like everybody to test it and report me the errors and how can I
improve it.
I've used USRPv1 + Flex2400.

Thanks in advance!

Here it goes...

WIDESPECTRUM.PY:

#!/usr/bin/env python
#
# Copyright 2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#

from gnuradio import gr, gru, eng_notation, optfir, window
from gnuradio import audio
from gnuradio import usrp
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
import math
import struct
import Gnuplot, Gnuplot.funcutils # Added to view the results

class tune(gr.feval_dd):
    """
    This class allows C++ code to callback into python.
    """
    def __init__(self, tb):
        gr.feval_dd.__init__(self)
        self.tb = tb

    def eval(self, ignore):
        """
        This method is called from gr.bin_statistics_f when it wants to
change
        the center frequency.  This method tunes the front end to the
new
center
        frequency, and returns the new frequency as its result.
        """
        try:
            # We use this try block so that if something goes wrong from
here
            # down, at least we'll have a prayer of knowing what went
wrong.
            # Without this, you get a very mysterious:
            #
            #   terminate called after throwing an instance of
'Swig::DirectorMethodException'
            #   Aborted
            #
            # message on stderr.  Not exactly helpful ;)

            new_freq = self.tb.set_next_freq()
            return new_freq

        except Exception, e:
            print "tune: Exception: ", e


class parse_msg(object):
    def __init__(self, msg):
        self.center_freq = msg.arg1()
        self.vlen = int(msg.arg2())
        assert(msg.length() == self.vlen * gr.sizeof_float)

        # FIXME consider using Numarray or NumPy vector
        t = msg.to_string()
        self.raw_data = t
        self.data = struct.unpack('%df' % (self.vlen,), t)


class my_top_block(gr.top_block):

    def __init__(self):
        gr.top_block.__init__(self)

        usage = "usage: %prog [options] min_freq max_freq"
    # Example:  ./widespectrum.py 2.23G 2.93G
    # that is the maximun range of the USRP Flex2400 device.

    parser = OptionParser(option_class=eng_option, usage=usage)
        parser.add_option("-R", "--rx-subdev-spec", type="subdev",
default=(0,0),
                          help="select USRP Rx side A or B (default=A)")
        parser.add_option("-g", "--gain", type="eng_float",
default=None,
                          help="set gain in dB (default is midpoint)")
        parser.add_option("", "--tune-delay", type="eng_float",
default=1e-3, metavar="SECS",
                          help="time to delay (in seconds) after
changing
frequency [default=%default]")
        parser.add_option("", "--dwell-delay", type="eng_float",
default=10e-3, metavar="SECS",
                          help="time to dwell (in seconds) at a given
frequncy [default=%default]")
        parser.add_option("-F", "--fft-size", type="int", default=256,
                          help="specify number of FFT bins
[default=%default]")
        parser.add_option("-d", "--decim", type="intx", default=64,
                          help="set decimation to DECIM
[default=%default]")
        parser.add_option("", "--real-time", action="store_true",
default=False,
                          help="Attempt to enable real-time scheduling")
        parser.add_option("-B", "--fusb-block-size", type="int",
default=0,
                          help="specify fast usb block size
[default=%default]")
        parser.add_option("-N", "--fusb-nblocks", type="int", default=0,
                          help="specify number of fast usb blocks
[default=%default]")

        (options, args) = parser.parse_args()
        if len(args) != 2:
            parser.print_help()
            sys.exit(1)

        self.min_freq = eng_notation.str_to_num(args[0])
        self.max_freq = eng_notation.str_to_num(args[1])

        if self.min_freq > self.max_freq:
            self.min_freq, self.max_freq = self.max_freq, self.min_freq
#
swap them

    # FIXME We set MANUALLY the physical limits of the device. In this
case
the USRP Flex2400 limits.

    if self.min_freq < 2222000000:
        print ("The minimum frequency of this device is 2.222GHz")
        self.min_freq = 2222000000

    if self.max_freq <  2222000000:
        print ("The minimum frequency of this device is 2.222GHz")
        self.max_freq = 2222000000

    if self.min_freq > 2937000000:
        print ("The maximun frequency of this device is 2.937GHz")
        self.min_freq = 2937000000

    if self.max_freq > 2937000000:
        print ("The maximun frequency of this device is 2.937GHz")
        self.max_freq = 2937000000

    if self.min_freq == self.max_freq:
        print ("Do not use this program for a single frecuency analysis
please")
        exit()


    self.fft_size = options.fft_size


        if not options.real_time:
            realtime = False
        else:
            # Attempt to enable realtime scheduling
            r = gr.enable_realtime_scheduling()
            if r == gr.RT_OK:
                realtime = True
            else:
                realtime = False
                print "Note: failed to enable realtime scheduling"

        # If the user hasn't set the fusb_* parameters on the command
line,
        # pick some values that will reduce latency.

        if 1:
            if options.fusb_block_size == 0 and options.fusb_nblocks ==
0:
                if realtime:                        # be more aggressive
                    options.fusb_block_size =
gr.prefs().get_long('fusb',
'rt_block_size', 1024)
                    options.fusb_nblocks    =
gr.prefs().get_long('fusb',
'rt_nblocks', 16)
                else:
                    options.fusb_block_size =
gr.prefs().get_long('fusb',
'block_size', 4096)
                    options.fusb_nblocks    =
gr.prefs().get_long('fusb',
'nblocks', 16)

        #print "fusb_block_size =", options.fusb_block_size
    #print "fusb_nblocks    =", options.fusb_nblocks

        # build graph

        self.u = usrp.source_c(fusb_block_size=options.fusb_block_size,
                               fusb_nblocks=options.fusb_nblocks)


        adc_rate = self.u.adc_rate()                # 64 MS/s
        usrp_decim = options.decim
        self.u.set_decim_rate(usrp_decim)
        usrp_rate = adc_rate / usrp_decim

        self.u.set_mux(usrp.determine_rx_mux_value(self.u,
options.rx_subdev_spec))
        self.subdev = usrp.selected_subdev(self.u,
options.rx_subdev_spec)
        print "Using RX d'board %s" % (self.subdev.side_and_name(),)


    s2v = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size)

        mywindow = window.blackmanharris(self.fft_size)
        fft = gr.fft_vcc(self.fft_size, True, mywindow)
        power = 0
        for tap in mywindow:
            power += tap*tap

        c2mag = gr.complex_to_mag_squared(self.fft_size)

        # FIXME the log10 primitive is dog slow
        log = gr.nlog10_ff(10, self.fft_size,

-20*math.log10(self.fft_size)-10*math.log10(power/self.fft_size))

        # Set the freq_step to 75% of the actual data throughput.
        # This allows us to discard the bins on both ends of the
spectrum.



    self.freq_step = 0.75 * usrp_rate
        self.min_center_freq = self.min_freq + self.freq_step/2
        nsteps = math.ceil((self.max_freq - self.min_freq) /
self.freq_step)
        self.max_center_freq = self.min_center_freq + (nsteps *
self.freq_step)

        self.next_freq = self.min_center_freq

    # We define the minimum, maximum and frequency step in a global
statement to use them later.

    global min_center_freq, max_center_freq, freq_step
    min_center_freq = self.min_center_freq
    max_center_freq = self.max_center_freq
    freq_step = self.freq_step


        tune_delay  = max(0, int(round(options.tune_delay * usrp_rate /
self.fft_size)))  # in fft_frames
        dwell_delay = max(1, int(round(options.dwell_delay * usrp_rate /
self.fft_size))) # in fft_frames

        self.msgq = gr.msg_queue(16)
        self._tune_callback = tune(self)        # hang on to this to
keep it
from being GC'd
        stats = gr.bin_statistics_f(self.fft_size, self.msgq,
                                    self._tune_callback, tune_delay,
dwell_delay)

        # FIXME leave out the log10 until we speed it up
    self.connect(self.u, s2v, fft, c2mag, log, stats)
    #self.connect(self.u, s2v, fft, c2mag, stats)

        if options.gain is None:
            # if no gain was specified, use the mid-point in dB
            g = self.subdev.gain_range()
            options.gain = float(g[0]+g[1])/2

        self.set_gain(options.gain)
    print "gain =", options.gain


    def set_next_freq(self):
        target_freq = self.next_freq
        self.next_freq = self.next_freq + self.freq_step
        if self.next_freq >= self.max_center_freq:
            self.next_freq = self.min_center_freq

        if not self.set_freq(target_freq):
            print "Failed to set frequency to", target_freq

        return target_freq


    def set_freq(self, target_freq):
        """
        Set the center frequency we're interested in.

        @param target_freq: frequency in Hz
        @rypte: bool

        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital down converter.
        """
        return self.u.tune(0, self.subdev, target_freq)


    def set_gain(self, gain):
        self.subdev.set_gain(gain)

def mean(data):                # Returns the arithmetic mean of a
numeric
list
   return sum(data) / len(data)


def main_loop(tb):

    # We give basic information about the Spectrum Analysis

    print "The start frequency is %s Hz" % min_center_freq
    print "The final frequency is %s Hz" % max_center_freq
    print "The frequency step is %s Hz" % freq_step
    g = Gnuplot.Gnuplot(debug=1)

    while 1:

        # Get the next message sent from the C++ code (blocking call).
        # It contains the center frequency and the mag squared of the
fft
        m = parse_msg(tb.msgq.delete_head())

        # Print center freq so we know that something is happening...
        #print (m.center_freq)

    # FIXME do something useful with the data...


    # Mechanism to save in a file (power.dat) 2 columns, one for the
frequencies and the other for the mean of the FFT_SIZE points of m.data

    if m.center_freq == min_center_freq:    # If we get the minimum
frequency, it'll reset the power.dat file
        power=open("power.dat", "w")    # It will overwrite the
power.dat
file

    power=open("power.dat", "a")        # Each loop, it adds a dataline
(append)
    p=str(m.center_freq)            # with a frequency and the mean of
the
256 FFT samples (Power in dB)
    media=str(mean(m.data))            #
    todo= p + "    " + media + '\n'        #
    power.write(todo)            #


    if m.center_freq == (max_center_freq-freq_step):    # If it gets the
final frecuency

        p=str(m.center_freq)                # It'll write the last
frecuency
with its Power in the power.dat file
        media=str(mean(m.data))                #
        todo= p + "    " + media + '\n'            #
        power.write(todo)                #
        g.load("plot.p")                # Load the plot with the data
obtained from URSP
        power=open("power.dat", "a")            # Without this line, the
file will start with the last frecuency
        #g.hardcopy('spectrum.ps', enhanced=1, color=1)        # It does
a
plot copy to the hard disk (I think there's not enough time to do it)


    # m.data in 'w' mode: only write, if it exist a file with the same
name,
it'll be overwrite.
    #           'a' to append
    #        'r+' for read and write

        # m.data are the mag_squared of the fft output (they are in the
        # standard order.  I.e., bin 0 == DC.)
        # You'll probably want to do the equivalent of "fftshift" on
them

    # m.raw_data is a string that contains the binary floats.
        # You could write this as binary to a file.


if __name__ == '__main__':
    tb = my_top_block()
    try:
        tb.start()              # start executing flow graph in another
thread...
        main_loop(tb)

    except KeyboardInterrupt:
        pass


PLOT.P

set autoscale
unset logscale
unset label
set xtic auto
set ytic auto
set title "Wideband Spectrum Analyzer"
set xlabel "Frecuency"
set ylabel "Power (dB)"
set grid
plot "power.dat" using 1:2 title 'Mean power' with linespoints
--
View this message in context:
http://www.nabble.com/Wideband-Spectrum-Analyzer-t...
Sent from the GnuRadio mailing list archive at Nabble.com.
C153c581b7bf93de497347ba0daed290?d=identicon&s=25 shesh (Guest)
on 2009-06-23 11:24
(Received via mailing list)
Firas,
have to written a detailed explanation  about "usrp_spectrum_sense.py" ?
I
am unable to find it. Please let us know the link for the same...

Shesh


Firas A. wrote:
>
>
--
View this message in context:
http://www.nabble.com/Wideband-Spectrum-Analyzer-t...
Sent from the GnuRadio mailing list archive at Nabble.com.
229fe98f1304ec4c4468f3b7075d6cc9?d=identicon&s=25 Dan Rosenqvist (Guest)
on 2009-06-23 13:36
(Received via mailing list)
shesh wrote:
>
> Firas,
> have to written a detailed explanation  about "usrp_spectrum_sense.py" ? I
> am unable to find it. Please let us know the link for the same...
>
> Shesh
>
>

http://www.nabble.com/Some-usrp_spectrum_sense.py-...
--
View this message in context:
http://www.nabble.com/Wideband-Spectrum-Analyzer-t...
Sent from the GnuRadio mailing list archive at Nabble.com.
1bb274b4412651d27e1756a626852258?d=identicon&s=25 unknown (Guest)
on 2010-01-13 00:58
(Received via mailing list)
Hello

I wonder someone can help me out. While testing this code, the media
with the different size of fft shows different value. I would like to
know how I can get the same media value regardless of using different
fft size.

Thanks,

Kyungtae-- Santix wrote :

    media=str(mean(m.data))            #
    todo= p + "    " + media + '\n'        #
    power.write(todo)            #


--
This message was sent on behalf of kyungtae@nec-labs.com at
openSubscriber.com
http://www.opensubscriber.com/message/discuss-gnur...
4252201ac30d6dd44d8090ce1070e35f?d=identicon&s=25 Josh Blum (Guest)
on 2010-01-13 01:05
(Received via mailing list)
See how the logpwrfft in gnuradio adjusts for different windows and fft
lengths:
http://gnuradio.org/redmine/repositories/entry/gnu...

-Josh
This topic is locked and can not be replied to.