Cannot receive after one run of the code?


#1

Dear All,

I am writing because I am really in need for some advice. I wrote a
program that

(1) receives from the sender and estimates the channel
(2) switch to the transmitting mode and sends the channel estimation
back to the sender
(3) switch back to the receiving mode to receive data

A while ago, I asked about how to switch between these modes without
having to stop the flow graph, and Eric gave me excellent advice on
looking at tunnel.py. Recently, after did some optimizations, I found
that the code is having a weird problem, and I have struggled on it
about a week on it but still don’t know what to do.

Basically, after power-on the USRP, the code runs perfectly once. But
most often, it runs well exactly once – the next time I run it, the
receiver at step 1 cannot receive any signal. To run it again, I have
to unplug the USRP.

Here, by not receiving any signal, I mean that the signals read from
USRP have an average square value of around 0.8. When things are
working fine, the value is around 200 when the sender is not sending,
and is around 1000000 when the sender is sending.

At first I thought it was because I did not set mux right. But it does
not seem to be so. I also noticed that after I screw it up, I cannot
even run the benchmark_rx.py, because it will also not receive
anything. But I can run usrp_oscope.py and I can see the waveform when
I have a transmitter sending.

I really appreciate if someone could give me a hint on this. Thanks so
much!

Best regards,
Zhenghao


I have simplified my code and I am posting it here. This code has
exactly the same problem as I described. If other information is
needed, please let me know. Thanks!

from gnuradio import gr, gru, modulation_utils
from gnuradio.blksimpl import psk
import cmath
import Numeric
from pprint import pprint
from gnuradio import usrp
from pick_bitrate import pick_rx_bitrate
import time
import sys
from array import array
from pick_bitrate import pick_tx_bitrate

default values (used in init and add_options)

_def_samples_per_symbol = 2
_def_excess_bw = 0.35
_def_gray_code = True
_def_verbose = True
_def_log = True

_def_costas_alpha = 0.05 # the original setting

_def_gain_mu = 0.03
_def_mu = 0.05
_def_omega_relative_limit = 0.005

_def_rv_tx_freq = 2470000000
_def_rv_rx_freq = 2420000000

_def_found_delta_f = 0.025

_def_bitrate = 500000

_def_PI = 3.141592653
_def_rv_tx_power = 2000 #org: 12000

/////////////////////////////////////////////////////////////////////////////

DBPSK demodulator

Differentially coherent detection of differentially encoded BPSK

/////////////////////////////////////////////////////////////////////////////

class dbpsk_demod(gr.hier_block):

