discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Discuss-gnuradio] Cannot receive after one run of the code?


From: Zenny Zhang
Subject: [Discuss-gnuradio] Cannot receive after one run of the code?
Date: Mon, 20 Oct 2008 19:24:32 -0400

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()




reply via email to

[Prev in Thread] Current Thread [Next in Thread]