Hi, Still struggling with the configuration – 2x N200 r4, master O/B GPSDO, slave MIMO cable. Have put in python code to use timed commands and that produced a constant phase offset even over rerun of FG or power cycling on N200 which was great news.
However, the relative offset changes with frequency. The splitter is a Mini-circuits ZRFSC-123S+ which is spec-ed to has a typical of phase unbalance of 1/2 a degree over the frequency ranges used. The results are independent of source NWT 4000-1 or an SBX using uhd_siggen. When I have checked the ref_locked flags etc. they are good. the gpsdo is ‘locked’ as is MIMO. In addition to using the timed_commands to synch the SBX LOs, I also implement the integer-N-tuning and no improvement. The results are roughly Freq (MHz) Phase offset (deg) 450 -7 1450 -30 1950 -65 2450 -100 When I switch the cables between the 2 N200, the phase offset doesn’t change sign so I presume it is not cabling? What on earth, else, could it be? Kind Regards, John --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
#!/usr/bin/env python2 # -*- coding: utf-8 -*- ################################################## # GNU Radio Python Flow Graph # Title: Top Block # Generated: Mon Oct 16 05:41:38 2017 ################################################## if __name__ == '__main__': import ctypes import sys if sys.platform.startswith('linux'): try: x11 = ctypes.cdll.LoadLibrary('libX11.so') x11.XInitThreads() except: print "Warning: failed to XInitThreads()" from PyQt4 import Qt from gnuradio import blocks from gnuradio import eng_notation from gnuradio import filter from gnuradio import gr from gnuradio import qtgui from gnuradio import uhd from gnuradio.eng_option import eng_option from gnuradio.filter import firdes from gnuradio.qtgui import Range, RangeWidget from optparse import OptionParser import cmath import math import sip import sys import time import tune_helper # embedded python module from gnuradio import qtgui class top_block(gr.top_block, Qt.QWidget): def __init__(self, flt_dec=1000): gr.top_block.__init__(self, "Top Block") Qt.QWidget.__init__(self) self.setWindowTitle("Top Block") qtgui.util.check_set_qss() try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "top_block") self.restoreGeometry(self.settings.value("geometry").toByteArray()) ################################################## # Parameters ################################################## self.flt_dec = flt_dec ################################################## # Variables ################################################## self.shift_in_radians = shift_in_radians = 0 self.samp_rate = samp_rate = 1e6 self.gain = gain = 10 self.freq = freq = 450e6 ################################################## # Blocks ################################################## self._shift_in_radians_range = Range(0, 7, 0.001, 0, 200) self._shift_in_radians_win = RangeWidget(self._shift_in_radians_range, self.set_shift_in_radians, 'Shift', "counter_slider", float) self.top_layout.addWidget(self._shift_in_radians_win) self._gain_range = Range(0, 30, 1, 10, 200) self._gain_win = RangeWidget(self._gain_range, self.set_gain, 'Gain', "counter_slider", float) self.top_layout.addWidget(self._gain_win) self._freq_range = Range(400e6, 4e9, 100e3, 450e6, 200) self._freq_win = RangeWidget(self._freq_range, self.set_freq, 'Freq', "counter_slider", float) self.top_layout.addWidget(self._freq_win) self.uhd_usrp_source_0_0 = uhd.usrp_source( ",".join(("", "addr0=192.168.20.2,addr1=192.168.10.2")), uhd.stream_args( cpu_format="fc32", channels=range(2), ), ) self.uhd_usrp_source_0_0.set_clock_source('gpsdo', 0) self.uhd_usrp_source_0_0.set_time_source('gpsdo', 0) self.uhd_usrp_source_0_0.set_subdev_spec("A:0", 0) self.uhd_usrp_source_0_0.set_clock_source('mimo', 1) self.uhd_usrp_source_0_0.set_time_source('mimo', 1) self.uhd_usrp_source_0_0.set_subdev_spec("A:0", 1) self.uhd_usrp_source_0_0.set_samp_rate(samp_rate) ##JSself.uhd_usrp_source_0_0.set_center_freq(freq, 0) self.uhd_usrp_source_0_0.set_gain(gain, 0) self.uhd_usrp_source_0_0.set_antenna('TX/RX', 0) #JSself.uhd_usrp_source_0_0.set_center_freq(freq, 1) self.uhd_usrp_source_0_0.set_gain(gain, 1) self.uhd_usrp_source_0_0.set_antenna('TX/RX', 1) # inserted code to synch LO and, by way of the mechanism, align the CORDICs self.tune_time=self.uhd_usrp_source_0_0.get_time_now(0)+uhd.time_spec_t(0.2) # tune in 200 msecs from 'now' #self.tune_time=self.uhd_usrp_source_m.get_time_now(0)+uhd.time_spec_t(0.1) self.uhd_usrp_source_0_0.set_command_time(self.tune_time,0) self.uhd_usrp_source_0_0.set_center_freq(tune_helper.int_n_tuning(self.freq),0) self.uhd_usrp_source_0_0.clear_command_time(0) self.uhd_usrp_source_0_0.set_command_time(self.tune_time,1) self.uhd_usrp_source_0_0.set_center_freq(tune_helper.int_n_tuning(self.freq),1) self.uhd_usrp_source_0_0.clear_command_time(1) self.qtgui_time_sink_x_0_0 = qtgui.time_sink_f( 1024, #size samp_rate, #samp_rate "", #name 1 #number of inputs ) self.qtgui_time_sink_x_0_0.set_update_time(0.1) self.qtgui_time_sink_x_0_0.set_y_axis(-120, 20) self.qtgui_time_sink_x_0_0.set_y_label('Phase Offset', "") self.qtgui_time_sink_x_0_0.enable_tags(-1, True) self.qtgui_time_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_0_0.enable_autoscale(False) self.qtgui_time_sink_x_0_0.enable_grid(False) self.qtgui_time_sink_x_0_0.enable_axis_labels(True) self.qtgui_time_sink_x_0_0.enable_control_panel(False) if not True: self.qtgui_time_sink_x_0_0.disable_legend() labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "blue"] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_time_sink_x_0_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_0_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0_0.pyqwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_time_sink_x_0_0_win) self.qtgui_time_sink_x_0 = qtgui.time_sink_f( 1024, #size samp_rate, #samp_rate "", #name 2 #number of inputs ) self.qtgui_time_sink_x_0.set_update_time(0.10) self.qtgui_time_sink_x_0.set_y_axis(-1, 1) self.qtgui_time_sink_x_0.set_y_label('Amplitude', "") self.qtgui_time_sink_x_0.enable_tags(-1, True) self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_0.enable_autoscale(False) self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_axis_labels(True) self.qtgui_time_sink_x_0.enable_control_panel(False) if not True: self.qtgui_time_sink_x_0.disable_legend() labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "blue"] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(2): if len(labels[i]) == 0: self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_time_sink_x_0_win) self.qtgui_freq_sink_x_1 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype freq, #fc samp_rate, #bw "", #name 1 #number of inputs ) self.qtgui_freq_sink_x_1.set_update_time(0.10) self.qtgui_freq_sink_x_1.set_y_axis(-140, 10) self.qtgui_freq_sink_x_1.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_1.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_1.enable_autoscale(False) self.qtgui_freq_sink_x_1.enable_grid(False) self.qtgui_freq_sink_x_1.set_fft_average(1.0) self.qtgui_freq_sink_x_1.enable_axis_labels(True) self.qtgui_freq_sink_x_1.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_1.disable_legend() if "complex" == "float" or "complex" == "msg_float": self.qtgui_freq_sink_x_1.set_plot_pos_half(not True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue"] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_1.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_1.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_1.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_1.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_1.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_1_win = sip.wrapinstance(self.qtgui_freq_sink_x_1.pyqwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_freq_sink_x_1_win) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype freq, #fc samp_rate, #bw "", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-140, 10) self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0.enable_axis_labels(True) self.qtgui_freq_sink_x_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0.disable_legend() if "complex" == "float" or "complex" == "msg_float": self.qtgui_freq_sink_x_0.set_plot_pos_half(not True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue"] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win) self.fir_filter_xxx_0 = filter.fir_filter_fff(flt_dec, (1, )) self.fir_filter_xxx_0.declare_sample_delay(0) self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_vff((180/math.pi, )) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((complex(math.cos(shift_in_radians),math.sin(shift_in_radians)) , )) self.blocks_multiply_conjugate_cc_0 = blocks.multiply_conjugate_cc(1) self.blocks_complex_to_real_1 = blocks.complex_to_real(1) self.blocks_complex_to_real_0 = blocks.complex_to_real(1) self.blocks_complex_to_arg_0 = blocks.complex_to_arg(1) ################################################## # Connections ################################################## self.connect((self.blocks_complex_to_arg_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.blocks_complex_to_real_0, 0), (self.qtgui_time_sink_x_0, 0)) self.connect((self.blocks_complex_to_real_1, 0), (self.qtgui_time_sink_x_0, 1)) self.connect((self.blocks_multiply_conjugate_cc_0, 0), (self.blocks_complex_to_arg_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_complex_to_real_0, 0)) self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.qtgui_time_sink_x_0_0, 0)) self.connect((self.fir_filter_xxx_0, 0), (self.blocks_multiply_const_vxx_0_0, 0)) self.connect((self.uhd_usrp_source_0_0, 1), (self.blocks_complex_to_real_1, 0)) self.connect((self.uhd_usrp_source_0_0, 0), (self.blocks_multiply_conjugate_cc_0, 0)) self.connect((self.uhd_usrp_source_0_0, 1), (self.blocks_multiply_conjugate_cc_0, 1)) self.connect((self.uhd_usrp_source_0_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.uhd_usrp_source_0_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.uhd_usrp_source_0_0, 1), (self.qtgui_freq_sink_x_1, 0)) def closeEvent(self, event): self.settings = Qt.QSettings("GNU Radio", "top_block") self.settings.setValue("geometry", self.saveGeometry()) event.accept() def get_flt_dec(self): return self.flt_dec def set_flt_dec(self, flt_dec): self.flt_dec = flt_dec def get_shift_in_radians(self): return self.shift_in_radians def set_shift_in_radians(self, shift_in_radians): self.shift_in_radians = shift_in_radians self.blocks_multiply_const_vxx_0.set_k((complex(math.cos(self.shift_in_radians),math.sin(self.shift_in_radians)) , )) def get_samp_rate(self): return self.samp_rate def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate self.uhd_usrp_source_0_0.set_samp_rate(self.samp_rate) self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate) self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate) self.qtgui_freq_sink_x_1.set_frequency_range(self.freq, self.samp_rate) self.qtgui_freq_sink_x_0.set_frequency_range(self.freq, self.samp_rate) def get_gain(self): return self.gain def set_gain(self, gain): self.gain = gain self.uhd_usrp_source_0_0.set_gain(self.gain, 0) self.uhd_usrp_source_0_0.set_gain(self.gain, 1) def get_freq(self): return self.freq def set_freq(self, freq): self.freq = freq # inserted code to synch LO and, by way of the mechanism, align the CORDICs self.tune_time=self.uhd_usrp_source_0_0.get_time_now(0)+uhd.time_spec_t(0.2) # tune in 200 msecs from 'now' #self.tune_time=self.uhd_usrp_source_m.get_time_now(0)+uhd.time_spec_t(0.1) self.uhd_usrp_source_0_0.set_command_time(self.tune_time,0) #####self.uhd_usrp_source_0_0.set_center_freq(uhd.tune_request(freq, samp_rate*1.5), 0) self.uhd_usrp_source_0_0.set_center_freq(tune_helper.int_n_tuning(self.freq),0) self.uhd_usrp_source_0_0.clear_command_time(0) self.uhd_usrp_source_0_0.set_command_time(self.tune_time,1) self.uhd_usrp_source_0_0.set_center_freq(tune_helper.int_n_tuning(self.freq),1) self.uhd_usrp_source_0_0.clear_command_time(1) #js self.uhd_usrp_source_0_0.set_center_freq(self.freq, 0) #js self.uhd_usrp_source_0_0.set_center_freq(self.freq, 1) self.qtgui_freq_sink_x_1.set_frequency_range(self.freq, self.samp_rate) self.qtgui_freq_sink_x_0.set_frequency_range(self.freq, self.samp_rate) def argument_parser(): parser = OptionParser(usage="%prog: [options]", option_class=eng_option) parser.add_option( "", "--flt-dec", dest="flt_dec", type="intx", default=1000, help="Set flt_dec [default=%default]") return parser def main(top_block_cls=top_block, options=None): if options is None: options, _ = argument_parser().parse_args() from distutils.version import StrictVersion if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): style = gr.prefs().get_string('qtgui', 'style', 'raster') Qt.QApplication.setGraphicsSystem(style) qapp = Qt.QApplication(sys.argv) tb = top_block_cls(flt_dec=options.flt_dec) tb.start() tb.show() def quitting(): tb.stop() tb.wait() qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting) qapp.exec_() if __name__ == '__main__': main()
# this module will be imported in the into your flowgraph from gnuradio import uhd int_n_args=uhd.device_addr("mode_n=integer") def int_n_tuning(target_f,lo_offset=0): tune_req=uhd.tune_request(target_f,lo_offset) tune_req.args=int_n_args return tune_req
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com