def __init__(self, fg,
             samples_per_symbol=_def_samples_per_symbol,
             excess_bw=_def_excess_bw,
             costas_alpha=_def_costas_alpha,
             gain_mu=_def_gain_mu,
             mu=_def_mu,
             omega_relative_limit=_def_omega_relative_limit,
             gray_code=_def_gray_code,
             verbose=_def_verbose,
             log=_def_log):
    """

Hierarchical block for RRC-filtered differential BPSK demodulation

The input is the complex modulated signal at baseband.
The output is a stream of bits packed 1 bit per byte (LSB)

@param fg: flow graph
@type fg: flow graph
@param samples_per_symbol: samples per symbol >= 2
@type samples_per_symbol: float
@param excess_bw: Root-raised cosine filter excess bandwidth
@type excess_bw: float
@param costas_alpha: loop filter gain
@type costas_alphas: float
@param gain_mu: for M&M block
@type gain_mu: float
@param mu: for M&M block
@type mu: float
@param omega_relative_limit: for M&M block
@type omega_relative_limit: float
@param gray_code: Tell modulator to Gray code the bits
@type gray_code: bool
@param verbose: Print information about modulator?
@type verbose: bool
@param debug: Print modualtion data to files?
@type debug: bool
“”"

    self._fg = fg
    self._samples_per_symbol = samples_per_symbol
    self._excess_bw = excess_bw
    self._costas_alpha = costas_alpha
    self._gain_mu = gain_mu
    self._mu = mu
    self._omega_relative_limit = omega_relative_limit
    self._gray_code = gray_code

    self._rx_freq            = _def_rv_rx_freq
    self._rx_gain            = 45           # receiver's gain
    self._rx_subdev_spec     = None
    self._bitrate            = _def_bitrate
    self._decim              = 64           # Decimating rate for

the USRP (prelim)
self._fusb_block_size = 0
self._fusb_nblocks = 0

    if self._rx_freq is None:
        sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ

must be specified\n")
raise SystemExit

    # Set up USRP source; also adjusts decim, samples_per_symbol,

and bitrate
self._setup_usrp_source()

    g = self.subdev.gain_range()
    if 1:
        print "Rx Gain Range: minimum = %g, maximum = %g, step size 

= %g"
% (g[0], g[1], g[2])

    self.set_gain(self._rx_gain)

    self.set_auto_tr(True)                 # enable Auto

Transmit/Receive switching

    # Set RF frequency
    ok = self.set_freq(self._rx_freq)
    if not ok:
        print "Failed to set Rx frequency to %s" %

(eng_notation.num_to_str(self._rx_freq))
raise ValueError, eng_notation.num_to_str(self._rx_freq)

    alpha = 0.001
    thresh = 30   # in dB, will have to adjust

    self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)

    # Design filter to get actual channel we want
    sw_decim = 1
    chan_coeffs = gr.firdes.low_pass (1.0,                  # gain
                                      sw_decim *

self._samples_per_symbol, # sampling rate
1.0, #
midpoint of trans. band
0.5, #
width of trans. band
gr.firdes.WIN_HANN) # filter
type

    # Decimating channel filter
    # complex in and out, float taps
    self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs)
    #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs)


    if samples_per_symbol < 2:
        raise TypeError, "samples_per_symbol must be >= 2, is %r"

% (samples_per_symbol,)

    arity = pow(2,self.bits_per_symbol())

    # Automatic gain control
    scale = (1.0/16384.0)
    self.pre_scaler = gr.multiply_const_cc(scale)   # scale the

signal from full-range to ±1
#self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
self.agc = gr.feedforward_agc_cc(16, 1.0)

    ntaps = 11 * self._samples_per_symbol
    self.rrc_taps = gr.firdes.root_raised_cosine(
        1.0,                      # gain
        self._samples_per_symbol, # sampling rate
        1.0,                      # symbol rate
        self._excess_bw,          # excess bandwidth (roll-off 

factor)
ntaps)

    self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)


    # find closest constellation point
    rot = 1

#rot = .707 + .707j
#print “psk.constellation[arity]=”, psk.constellation[arity] #chen
rotated_const = map(lambda pt: pt * rot,
psk.constellation[arity])
print “rotated_const =”, rotated_const

   # symbol clock recovery

omega = self._samples_per_symbol
gain_omega = .25 * self._gain_mu * self._gain_mu
#if not self._mm_gain_mu:
# self._mm_gain_mu = 0.1

    #self._mm_omega = self._samples_per_symbol
    #self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu
    self._costas_beta  = 0.25 * self._costas_alpha * 

self._costas_alpha
#fmin = -0.025
#fmax = 0.025
fmin = -0.1
fmax = 0.1

    self.receiver=gr.mpsk_receiver_cc(arity, 0,
                                     self._costas_alpha, 

self._costas_beta,
fmin, fmax,
self._mu, self._gain_mu,
omega, gain_omega,
self._omega_relative_limit)

    self.diffdec = gr.diff_phasor_cc()
    #self.diffdec = gr.diff_decoder_bb(arity)

    self.slicer = gr.constellation_decoder_cb(rotated_const, 

range(arity))

    if self._gray_code:
        self.symbol_mapper = gr.map_bb(psk.gray_to_binary[2])
    else:
        self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[2])

    # unpack the k bit vector into a stream of bits
    self.unpack = gr.unpacked_to_packed_bb(self.bits_per_symbol(),

gr.GR_MSB_FIRST)

    self.file_sink_1 = gr.file_sink(gr.sizeof_gr_complex, 

“DBPSKDemod.dat”)

    # Connect and Initialize base class

#self._fg.connect(self.u, self.pre_scaler, self.agc, self.chan_filt,
self.rrc_filter, self.receiver, self.file_sink_1)
self._fg.connect(self.u, self.pre_scaler, self.chan_filt,
self.rrc_filter, self.receiver, self.file_sink_1)

self.dst = gr.vector_sink_b()

    self._fg.connect(self.u, self.probe)

    gr.hier_block.__init__(self, self._fg, self.u, self.file_sink_1)

def samples_per_symbol(self):
    return self._samples_per_symbol

def bits_per_symbol(self=None):   # staticmethod that's also

callable on an instance
return 1
bits_per_symbol = staticmethod(bits_per_symbol) # make it a
static method. RTFM

def _setup_usrp_source(self):
    self.u = usrp.source_c (fusb_block_size=self._fusb_block_size,
                            fusb_nblocks=self._fusb_nblocks)
    adc_rate = self.u.adc_rate()

    # derive values of bitrate, samples_per_symbol, and decim from

desired info
(self._bitrate, self._samples_per_symbol, self._decim) =
pick_rx_bitrate(self._bitrate, 1,
self._samples_per_symbol, self._decim,
adc_rate)

    self.u.set_decim_rate(self._decim)

    # determine the daughterboard subdevice we're using
    if self._rx_subdev_spec is None:
        self._rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
    self.subdev = usrp.selected_subdev(self.u, self._rx_subdev_spec)

mux_value = usrp.determine_rx_mux_value(self.u, self._rx_subdev_spec)
self.u.set_mux(mux_value)
#print “-------------- usrp source mux_value = %d
----------------” %mux_value

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 up converter.
    """
    r = self.u.tune(0, self.subdev, target_freq)
    if r:
        return True

    return False

