Forum: GNU Radio Software Decimation - problem estimating frequency

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.
E. Ornelas (Guest)
on 2009-03-31 18:55
(Received via mailing list)
Hello!

I'm doing a project where i need to tune a signal around 10.7Mhz, and
then
start making a capture to a file.
So I need to the a tuner which searches for the correct center
frequency, so
that I can narrow the sampling band as much as possible.

The idea I'm trying to implement is a two step search.
On the first I use a 250khz band using only USRP decimation, and a 4096
points fft. This way the center frequency has an accuracy of about
120hz.
On the second step I narrow the band to 25kHz, decimating 10 times the
signal
from the usrp using software decimation. It's implemented using
gr.keep_one_in_n(type,10). Keeping the same FFT size there should be an
error of about 12hz.

Now the problem is this: the estimation from the first step is closer to
the
real value, read on a spectrum analyzer, than the one in the second.
Since I have the same number of points for the FFT, shouldn't the
resolution
per bin be 10 times better because the bandwidth is 10 times narrower?
Do I need to change the way I'm decimating the signal? (Not using
keep_one_in_n ...)
Why am I getting poorer results?

This is the 2-step tuner I have for now:

#//////////////////////////////////////////////////////////
# Set initial values so start signal search with the tunner
#//////////////////////////////////////////////////////////

  cf = 10.701200e6    # center frequency
  fs = 250.0e3  # sampling frequency
  fsize = 4096  # number of point on the FFT

  print
  print "Initilizing Tunner.."
  tb = tunner(cf, fs, fsize)
  print "1st Search.."
  tb.start()

  # Waiting period, to avoid initial flunctuations
  time.sleep(5)

  # Get 500 samples to make the first estimation
  while(len(tb.v_sink.out_freq()) < 30):
    pass
  tb.stop()
  tb.wait()
  print "Search done!"

  # Make evaluation
  # @ get magnitude vector
  # @ get frequency vector
  print "Evaluating.."

  mg = scipy.array(tb.v_sink2.out_mag())
  fq = scipy.array(tb.v_sink.out_freq())

  print "MAG:", mg
  print "FREQ:", fq

  if mg.mean() > -10:
    cf = fq.mean()
    print "Center Frequency = ", cf
    print
  elif mg.mean() <= -10:
    print "Not enough power!!"
    print


#//////////////////////////////////////////////////////
# Set values to fine tunne the frequency before capture
#//////////////////////////////////////////////////////
  tb = None

  cf = 10.701200e6
  fs = 25.0e3
  fsize = 4096

  print
  print "Initilizing Tunner.."
  tb = tunner(cf, fs, fsize)
  print "2nd Search.."
  tb.start()

  # Waiting period, to avoid initial flunctuations
  time.sleep(5)

  # Get 30 samples to make the first estimation
  while(len(tb.v_sink.out_freq()) < 30):
    pass
  tb.stop()
  tb.wait()
  print "Search done!"

  # Make evaluation
  # @ get magnitude vector
  # @ get frequency vector
  print "Evaluating.."

  mg = scipy.array(tb.v_sink2.out_mag())
  fq = scipy.array(tb.v_sink.out_freq())

  print "MAG:", mg
  print "FREQ:", fq

  if mg.mean() > -10:
    cf = fq.mean()
    print "Center Frequency = ", cf
    print
  elif mg.mean() <= -10:
    print "Not enough power!!"


And this is the part of the __init__ that concerns the decimation:
(buffer_sink is a block made by me that implement a circular buffer to
store
values)

class tunner(gr.top_block):
  def __init__(self, center_frequency, sampling_frequency, fft_size):
    gr.top_block.__init__(self)

    (....)

    full_decim = int(64e6/sampling_frequency)

    print "FULL DECIM = ", full_decim

    if full_decim > 256:
      decim = 256
      sw_decim = gr.keep_one_in_n(gr.sizeof_gr_complex,
int(250e3/sampling_frequency))
      print "SW = ", int(250e3/sampling_frequency)
    elif full_decim <= 256:
      decim = full_decim
      sw_decim = gr.keep_one_in_n(gr.sizeof_gr_complex, 1)
      print "SW = 0"

                (....)

                self.connect(self.u, sw_decim, ss2v, fft, c2m, (imax,0),
s2f1, self.buffer_sink)
    self.connect((imax,1), s2f2, p1)
--
View this message in context:
http://www.nabble.com/Software-Decimation---proble...
Sent from the GnuRadio mailing list archive at Nabble.com.
Kieran B. (Guest)
on 2009-04-01 00:42
(Received via mailing list)
I don't actually know but I would assume keep_one_in_n is not actually
doing
any Anti Aliasing for you, that may explain why you are getting a worse
result.

I recently implemented a system for doing what you are describing and it
may
be easier for you to just increase the size of your FFT. My system uses
a
12800 bin FFT at 1.28M Complex S/s (giving 100Hz bins) and only uses
~20%
CPU on an old P4 machine.

Kieran
E. Ornelas (Guest)
on 2009-04-01 01:49
(Received via mailing list)
Hello again!

Thanks for the advice. But the problem is that during the file capture I
was
asked to have a resolution of about 1hz or 2hz on a bandwidth of about
200hz. I would like to have at that point enough decimation to sample at
about 500hz. So I think I'll need the decimation working correctly in
the
final program.
Won't this effect I'm seeing apear too?

Right now I can have an accurate estimation until the hundreds. I was
hoping
to get the tens and units correct as well or with an error of 1hz or
2hz.
It's very important to have this resolution given the fact that the
power is
mostly in a 100hz width. With decimation I have an error of about 60hz
and
it was supposed to be around 6hz to 12hz.

Sorry if I'm repeating my self over and over. But it's very important to
solve this problem to advance in my thesis project.

Thanks in advance.

Emanuel Ornelas



E. Ornelas wrote:
> points fft. This way the center frequency has an accuracy of about 120hz.
> narrower?
>   cf = 10.701200e6    # center frequency
>   time.sleep(5)
>   # @ get frequency vector
>     print "Center Frequency = ", cf
>
>   # Waiting period, to avoid initial flunctuations
>   # @ get magnitude vector
>     cf = fq.mean()
> class tunner(gr.top_block):
>       decim = 256
>                 self.connect(self.u, sw_decim, ss2v, fft, c2m, (imax,0),
> s2f1, self.buffer_sink)
>     self.connect((imax,1), s2f2, p1)
>

--
View this message in context:
http://www.nabble.com/Software-Decimation---proble...
Sent from the GnuRadio mailing list archive at Nabble.com.
Kieran B. (Guest)
on 2009-04-01 03:46
(Received via mailing list)
My advice would be to go read up on downsampling (especially
anti-aliasing
filters). :)

The short answer is you need to low pass filter the incoming signal so
when
you perform the down sampling you do not get aliasing of the signal.

Kieran
Eric B. (Guest)
on 2009-04-01 07:37
(Received via mailing list)
On Wed, Apr 01, 2009 at 12:45:45PM +1300, Kieran B. wrote:
> My advice would be to go read up on downsampling (especially anti-aliasing
> filters). :)
>
> The short answer is you need to low pass filter the incoming signal so when
> you perform the down sampling you do not get aliasing of the signal.

Yes.  Consider using

  gr.fir_filter_ccf(decim, taps)

to decimate.  The low pass filter taps can be generated using
gr.firdes.low_pass.

Eric
This topic is locked and can not be replied to.