voltage pulse from USRP when using simple GNU Radi

2019-07-17 07:30发布

问题:

This is a follow-up to my earlier question: FFT in non-flowgraph centered application different from flowgraph centered apps like uhd_fft

In an attempt to better clarify the issue, I've boiled my code down to about ~30 LOC and have removed as much processing out of the flowgraph as possible.

The issue that I'm having is that, although the USRP is tuned to a frequency only once, each run of the flowgraph has about 70 ms of junk data. I'm fully aware that a certain amount of "junk" samples are to be expected when I first stream samples after a retune, but that's not what we're seeing here. We're seeing a significant amount of junk samples (~50,000) for each run of an existing, connected flowgraph.

Running the flowgraph and then handing data in Python is somewhat uncommon, but is introduced in the tutorial as a valid way to interact with GNU Radio here

I'd like to understand what part of the GNU Radio flowgraph logic creates this "hiccup" of voltage each time I call run() on it, whereas having it stream constantly (calling run only once, like uhd_fft) does not display the same behavior.

...produced with this code:

import numpy as np
from gnuradio import gr, uhd, blocks
import matplotlib.pyplot as plt

class topblock(gr.top_block):
    def __init__(self, freq=700e6, rate=1e6, nsamps=100000):
        gr.top_block.__init__(self)
        self.u = uhd.usrp_source(device_addr="", stream_args=uhd.stream_args('fc32'))
        self.u.set_center_freq(freq)
        self.u.set_samp_rate(rate)
        self.head = blocks.head(gr.sizeof_gr_complex, int(nsamps))
        self.vsink = blocks.vector_sink_c()
        self.connect(self.u, self.head, self.vsink)

tb = topblock()
fig, (freqplot, timeplot) = plt.subplots(2, sharex=True)
freqplot.set_title("Frequency domain")
timeplot.set_title("Time domain")

def plot():
    tb.run()
    data = np.array(tb.vsink.data())
    shifted_fft = np.fft.fftshift(np.fft.fft(data))
    dBm = 20*np.log10(np.abs(shifted_fft)) - 30
    freqplot.plot(dBm)
    timeplot.plot(np.abs(data))
    tb.head.reset()
    tb.vsink.reset()

def run_tb(times=10):
    for _ in range(times):
        plot()
    plt.show(block=False)

回答1:

The behavior above is caused by the auto_dc_offset feature of the USRP. The hardware has an inherent DC bias for both I and Q. gr-uhd provides the function set_auto_dc_offset, which is on by default and enables some kind of averaging function to bring I and Q offset to 0. Here you can see I/Q plotted with auto DC correction off: And on:

Notice that it takes almost 50,000 samples to zero out the DC offset.

The fact that UHD "forgets" its DC correction setting each time the flowgraph exits means that we have to deal with this pulse and the ensuing slow correction each time, even if the frequency didn't change between runs. This creates a pretty big penalty for running the flowgraph from an external loop.