On Wed, Sep 6, 2017 at 7:37 PM, Marcus D. Leech <mle...@ripnet.com> wrote:
> On 09/06/2017 01:07 PM, Michael M wrote: > > > > On Mon, Sep 4, 2017 at 6:14 PM, Marcus D. Leech via USRP-users < > usrp-users@lists.ettus.com> wrote: > >> On 09/04/2017 04:54 PM, Michael M via USRP-users wrote: >> >>> I'm having an issue with my Ettus E310 where I'm seeing inconsistent >>> timestamping from one run to another. >>> >>> First, I set up a reference transmitter that is designed to output a >>> waveform at the top of each second. The transmitter has been tested and >>> shown to be within a few nanoseconds of GPS time with other test >>> equipment. This transmitter is connected to the RX2 input of the USRP E310. >>> >>> I am then setting the time source on the E310 to GPSDO and the clock >>> source to INTERNAL. I am waiting until the gps is locked and the reference >>> is locked. Once this is done, we are getting the gps time from the E310 >>> and setting the clock to what the GPS time should be at the next 1PPS. >>> This is all working fine and the time looks correct. >>> >>> Then, I receive the signal, write it out to files with the time stamps >>> and correlate with the signal that is being transmitted by the reference >>> transmitter. Within one run, I'm getting a standard deviation of under >>> 50ns for arrival time relative to the top of each second. If I stop >>> receiving and start again, I am again getting a standard deviation of under >>> 50ns for arrival time. The problem is that that arrival time varies as >>> much as a couple of microseconds between separate recordings. >>> >>> My question is, can anyone think of what might be the cause of this >>> variance from one run to another? Could it be something I'm doing wrong? >>> Could the process of locking the digital PLL to the 1pps reference have >>> enough jitter that once locked it is tracking a value that can be off by a >>> couple microseconds? I'd like to be able to get repeatable results from >>> one run to another (within 100ns). >>> >>> Thanks, >>> >>> Michael >>> >>> How are you starting your receive process? How is that time-coordinated? > > > Here's a quick snippet of what we were doing. We started with the > usrp_source_impl in gnuradio (https://github.com/gnuradio/ > gnuradio/blob/master/gr-uhd/lib/usrp_source_impl.cc), and added the > following code to set the timecode to gps time: > > this->set_clock_source("internal",0); > //Set time source to GPSDO > this->set_time_source("gpsdo",0); > //Wait for GPS Lock > while(this->get_mboard_sensor("gps_locked",0).value != "true") { > boost::this_thread::sleep(boost::posix_time::seconds(2)); > } > //Wait for REF Lock > while(this->get_mboard_sensor("ref_locked",0).value != "true") { > boost::this_thread::sleep(boost::posix_time::seconds(2)); > } > //Extra Sleep never Hurts > boost::this_thread::sleep(boost::posix_time::seconds(5)); > //Set PPS Time > long long this_pps, last_pps; > this_pps = last_pps = this->get_time_last_pps(0).to_ticks(1.0); > //Wait for PPS Edge > while (this_pps == last_pps) { > this_pps = this->get_time_last_pps(0).to_ticks(1.0); > } > boost::this_thread::sleep(boost::posix_time::seconds(.2)); > > this->set_time_next_pps(::uhd::time_spec_t(this->get_mboard_sensor("gps_time",0).to_int() > + 1.0)); > this_pps = last_pps = this->get_time_last_pps(0).to_ticks(1.0); > //Wait for PPS Edge > while (this_pps == last_pps) { > this_pps = this->get_time_last_pps(0).to_ticks(1.0); > } > boost::this_thread::sleep(boost::posix_time::seconds(.2)); > int sec_gps = this->get_mboard_sensor("gps_time",0).to_int(); > long long pps_sec = this->get_time_last_pps(0).to_ticks(1.0); > if (sec_gps == pps_sec) { > std::cout << "SYNC GOOD" << std::endl; > } else { > std::cout <<"FAILED TO SYNC" <<std::endl; > } > > > Then, in the work method, we also added a check to see if 10 seconds had > elapsed, in which case we tag the output to include the new timecode: > (fullSecs is initialized to 0 and newGoal is initialized to true when > starting) > > ... > if(newGoal && fullSecs != 0) { > newGoal = false; > goalSecs = fullSecs + 10; > //std::cout << "New Goal Set" << std::endl; > } > switch(_metadata.error_code) { > case ::uhd::rx_metadata_t::ERROR_CODE_NONE: > if(fullSecs >= goalSecs) { > _tag_now = true; > newGoal = true; > } else { > fullSecs = _metadata.time_spec.get_full_secs(); > //std::cout << fullSecs << std::endl; > } > if(_tag_now) { > _tag_now = false; > fullSecs = _metadata.time_spec.get_full_secs(); > //create a timestamp pmt for the first sample > const pmt::pmt_t val = pmt::make_tuple > (pmt::from_uint64(_metadata.time_spec.get_full_secs()), > pmt::from_double(_metadata.time_spec.get_frac_secs())); > //create a tag set for each channel > for(size_t i = 0; i < _nchan; i++) { > this->add_item_tag(i, nitems_written(0), TIME_KEY, val, _id); > this->add_item_tag(i, nitems_written(0), RATE_KEY, > pmt::from_double(_samp_rate), _id); > this->add_item_tag(i, nitems_written(0), FREQ_KEY, > pmt::from_double(this->get_center_freq(i)), > _id); > } > } > break; > ... > > We then wrote a gnuradio block that writes out files every time we get a > new tag (using the previously received timestamp, approximately every 10 > seconds). We connected that block to the output of the usrp_source We > then used external processing to do the correlations with the reference > file. > > > I don't see any code where you're arranging for streaming to start at a > particular time, if you're doing something like: > > wait-until-USRP-says-it's-time > start-receiving > > There'll be micro-second-to-millisecond-scale uncertainty about exactly > when streaming will start, because some unknown amount of ftime > will elapse between those two steps. > > > I am not setting a start time in the usrp_source gnuradio block, but it looks like even if I don't set a start time, the block does set a start time as follows: static const double reasonable_delay = 0.1; //order of magnitude over RTT ::uhd::stream_cmd_t stream_cmd(::uhd::stream_cmd_ t::STREAM_MODE_START_CONTINUOUS); stream_cmd.stream_now = _stream_now; stream_cmd.time_spec = get_time_now() + ::uhd::time_spec_t(reasonable_delay); this->issue_stream_cmd(stream_cmd); For me it's not important when the stream starts, as long as it has a precise timestamp (between 50-150 ns is good), which I get from the metadata coming in with the stream, which is done when receiving samples as follows: size_t num_samps = _rx_stream->recv( output_items, noutput_items, _metadata, _recv_timeout, true /* one packet -> minimize latency */ ); My issue is that I get consistent timing in one run of the flow (under 50-100ns for running even hours at a time), but if I stop it, then run it again, the delta between that run and the run before can be several microseconds (relative to the top of the second). As I mentioned before, I am using a reference transmitter which has a transmit time variance much smaller than 50ns and has been shown to be accurate. Do I need to do something different with setting the start time?
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com