def set_gain(self, gain):
    """
    Sets the analog gain in the USRP
    """
    if gain is None:
        r = self.subdev.gain_range()
        gain = (r[0] + r[1])/2               # set gain to midpoint
    self.gain = gain
    return self.subdev.set_gain(gain)

def set_auto_tr(self, enable):
    return self.subdev.set_auto_tr(enable)

def bitrate(self):
    return self._bitrate

def samples_per_symbol(self):
    return self._samples_per_symbol

def decim(self):
    return self._decim

def carrier_sensed(self):
    """
    Return True if we think carrier is present.
    """
    #return self.probe.level() > X
    return self.probe.unmuted()

def carrier_threshold(self):
    """
    Return current setting in dB.
    """
    return self.probe.threshold()

def set_carrier_threshold(self, threshold_in_db):
    """
    Set carrier threshold.

    @param threshold_in_db: set detection threshold
    @type threshold_in_db:  float (dB)
    """
    self.probe.set_threshold(threshold_in_db)

#//////////////////////////////////////////////////////////////////

#//////////////////////////////////////////////////////////////////

class dbpsk_mod(gr.hier_block):

def __init__(self, fg,
 samples_per_symbol=_def_samples_per_symbol,
             excess_bw=_def_excess_bw,
             gray_code=_def_gray_code,
             verbose=_def_verbose,
             log=_def_log):
    """

Hierarchical block for RRC-filtered differential BPSK modulation.

The input is a byte stream (unsigned char) and the
output is the complex modulated signal at baseband.

@param fg: flow graph
@type fg: flow graph
@param samples_per_symbol: samples per baud >= 2
@type samples_per_symbol: integer
@param excess_bw: Root-raised cosine filter excess bandwidth
@type excess_bw: float
@param gray_code: Tell modulator to Gray code the bits
@type gray_code: bool
@param verbose: Print information about modulator?
@type verbose: bool
@param log: Log modulation data to files?
@type log: bool
“”"
self._tx_freq = _def_rv_tx_freq
self._tx_amplitude = _def_rv_tx_power #original setting is
12000
self._fusb_block_size = 0
self._fusb_nblocks = 0
self._bitrate = _def_bitrate
self._tx_subdev_spec = None
self._fg = fg
self._samples_per_symbol = samples_per_symbol
self._excess_bw = excess_bw
self._gray_code = gray_code
self.phase_diff_est = 192

    # Set up USRP sink; also adjusts interp, samples_per_symbol, and 

bitrate
self._setup_usrp_sink()

    # Set center frequency of USRP
    ok = self.set_freq(self._tx_freq)
    if not ok:
        print "Failed to set Tx frequency to %s" %

(eng_notation.num_to_str(self._tx_freq),)
raise ValueError

    # Set the USRP for maximum transmit gain
    # (Note that on the RFX cards this is a nop.)
    self.set_gain(self.subdev.gain_range()[1])

    self.amp = gr.multiply_const_cc(1)
    self.set_tx_amplitude(self._tx_amplitude)

    # enable Auto Transmit/Receive switching
    self.set_auto_tr(True)



    if not isinstance(self._samples_per_symbol, int) or

self._samples_per_symbol < 2:
raise TypeError, (“sbp must be an integer >= 2, is %d” %
self._samples_per_symbol)

ntaps = 11 * self._samples_per_symbol

    arity = pow(2,self.bits_per_symbol())

    # turn bytes into k-bit vectors
    self.bytes2chunks = \
      gr.packed_to_unpacked_bb(self.bits_per_symbol(), 

gr.GR_MSB_FIRST)

    if self._gray_code:
        self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity])
    else:
        self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity])

    self.chunks2symbols = 

gr.chunks_to_symbols_bc(psk.constellation[2])

    self.rrc_taps = gr.firdes.root_raised_cosine(
        1.0,                      # gain
        self._samples_per_symbol, # sampling rate
        1.0,                      # symbol rate
        self._excess_bw,          # excess bandwidth (roll-off 

factor)
ntaps)

self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol,
self.rrc_taps)

self.bytes_src1 = gr.null_source(gr.sizeof_char)

self.diffenc = gr.diff_encoder_bb(arity)

    fg.connect(self.bytes_src1, self.bytes2chunks,

self.symbol_mapper, self.diffenc, self.chunks2symbols,
self.rrc_filter, self.amp, self.u)

gr.hier_block.init(self, self._fg, self.bytes_src1, self.u)

def samples_per_symbol(self):
    return self._samples_per_symbol

def bits_per_symbol(self=None):   # static method that's also

callable on an instance
return 1
bits_per_symbol = staticmethod(bits_per_symbol) # make it a
static method. RTFM

def _setup_usrp_sink(self):
    """
    Creates a USRP sink, determines the settings for best bitrate,
    and attaches to the transmitter's subdevice.
    """

self.u = usrp.sink_c(fusb_block_size=self._fusb_block_size,
fusb_nblocks=self._fusb_nblocks)
dac_rate = self.u.dac_rate();

    # derive values of bitrate, samples_per_symbol, and interp

from desired info
(self._bitrate, self._samples_per_symbol, self._interp) =
pick_tx_bitrate(self._bitrate, 1,
self._samples_per_symbol, None, dac_rate)

    self.u.set_interp_rate(self._interp)

    # determine the daughterboard subdevice we're using
    if self._tx_subdev_spec is None:
        self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u)

mux_value = usrp.determine_tx_mux_value(self.u, self._tx_subdev_spec)
self.u.set_mux(mux_value)

    self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec)


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 up converter.
    """
    r = self.u.tune(self.subdev._which, self.subdev, target_freq)
    if r:
        return True

    return False

def set_gain(self, gain):
    """
    Sets the analog gain in the USRP
    """
    self.gain = gain
    self.subdev.set_gain(gain)

def set_tx_amplitude(self, ampl):
    """
    Sets the transmit amplitude sent to the USRP
    @param: ampl 0 <= ampl < 32768.  Try 8000
    """
    self._tx_amplitude = max(0.0, min(ampl, 32767.0))
    self.amp.set_k(self._tx_amplitude)

def set_auto_tr(self, enable):
    """
    Turns on auto transmit/receive of USRP daughterboard (if

exits; else ignored)
“”"
return self.subdev.set_auto_tr(enable)

if name == ‘main’:

fg1 = gr.flow_graph()
objDemod1 = dbpsk_demod(fg1)
fg1.start() #objDemod1._fg.start()
count = 0
while count < 10:
    time.sleep(0.1) #orig: 0.001
    print "level %f" % objDemod1.probe.level()
    count = count + 1

fg1.stop()#objDemod1._fg.stop()

fg2 = gr.flow_graph()
objmod = dbpsk_mod(fg2)
objmod.set_tx_amplitude(_def_rv_tx_power)
fg2.start()
time.sleep(0.003)
objmod.set_tx_amplitude(0)
fg2.stop()