Software Decimation - problem estimating frequency

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---problem-estimating-frequency-tp22804977p22804977.html
Sent from the GnuRadio mailing list archive at Nabble.com.

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

My advice would be to go read up on downsampling (especially
anti-aliasing
filters). :slight_smile:

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

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). :slight_smile:

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

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---problem-estimating-frequency-tp22804977p22815529.html
Sent from the GnuRadio mailing list archive at Nabble.com.