DIY GPSDO project w/ STM32, TDC7200 - Page 1
Forum section: electronics / projects

author: thinkfat
author_rank: Unknown
timestamp: November 26, 2019, 11:52:44 am
content: Hi,inspired by the discussion on Lars DIY GPSDO, I went on to try a different, slightly more elaborate approach on the topic. I'm not yet sure if it's going to be an actual improval, it's just my take on the topic and it's deviating from Lars Walenius' design in several aspects.I'm using a dedicated time-to-digital converter chip (TDC7200) instead of the 4046/Arduino ADC TIC, which is pretty ingenious in its minimality but at the same time has some dependencies on component choice (leakage, temperature drift etc). I also decided to use an AD5693R instead of a PWM DAC.The controller I chose is an STM32F042 in LQFP-32 package. I actually wanted to go smaller but the 03x series has only one UART...To give the whole thing an initial purpose, the PCB is made so that you can directly plug it into the front connector of an LPRO-101 Rb standard.I've attached the schematics and a couple of screenshots (top, bottom PCB) if you want to have a look.The original design was sketched out by forum regular @imo, who I owe greatly for inspiration and giving hints for actual implementation.The status of the project is:- first revision of the schematic is complete- PCB is routed and first prototype has been launched.I hope it'll work good enough to start with the software integration and to work out the kinks to launch the second revision of the board.

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 11, 2019, 10:05:08 am
content: Can you sketch a rough area where you want to end up on ADEV or MDEV plot?Leo

author: thinkfat
author_rank: Unknown
timestamp: December 11, 2019, 10:13:23 am
content: The PCBs have arrived meanwhile and I'm assembling them bit by bit. I've put the 12V and 3.3V regulators on and I'm going to check out the STM32 first, making sure that it boots and that I can blink some LEDs.Next step will be to populate the HC390 and the TDC7200 and making sure that I can talk to it. When that's done, I'll start feeding a 10MHz and 1PPS signal from some GPSDO and see if the measurements make sense, I think that will also give me an idea about the noise floor I can expect.I've spotted a small problem already, the mounting holes for the LPRO-101 are a bit too far apart, the next PCB revision will correct that.The next revision will also remove the footprint for the ublox receiver and RF circuitry, I'll replace that with sockets for a ublox breakout board that I've designed, PCBs to come soon.

author: thinkfat
author_rank: Unknown
timestamp: December 11, 2019, 10:20:40 am
content: Quote from: Leo Bodnar on December 11, 2019, 10:05:08 amI have no idea yet. This is an experiment for me. I think the short-term ADEV (tau < 20s or so) will be as good as the LPRO-101 spec allows, it's not the best Rb standard out there, but its pretty ubiquitous. It'll depend mostly on the noise I'm introducing through the opamp that drives the C-Field adjustment, I guess.For the long-term stability, not sure how I'm going to measure it. My test equipment arsenal is pretty limited when it comes to picosecond deviations.

author: iMo
author_rank: Super Contributor
timestamp: December 11, 2019, 10:56:47 am
content: FYI - the TDC7200 has been elaborated in TAPR-TICC design years back:https://www.tapr.org/pdf/DCC2016-The_TAPR_TICC_Counter_Measuriing_Trillionths_of_a_Second_with_an_Arduino_John_Ackerman_N8UR.pdfThere are some measurements with ADEVs with cesium in the above pdf.Rubidium:http://lists.febo.com/pipermail/time-nuts_lists.febo.com/2019-September/097485.htmlhttps://www.eevblog.com/forum/projects/a-look-at-my-symmetricom-gpsdo-(ocxo-furuno-receiver)/msg1143960/#msg1143960Also here some detailed discussion:

author: thinkfat
author_rank: Unknown
timestamp: December 12, 2019, 10:22:34 pm
content: Small update:- The STM32 works, it boots and I have written a bit of test code, UARTs are OK and it's happily blinking its two status LEDs.- The input squarer works, it's output is not entirely symmetric, though. It outputs a square wave with about 54% duty cycle.- I'm not happy with the jitter of the 10MHz signal. It should be fairly stable, I source it from a GPSDO. I suspect the jitter is from the input squarer but I'll check what comes from the GPSDO, too.- The 74HC390 works and outputs a 500kHz signal to the TDC7200 (which is not yet mounted)- The 74AC04 creates around 40mV (p-p) ripple on the 3.3V digital supply rail. Good thing the DAC and the output opamp will each have an LDO on their own.- The 10MHz output (two parallel inverters from the same AC04 through aBesselButterworth filter) creates a fairly nice sine wave. I cannot really measure it, but the FFT of my scope suggests that the first harmonic is at least 45dB below the fundamental.The TDC7200 will be delivered tomorrow. I'll do some more meaningful tests once it's on the PCB. I'll probably not assemble the analog section on this PCB revision, not until I've found out where the jitter on the 10MHz come from.Current schematic attached.EDIT: I think the jitter might be through the voltage divider at the input of the AC04-F. The ripple on the VDD rail directly translates to an input bias shift. Maybe a small capacitor parallel to R12 would help.Update: No, of course a capacitor parallel to R12 won't be good because it's then part of a capacitive voltage divider that attenuates the input signal. However, beefing up the decoupling by exchanging C27 with a 4.7u MLCC worked much better. Also, I see the jitter on the scope only on every _second_ rising edge. Likely a problem of the scope and not actually there. Fedex just delivered the TDC7200 so I'll put that on the PCB and when that's done, I'll be working on the software for a bit.Update2: Took a closer look at the jitter: It's coming and going in 100ns intervals. 100ns from the trigger point it's there, 200ns it's gone, 300ns it's back. This is a Rigol 1054Z. You may remember the infamous jitter problem they have due to bad PLL loop filter design, what I'm seeing is similar to that issue. I have the software update but we all know it's only a band aid. So I'm going with the assumption that the signal is actually OK and I'm only seeing a scope artifact.

author: edpalmer42
author_rank: Super Contributor
timestamp: December 13, 2019, 04:40:28 pm
content: The AC04 can generate pretty substantial current spikes on the +5V supply, depending on what it's driving. You should consider using a dedicated +5V supply and AC04 for the input sine/square stage and maybe a second dedicated supply and AC04 for the output buffer.

author: iMo
author_rank: Super Contributor
timestamp: December 13, 2019, 05:15:44 pm
content: The decoupling caps are not always enough.. An RC (R=10-100ohm) or LC (L=1-10u) may help, even the LC has to be designed with care - not to introduce some resonances increasing the ripple..

author: thinkfat
author_rank: Unknown
timestamp: December 14, 2019, 07:23:45 pm
content: Alright, small update:The TDC7200 seems to work fine, the STM32 can talk to it just fine and I'm getting interrupts for completed measurements. I adapted an Arduino library I found on Github and it seems I can configure the chip and retrieve measurement data. The biggest problem was actually translating the Arduino SPI class into opencm3 speak, but going back to the basics and realizing how SPI works at the shift register level brought enlightenment in the end.The values I get seem to be stable down to the 1ns level, but I have only the debugger connected at the moment and no logging, I have to write a bit of code that spits out the measurements to one of the serial ports so that I can log them and feed them through Octave or something. Frequency and 1PPS are atm. sourced from the same GPSDO, so no wonder they are nicely correlated.Other news: the PCBs for the Ublox breakout board I designed are back from Aisler, which means I will have a little side project this weekend to populate the board and check if it actually works. Then it's time to think about improvements for the next PCB revision.

author: thinkfat
author_rank: Unknown
timestamp: December 14, 2019, 08:12:27 pm
content: Quote from: imo on December 13, 2019, 05:15:44 pmI think I'll play safe and go with an RC. I might be able to squeeze in a small tantalum capacitor, too. I think I can even prototype it, I can cut the VDD trace on the bottom copper and bridge it with a small resistor and then check what additional capacitance I might need. But first I want to log a couple hours of data with the existing setup to have a benchmark.

author: thinkfat
author_rank: Unknown
timestamp: December 14, 2019, 08:51:13 pm
content: Quote from: edpalmer42 on December 13, 2019, 04:40:28 pmI don't think I have enough space to fit another two AC04. But if there are single AC inverters or NANDs, that might be an option.

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 08:43:19 am
content: First raw data set, scale 1ps, 1 sample per second.

author: iMo
author_rank: Super Contributor
timestamp: December 15, 2019, 09:57:32 am
content: 835ns w/ 173ps_rms (first 20k). What have you measured?

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 10:37:46 am
content: Quote from: imo on December 15, 2019, 09:57:32 amThese are just the raw measurements from the 1PPS pulse rising edge to the next rising edge of the divided-down clock, sourced from the same GPSDO. I want to use them as a benchmark for future improvements. I'll modify the AC04 supply, adding a small resistor into the supply rail, then run the measurement again to see if there's an improvement.Mode 2 measurements, 10 calibration cycles, 1 stop event, no averaging.

author: iMo
author_rank: Super Contributor
timestamp: December 15, 2019, 10:56:01 am
content: It means you generate "1PPS" from the OCXO's 10MHz clock?

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 15, 2019, 11:02:22 am
content: There are some nasty outliers in there. They need removing before applying any statistics.Leo

author: iMo
author_rank: Super Contributor
timestamp: December 15, 2019, 11:05:43 am
content: Quote from: imo on December 15, 2019, 09:57:32 amTherefore I took only first 20k samples. It also depends where the 1PPS comes from.173ps rms seems to me rather high. I got about 120ps on a solderless breadboard while measuring 100ns pulse off my OCXO (as my benchmark).

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 11:10:27 am
content: Quote from: imo on December 15, 2019, 10:56:01 amNot exactly sure how the GPSDO creates the 1PPS signal. It's one of those UCCM telecom modules, this particular one was made by Trimble.I noticed the outliers as well, when removing them I get a mean of 835.13ns and standard deviation of 16.295ns

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 15, 2019, 11:46:51 am
content: Note how things are warming for the first ten minutes. Perhaps, strip them from reference run as well.All outliers are at the end of the run (beyond 6 hours). It may be that one of the edges has drifted into some metastability zone.What does 835ns represent?Leo

author: iMo
author_rank: Super Contributor
timestamp: December 15, 2019, 11:58:48 am
content: For measuring the TDC7200 and the circuits around do not use 1PPS from an external source!Divide the 10MHz OCXO (the same OCXO you are using for TDC7200 and 500kHz) to 1Hz, and feed it to 1PPS input.Invert the 500kHz when you get small readings (you will get either a few ns readings or 1us readings).PS: perhaps an improvement for the next pcb revision - it is nice to have a chance to invert the 500kHz phase coming to the TIC - for self measurement purposes..PPS: you cannot get 16ns rms, with first 22k samples (no outliers there) you get 173ps rms.

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 12:25:47 pm
content: The 835ns have no significance. It's just what the phase relation between the 1pps pulse and the 10Mhz signal happen to be, including the propagation delay through the AC04 and HC390.

author: iMo
author_rank: Super Contributor
timestamp: December 15, 2019, 12:30:45 pm
content: The propagation delay through 04 and 390 is 20ns. So the question is where the 1PPS comes from? An external source? Or you have used the same OCXO divided by 10mil as you are using for 500kHz? As I wrote above - do not use an external 1PPS for self diagnostic test. See my picture above.PS: another self test would be to feed the 1PPS with 500kHz (off the "stop wire"), passed through an inverter such you get 1us start-stop difference. You should get aprox "1.000.000ps" readings, with stddev below 100ps (~60ps ideally), no outliers, hopefully.

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 03:58:32 pm
content: Quote from: imo on December 15, 2019, 11:58:48 amI had hoped that using the 10MHz and the 1PPS from the same GPSDO would be just that. But it is a 'maybe' I should seek to eliminate.I'll hook them both up to a scope and take a look.

author: thinkfat
author_rank: Unknown
timestamp: December 15, 2019, 08:55:39 pm
content: Quote from: imo on December 15, 2019, 12:30:45 pmYep, I will try that. I was thinking of using the spare dividers in the HC390 to create a correlated start signal. But using an inverter is just as good.

author: thinkfat
author_rank: Unknown
timestamp: December 17, 2019, 05:35:26 am
content: No time yet for big modifications, but I tried something else: I used an external squarer. Result attached, raw data, like the previous one.Just for kicks I've added an Allanvariancedeviation plot.

author: iMo
author_rank: Super Contributor
timestamp: December 17, 2019, 08:16:39 am
content: The std dev is better: 97ps.The squarer - there is a discussion in Lars' thread.

author: thinkfat
author_rank: Unknown
timestamp: December 17, 2019, 08:48:15 am
content: Yes, it's definitely better. I also tried removing any residual drift with a FIR high-pass filter, but the improvement is only marginal.

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 17, 2019, 08:58:39 am
content: Quote from: thinkfat on December 17, 2019, 05:35:26 amNumbers look unusually bad for variance, are you sure it is not deviation?Leo

author: thinkfat
author_rank: Unknown
timestamp: December 17, 2019, 09:09:36 am
content: Quote from: Leo Bodnar on December 17, 2019, 08:58:39 amYep, you're right. It's Allan deviation (tau-sigma). I'm correcting the post.

author: iMo
author_rank: Super Contributor
timestamp: December 17, 2019, 11:12:55 am
content: And it is ADEV of what? How did you get the ADEV off pps2log?

author: thinkfat
author_rank: Unknown
timestamp: December 17, 2019, 02:36:49 pm
content: Well that's just the pps2.log.txt dataset scaled to 1ps and then run through "octave" and a function for ADEV. What it shows I think is that for observation intervals longer than 400 seconds, you get down to a resolution of about 60ps and no improvement from there on. If I understood it correctly, that's the limit of the TDC7200.

author: iMo
author_rank: Super Contributor
timestamp: December 17, 2019, 02:53:21 pm
content: With TimeLab (all trends subtracted) I get the same result, but 5ps (not 60ps). You've got 5ps too, it seems.I've multiplied the data by 1e-12.Have you filtered the data in pps2log.txt above somehow?PS: doublecheck your 7200 math. As I wrote earlier, the first step should be to test the 7200 such it returns correct data. Best with well defined start-stop, ie. 1us directly on the board (not with external sources with undefined params).

author: thinkfat
author_rank: Unknown
timestamp: December 17, 2019, 05:14:48 pm
content: Quote from: imo on December 17, 2019, 02:53:21 pmThe data is unfiltered, I just cut of a section at the beginning with an obvious temperature drift, then multiplied it by 1e-12. You're right, it's somewhere in the 5ps range, I misread the graph.The math is indeed a bit tricky. I used the well-known Arduino library for the TDC7200 (there is only one I believe) and translated it into plain C. There's definitely some pitfalls in there due to the mixed data types (32bit unsigned int vs. 64bit signed int etc), I had to get in with the debugger and look at intermediate results to get all the casts correct. I had to introduce a few temporary variables to make sure the compiler does everything correctly. When I have a bit of quality time to wire up an inverter, I'll definitely make a sanity check.Menawhile I checked a couple of ideas around the squarer and decided that no amount of trickery with the current single-chip solution will get me to the required stability. So I'll add an additional inverter gate, probably an SN74LVC1G04 in SOT23-5 package, might be able to squeeze it in there if I push the chips around a little bit.

author: iMo
author_rank: Super Contributor
timestamp: December 17, 2019, 05:21:41 pm
content: FYI - the squarer from TAPR-TICChttps://github.com/TAPR/TICC/blob/master/docs/TICC_rev_d_schem.pdf

author: thinkfat
author_rank: Unknown
timestamp: December 18, 2019, 09:52:50 am
content: That's only the frontend part of it, though. There's an additional inverter after it, too.

author: thinkfat
author_rank: Unknown
timestamp: December 18, 2019, 09:58:00 am
content: I've taken some time to assemble the Ublox breakout module. Seems to be working, at least Lady Heather claims it's a Ublox timing receiver. Bought it on Ebay from some French guy. Seems he has got the real stuff.No antenna connected for now, I'll do that tonight when I'm back home.

author: iMo
author_rank: Super Contributor
timestamp: December 18, 2019, 05:35:49 pm
content: FYI - some thoughts on sine squarer:http://www.wenzel.com/documents/waveform.htmlhttp://www.ke5fx.com/ac.htm

author: edpalmer42
author_rank: Super Contributor
timestamp: December 18, 2019, 05:59:24 pm
content: Quote from: thinkfat on December 18, 2019, 09:52:50 amThe first stage is the key. The performance of this frontend will determine the performance of your entire circuit. Many people have tried many different circuits to determine what works best. There doesn't seem to be a clear winner, but if you insist on the best possible performance, start researching circuits that NIST uses. I don't have any links handy.Turning a sine wave into a square wave is an analog function. Trying to use a digital IC like a 74AC04 means you're operating far outside the normal operating parameters. You're trying to make a digital circuit act like an analog comparator. Standard rules doNOTapply. Once you're past the first stage, you're now back into a normal digital environment. Good performance in this environment is relatively easy to obtain.The LPRO User's Guide and Integration Guidelines includes some good info on the topic.http://www.ko4bb.com/getsimple/index.php?id=download&file=02_GPS_Timing/Datum/LPRO/Datum_LPRO_Users_guide1.pdf

author: thinkfat
author_rank: Unknown
timestamp: December 18, 2019, 07:39:09 pm
content: Quote from: thinkfat on December 18, 2019, 09:58:00 amWith antenna connected - looks good. Not surprising, however. Biggest unknown was the origin of the ublox module, but it seems it's a good one.The breakout board is trivial, the only complex item is a microstrip transmission line to connect the antenna socket with the module.

author: thinkfat
author_rank: Unknown
timestamp: December 18, 2019, 07:46:44 pm
content: Quote from: edpalmer42 on December 18, 2019, 05:59:24 pmYep, that's what I was using as a reference. They recommend the 74AC04, actually, in a non-self biasing configuration. I copied the circuit almost verbatim, but the decision to use the remaining inverters to distribute the 10MHz and as a driver for a sine wave output was quite likely a mistake. I skimped on the decoupling network they suggested, which was the second mistake.

author: thinkfat
author_rank: Unknown
timestamp: December 18, 2019, 08:02:56 pm
content: Quote from: imo on December 18, 2019, 05:35:49 pmThe TAPR-TICC input squarer frontend looks like a verbatim copy of the Wenzel paper. I likely won't need the a large input range for my purpose, so I'll pass here. I do like your version with the resonant LC tank for its simplicity.How do you tune the circuit? I guess a fixed L and a trimmer capacitor are the best option here.

author: iMo
author_rank: Super Contributor
timestamp: December 18, 2019, 08:12:51 pm
content: Quote from: thinkfat on December 18, 2019, 08:02:56 pmThe TAPR-TICC has got some "improvements" there, so it is not a verbatim copy. LC tank - I used to use a tuned L actually (off my junkbox), the fixed L and a combination of cap trimmer and fixed C would be more feasible today.PS: off topic - still thinking how to get someone's position (lat, long) off the UTC and the position of the satellites listed

author: thinkfat
author_rank: Unknown
timestamp: December 19, 2019, 10:30:08 am
content: Quote from: imo on December 18, 2019, 08:12:51 pmWhat was the Q of the inductor you used? Is it even relevant, I'm guessing that R would be the dominant factor anyway?Regarding the position - that's an intriguing thought. But I doubt the precision would be better than city-level.

author: iMo
author_rank: Super Contributor
timestamp: December 19, 2019, 02:13:11 pm
content: The L's quality - the higher the better.. The output impedance of the source should be kept low, as it is the part of the parallel LC tank (low Z coupling at the cold side, the tank's hot side is the inverter's input). The Rin=47-100ohm. Tune with o'scope (10Meg probe + few pF serial coupling) at the inverter's input to max amplitude (or to the max slope of edges, as the clamping diodes will limit the amplitude at the inverter's input). Mind it is a highZ point sensitive to parasitic C. Also the best inductor core would be iron powder (low TC) - see amidon toroid cores:http://www.qrz.lt/ly1gp/amidon.html

author: thinkfat
author_rank: Unknown
timestamp: December 23, 2019, 09:57:32 pm
content: Took some time today to wire up an inverter between STOP and START. The results are - interesting.Instead of steady 1µs measurement I get two clusters, one at 1µs and one at 3µs. Both in itself are stable, but the measurements jump randomly between the two.Not SPI weirdness, I took a scope to the SPI bus and decoded the line protocol, the values I read in the software are actual, visible on the line.There difference between the clusters is only from the TIME1 register, it jumps to and fro between them.However, In "mode 2", TIME1 is the ring oscillator count from start to the next rising edge of the clock input. The clock input is 10MHz, so I cannot quite see how even a missed edge there could amount to a 2µs offset. There must be something very odd in my calculation. Something wrong with the LSB calculation from the calibration values, I guess.

author: iMo
author_rank: Super Contributor
timestamp: December 23, 2019, 10:07:58 pm
content: Doublecheck whether you always calculate off the first s-s clock counter of the 7200 (there are 5).Is the 1us pulse ok on your oscope?Also what exact numbers you read?In mode2 the ring oscillator counts 2x - TIME1 (start) and TIME2 (stop), plus it counts 10MHz periods CLOCK_COUNT1.QuoteTIME1 gives you max 100ns so no way to jump between 1u and 3us. Even with TIME2 it is not possible. With fully messed TIME1 and TIME2 it should show 1us +/- 200ns.Nope - all those TIMEx and CLOCK_COUNTx are 24bit counters - so a lot of space for math problems..

author: thinkfat
author_rank: Unknown
timestamp: December 24, 2019, 08:38:52 am
content: Yes, there's something very strange about the TIME1 measurements. The readings are around 36620 for the 3µs cluster and 1262 for the 1µs cluster.normLSB is reasonable and computes to around 56ps. The COUNT1 register always reads 10, which is also what it should be.Provided there's nothing wrong with the circuit, what could be the reason for the strange TIME1 reading? It's almost as if the TDC was missing edges on the clock input and the ring oscillator doesn't stop. But on the scopes the signal there looks good.

author: iMo
author_rank: Super Contributor
timestamp: December 24, 2019, 09:01:45 am
content: The best way would be to log (and post here) an excel table with a series (say 100 measurements) of following data:Code:PulseN. TIME1 TIME2 CLOCK_COUNT1 CALIBRATION1 CALIBRATION2 YOUR_TOF1The assumption would also be the clock period is 100ns and CALIBRATION2_PERIODS is 10.

author: thinkfat
author_rank: Unknown
timestamp: December 25, 2019, 06:47:19 am
content: Santa brought an SDG2042X. Guess what happens if you use a proper signal source instead of a sketchy GPSDO from ebay.Anyway, the measurements I'm getting are now 999999ps +/- 1. No glitches, no outliers.I'm guessing the GPSDO has a high-impedance output, not 50and the BNC connectors are just decoration.

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 10:10:23 am
content: Photo of the test setup before I tore it down again to return to real world testing.

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 10:40:25 am
content: I'm now using both channels of the waveform generator to generate the 10MHz input and the 1PPS pulse. The results are extremely boring: the measurements are super-stable now, like with the previous self-test. +1ps or -1ps from the median are the maximum deviation I get, and they're rare. I'll log a couple thousand measurements to get some data, but it's all pretty promising.The nice thing about using a waveform generator is that I can tweak the phase of the 10MHz signal and look at the effect on the measurements.Next test will be hooking up the GPS module I built to take a look at the 1PPS. I'm driving the waveform generator with the GPSDO as external clock so there should be a good correlation and no frequency drift.

author: iMo
author_rank: Super Contributor
timestamp: December 27, 2019, 10:49:46 am
content: QuoteHmm, to get something like +/-1ps is impossible, imho.The TDC7200 itself is 35ps rms, that is perhaps180230ps p-p.Perhaps your result is in ns?? Then you may get boring +/-1ns..With a quality generator you cannot get something better thanthis histogram, as an example:

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 11:03:05 am
content: Quote from: imo on December 27, 2019, 10:49:46 amOK. Then I need to double-check the math. I'll record the register readings like you suggested and post them here as a CSV.Attached find the first 1181 measurements, I get a mean of10µs100ns and a standard deviation of 0.28ps. That's indeed to good to be true.

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 27, 2019, 11:13:59 am
content: Should you not see quantisation likehere?55ps resolution and 35ps rms accuracy has always confused me - shouldn't all raw data bins be 55ps wide?Leo

author: iMo
author_rank: Super Contributor
timestamp: December 27, 2019, 11:26:52 am
content: Quote from: thinkfat on December 27, 2019, 11:03:05 amSure, doublecheck your math. You have to get 100ns +/-115ps ideally (in mode 1 !!), afaik.In mode 2 working with 100ns pulse is not recommended - you will most probably get weird results.PS: as recommended above, I would advice you to provide some measurements with well defined pulse length (ideally 1us in mode 2). Print out in .csv format all the TDC7200 registers/data and do analyze them. Fix your math and get your 7200 under full controlPPS: btw, the chip allows 1..128 averaging cycles (AVG_CYCLES) (see ch. 8.4.4 Multi-Cycle Averaging)

author: iMo
author_rank: Super Contributor
timestamp: December 27, 2019, 11:35:33 am
content: Quote from: Leo Bodnar on December 27, 2019, 11:13:59 am55ps resolution with 35ps sigma, 28ps accuracy - sure confusing, the granularity should be visible while zooming into the histogram, imho..

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 12:08:25 pm
content: Alright, I found something: In the calculation of normLSB, the Arduino library assumed that CALIB2-CALIB1 can never become negative. But there's nothing in the datasheet that would support this.Find attached some Excel sheet with my calculations based on register values.

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 02:41:52 pm
content: What I'm not getting is the huge fluctuation in readings from the CALIBRATON1 and CALIBRATION2 registers. That doesn't look good to me.EDIT: the waveform generator was setup incorrectly - I was feeding 10kHz instead of 10MHz. That is waaay out. It's not even spec'd. Minimum clock input is 1MHz according to the datasheet. Not a miracle the readings of the calibration values were strange.

author: iMo
author_rank: Super Contributor
timestamp: December 27, 2019, 03:07:30 pm
content: There is an issue somewhere. It looks like you readings are weird. Doublecheck your SPI routines. And plz describe what you are measuring and how.PS: read my above post - you cannot measure 100ns long pulse in MODE2 !!!PPS: the normLSB cannot be smaller than 50ps, imho.

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 03:42:31 pm
content: Quote from: imo on December 27, 2019, 03:07:30 pmSee above. I was feeding 10kHz instead of 10MHz to the clock input. That would not work anyway. The TDC7200 can not operate under these conditions.

author: thinkfat
author_rank: Unknown
timestamp: December 27, 2019, 11:16:25 pm
content: Some measurements after correcting the wavegen settings, see Excel sheet attached.Conditions:- clock input 10MHz from channel 1 of the wavegen.- 1PPS input is fed with a 500kHz 50% duty cycle square wave from the second channel of the wavegen.- the two channels are phase-locked. The phase is adjusted so that the period between start and stop should measure 1µs.Findings:- I'm back to two clusters, spaced 2µs apart.- Using the wavegen instead of the GPSDO didn't actually make a difference. I thought the problem gone when I was feeding a 10kHz clock instead of 10MHz.- 2µs is the period of the 500kHz clock used as the START/STOP signal.Update:This thread on the TI E2E community might be the same issue. Unfortunately it wasn't resolved.https://e2e.ti.com/support/sensors/f/1023/p/828776/3117130?tisearch=e2e-sitesearch&keymatch=TDC7200%2520TOF%2520multiple%2520clusters#3117130

author: iMo
author_rank: Super Contributor
timestamp: December 28, 2019, 01:06:16 am
content: The numbers look much better now.When you subtract 2us from those 3us long pulses you get 1.005us with 498ps stddev.That jitter may come from your signal generator.The rms jitter contributed by your signal generator is sqrt(10)*sig_gen_jitter_rms, thus ~100ps rms jitter off your Siglent will mess up the expected result accordingly..Therefore I advised not to use an external signal source for that specific measurement.3us issue - you feed the inputs by the "proper" edges, but mind there are inverters in the signal path. Doublecheck the polarity and sequence of the start-stop edges directly at the 7200 inputs.In standard operation the inverters do not matter, as the 10MHz and 1PPS edges are random phased before the lock.PS: during the "3us issue" the TIME1 shows 2.090748usecs = 37070*56.4ps.The COUNT1 is always 10 CLOCKs.It could mean - after the start edge the TIME1 sometimes runs ~2us long "waiting" for the first edge of the 100ns CLOCK.Normally the first edge of the 100ns CLOCK comes in 1641*56.4ps.Hmm.PPS: ENABLE input - do not toggle the EN during measurements (it is a reset). Upon power up it should be LOW, then wait say 100ms and set it HIGH.

author: texaspyro
author_rank: Super Contributor
timestamp: December 28, 2019, 01:09:15 am
content: You might want to look at the source code for the TAPR TICC and see what that is doing...

author: thinkfat
author_rank: Unknown
timestamp: December 28, 2019, 08:21:27 am
content: The TAPR TICC driver for the TDC7200 is a bit weird, with its magic numbers and correction terms. But it's doing nothing special, apart from that.I posted my question on the TI E2E forum, let's see if I get an answer there.I wonder if there's a minimum time to maintain between starting the measurement and seeing the start signal?EDIT: TTRIGSTART, the time from the TDC enabling the TRIGG output (in response to a measurement start) to receiving the START signal is given as 5ns nominal. There is no minimum value, so this seems to be just a recommendation. But what if the time is much shorter than that?

author: mino-fm
author_rank: Regular Contributor
timestamp: December 28, 2019, 09:53:26 am
content: Time from TRIGG to START is typ. 5 ns. Take a look at DS page 6 "Recommended Operating Conditions".Edit: avoid shorter times. Internal logic is not as fast as its ring counter, so behavior is not predictable.

author: thinkfat
author_rank: Unknown
timestamp: December 28, 2019, 10:45:15 am
content: Quote from: mino-fm on December 28, 2019, 09:53:26 amAye, that's good info. It might be the reason for the effect I have. I think it'd be prudent to configure an overflow value for the coarse counter and discard those measurements.

author: iMo
author_rank: Super Contributor
timestamp: December 28, 2019, 10:58:40 am
content: You do not use TRIGG output, that 5ns prop delay is not relevant in your system, imho.You set the start bit via SPI and the 7200 waits on the starting edge which comes almost "randomly" (but in 2us period). After receiving stop signal the 7200 should ignore the start edge.The largest TIME1 value in your case is 100ns/56.4ps = 1773. The "good result" is always 1641. That is interesting too. I would expect random values from 0..1773 for TIME1.EDIT: ok, you get always 1641 because your Siglent's 10MHZ/500kHz outputs are phase "locked" internally, as you wrote.Do you use INTB interrupt? Do you have the 1uF ceramic at Vreg there?EDIT: Hmm, I still do not understand how you can get start-rising-edge stop-rising-edge 1us apart when feeding the 1PPS input with 500kHz signal. Does the Siglent allow to set 10MHz and 500kHz phases such the 10MHz/20 and 500kHz rising edges are always 1us apart? Could you doublecheck with oscope or LA directly at 7200 start/stop inputs if that happens always?

author: thinkfat
author_rank: Unknown
timestamp: December 28, 2019, 12:36:46 pm
content: Quote from: imo on December 28, 2019, 10:58:40 amAs I interpret it, TTRIGGSTARTis the recommended time between starting a measurement and the START signal arriving. TRIGG is output by the TDC as a response to the start command from the MCU and the TDC is ready for a measurement within 5ns. This can be interpreted as a guard time. Since the 500kHz signal on START is not correlated to the measurement start from the MCU, it may well fall within this window. In normal 1PPS operation, it's not really relevant as there is always plenty of time between the start command and the 1PPS pulse. In hindsight, I could have routed the START signal to a GPIO. I'll put that on the TODO list for the Rev2 board.Yes, I'm using the INTB interrupt and I also read the INT_STATUS register to check if a measurement is done when I receive it. I have a 1µF MLCC on VREG. Voltage on VREG is around 1.5V which seems reasonable.Checking START/STOP directly on the TDC inputs is on my TODO list. But the soldering is a bit fiddly, I need to find a quiet hour to do it. The Siglent allows me to set arbitrary phase relation between the outputs. I can shift them against each other at will.

author: iMo
author_rank: Super Contributor
timestamp: December 28, 2019, 01:25:12 pm
content: So set the phase shift to 1.050useconds (1us+100ns/2).. What happens then?

author: thinkfat
author_rank: Unknown
timestamp: December 28, 2019, 01:30:14 pm
content: The phase shift is affecting only the time between start and stop. Not the time between the measurement start command that arms the TDC and the START signal that starts the actual TOF measurement.

author: iMo
author_rank: Super Contributor
timestamp: December 28, 2019, 01:38:43 pm
content: So try to add a random delay (0..100us for example) into your MCU code how it affects the result.QuoteYou run the MCU with its internal RC oscillator (from schematics) so the event would be rare. Your 3us issue is almost in half of the measurements.

author: FriedLogic
author_rank: Regular Contributor
timestamp: December 28, 2019, 02:09:30 pm
content: Hi,An Arduino that uses crystal for the microcontroller can be quite good for generating pulses to test basic TDCs. With basic stuff like port writes, NOPs and loops, delays can be set to 1 clock cycle as long as the interrupts are off during the delay. I got the delay into the milliseconds that way, although it takes care since the compiler tries to optimize out that sort of thing. The compiler can change behaviour between versions too, so it may optimize differently.IIRC, the results were mostly under 0.5ns P-P for a basic acam TDC-GP21 board.I'm sure that there are more elegant ways to do it, but it's very simple for the sort of short delays that are usually needed with a GPSDO. Making a tester with a PIC like the dividers that Tom has on Leapsecond.com has been on my to-do list for a long time...

author: mino-fm
author_rank: Regular Contributor
timestamp: December 28, 2019, 03:42:46 pm
content: Quote from: thinkfat on December 28, 2019, 12:36:46 pmFor start signal I use a single D-FF to synchronize between trigger enable and input signal. D-input is set by IO-pin after TDC-trigger is enabled. Here's my short code for STM32F4xx:void trigger_TDC(void){volatile int n = 5;TDC_write_cmd(0x4140); // Abgleich auf 10-fach einstellen; default settingTDC_write_cmd(0x4081); // Trigger inkl. autom. Abgleich ausgeben; enable START, set TRIGGwhile(n--); // interne Trigger-Verarbeitung vom TDC abwarten; waiting a short timeGPIO_SetBits(GPIOC, TRIG1_BIT); // Trigger-Ausgang auf '1'; set IO-Pin => D-input of D-FF}As you see an extra delay is inserted (and needed) before setting IO-pin. Omit this and you get weird numbers from time to time.

author: iMo
author_rank: Super Contributor
timestamp: December 28, 2019, 05:56:14 pm
content: FYI - a voodoo note form TICC source (not sure it is still valid):Quote

author: mino-fm
author_rank: Regular Contributor
timestamp: December 28, 2019, 07:08:36 pm
content: I can't confirm this. I'm using mode 1 with 1 x stop.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 10:22:29 am
content: A couple of new findings:I graphed START, STOP and TRIGG signals with my scope. The START and STOP traces showed that indeed the signals were locked against each other with no apparent jitter (at least not that I could see it on the scope). I conclude that this is therefore a viable setup for a performance test.Then I used the TRIGG signal as an indicator of when the start command from the MCU is executed by the TDC. I tried creating a trigger criterion for the assumption that TRIGG to START < 5ns causes an invalid measurement. This wasn't entirely conclusive. Indeed I found that when TRIGG to START is < 5ns I get a bogus measurement, but the frequency of bogus measurements is much higher than the events observed by the scope. This could mean that the window is much larger than those 5ns from the datasheet. Playing around with the trigger window hints that the critical window might be more in the tens or even hundreds of nanoseconds range.I decided then to discard all the measurements with implausible TIME1. Using only the samples of the 1µs cluster as total population, the standard deviation calculates to around 38.5ps.You can confirm the calculation based on the previously posted data set in Excel. Filter the TOF column to show only values < 2µs, then use the SUBTOTAL() function to calculate stdev.So far, so good, however the next headscratcher is right around the corner. When I set the 1PPS input to an actual 1 second pulse signal, I get 4 clusters, spaced exactly 500ns. Confirmed with the scope, the signals are not properly locked. The phase shifts exactly 90 degrees every second. Might be some peculiarity of the instrument itself. I'll investigate that. I wanted to update the software of the Siglent anyway.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 12:33:34 pm
content: QuoteAnd here is the histogram from the above data with the ~55ps quantization visible.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 01:25:45 pm
content: You may also improve the measurement such you1. set the NEO's 1PPM output to 128Hz (48MHz/375000=128)2. set TDC7200 to 128 averaging cycles3. you should get an interrupt in 1sec period with new data4. TOF= normLSB * (TIME1 - TIME2) + (CLOCK_COUNT1 / 128) x 100ns

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 04:21:01 pm
content: The INTB output of the 7200 is open drain, you need a pullup resistor there (or set the MCU's input with pullup).

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 04:40:10 pm
content: Quote from: imo on December 29, 2019, 04:21:01 pmYup, I missed that. Forgot to put a pull resistor, but it seems the MCU's internal pull-up is sufficient.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 04:49:54 pm
content: Quote from: thinkfat on December 29, 2019, 10:22:29 amTry with higher frequency at the 1PPS, like 10k/1k/100Hz.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 04:52:41 pm
content: Quote from: imo on December 29, 2019, 01:25:45 pmExcellent suggestion! I just modified my software to use the cycle averaging feature and set the Siglent to provide a 128Hz pulse. This works nicely, the phase shift is gone, measurement results are stable.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 05:22:34 pm
content: I still think the "3us issue" is coming outside the 7200 (hw or sw wise). I could imagine myself the 5ns between setting TRIGG and incoming start rising edge could be critical. But more than 5ns is not a realistic number, imho. The 3us issue comes from a problem with the input rising edges sequence, or some wrong setting of the 7200 registers. For example with some weird setting of CLOCK COUNTER STOP MASK value you will be ignoring the first 1-2 stop edges.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 05:31:01 pm
content: Ignoring some Stop edges will not make a difference for TIME1, though.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 05:52:31 pm
content: In past I messed with an FPGA shooting start/stop edges at around 100ns apart, 7200 in mode 1, readings 10-100x per second. 7200 soldered on an DIL adapter board, put into the solderless breadboard, wired to BluePill. The sequence was under BP control - BP initiated the process in the FPGA - thus the 100ns TOF was single-shot. The library as-is from the github. Never saw that kind of problem. I did not use INTB btw, I simply read the registers after some small delay. Also TRIGG output was not used.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 06:25:07 pm
content: Quote from: thinkfat on December 29, 2019, 04:52:41 pmI've been just thinking what would be a better solutiona) 128x averaging in the 7200, or,b) single measurements with the TOF results, done say 128x per second, and then the 128 TOFs averaged..

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 08:07:39 pm
content: The datasheet suggests to use multi-cycle averaging to battle system clock jitter...Anyway, here's a dataset of roughly 3300 samples. 128 averaged cycles, COUNT1 register already shifted, 10 calibration cycles, 128PPS input.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 08:39:22 pm
content: I'm also taking a couple of samples with the software averaging now, it seems already after a couple measurements that the std dev is lower (30ps vs. 43ps).But I'm very much doubting that the formula from the datasheet for multi-cycle averaging is numerically sound for integer. The term "(CLOCK_COUNT1 >> log2(AVG_CYCLES)) * CLOCKperiod" looses a full 7 bits of precision. I'll rewrite it to "(CLOCK_COUNT1 * CLOCKperiod) >> log2(AVG_CYCLES)", that should be a lot better.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2019, 09:24:55 pm
content: Results attached, approx. 1200 measurements for each strategy.pps128_mc_avg128.txt is 128 cycle averaging done by the TDC7200, formula corrected. Std dev 37.86ps. measurements are heavily quantized.pps128_soft_avg128.txt is 128 individual measurements averaged in software. Std dev 30.89ps The plot shows a slight drift even, so result might be better with all drift removed.

author: iMo
author_rank: Super Contributor
timestamp: December 29, 2019, 10:03:55 pm
content: Both look interesting.. No idea which one is better, howeverPS: added the original mathThe visible drift in the soft aver is around 20ps

author: FriedLogic
author_rank: Regular Contributor
timestamp: December 30, 2019, 08:02:50 am
content: Quote from: imo on December 29, 2019, 06:25:07 pmAveraging might not work well with an actual GPS since there will normally be phase jumps on a 128Hz (or any other frequency) output from the ublox. The 48MHz clock is not exact, so the GPS will add or remove a clock cycle every so often to keep it close to correct.The 48MHz on the M8N that I have is about 0.25PPM off, so that effectively means about twelve 20.8ns phase jumps a second.Somewhere on the Leapsecond.com site there was a comparison of GPSDO performance with different measurement resolutions. In that case there was surprisingly little difference between measuring the GPS to different resolutions, although it may make a bit more difference with a newer GPS.It should be possible to do a lot of separate measurements and identify jumps, but I doubt that it would be worth doing.The 1PPS with quantization error message is probably as good as the GPS itself can work out the timing, and single measurements with a TDC7200 should normally be more than good enough to measure it.

author: thinkfat
author_rank: Unknown
timestamp: December 30, 2019, 02:15:16 pm
content: Temperature drift is anyway going to mess big time with picosecond scale measurements. I may have underestimated that effect. Currently I only have the built-in temperature sensor of the STM32. I'm trying to make use of it to at least counter the large room temperature swings caused by the house heating. But it introduces quite a bit of noise by itself.

author: Leo Bodnar
author_rank: Frequent Contributor
timestamp: December 31, 2019, 11:47:00 am
content: Even after quantisation correction there is about 1ns wobble left. On top of that there is residual phase wander as navigation solution tries to steer timepulse reference to selected time grid. And then there are known unknowns like what the hell Galileo is doing?It would be smart to budget in bound 1-2ns rms TP error even after all the corrections are done.LeoQuote from: FriedLogic on December 30, 2019, 08:02:50 am

author: thinkfat
author_rank: Unknown
timestamp: December 31, 2019, 08:17:27 pm
content: Some experimenting with temperature compensation, see the attached data set. I'm using the internal temperature sensor of the STM32.Format:Col.1: uncorrected TOF, 128PPS, TDC multi-cycle averaging with 128 samples.Col.2: picoseconds added to TOF for temperature correctionCol.3: temperature compensated TOF.Col.4: temperature measured by the STM32 internal sensor, scaled according to the datasheet to °C. Not sure about the absolute value, you can pretty much disregard this column.

author: iMo
author_rank: Super Contributor
timestamp: December 31, 2019, 08:34:38 pm
content: How did you compensate (the math)?

author: thinkfat
author_rank: Unknown
timestamp: December 31, 2019, 08:42:48 pm
content: Simplest possible linear equation. Raw ADC value times magic value added to the TOF.

author: iMo
author_rank: Super Contributor
timestamp: December 31, 2019, 09:04:35 pm
content: It went from 323ps/C to 15ps/C.

author: thinkfat
author_rank: Unknown
timestamp: December 31, 2019, 11:32:04 pm
content: Maybe a bit worse, I need to check the temperature conversion formula, I might have to scale the ADC value differently.EDIT: I checked, the scaling is correct. So just the absolute temperature is unknown since I cannot check the actual die temperature, obviously

author: thinkfat
author_rank: Unknown
timestamp: January 01, 2020, 10:12:30 pm
content: Started implementing ublox binary protocol parsingLooking at the LadyHeather protocol decoder makes my eyes bleed..

author: texaspyro
author_rank: Super Contributor
timestamp: January 02, 2020, 03:15:01 am
content: Quote from: thinkfat on January 01, 2020, 10:12:30 pmIt's actually pretty simple once you get used to it. It might take a couple of weeks of Ebola sized orifice leakage to get there. Any Ublox decoder will do the same basic sequence of events.Step 1: capture a Ubox message (from start code to end code) into a bufferStep 2: get the message type code from the buffer and call the routine to decode that messageStep 3: use tsip_byte, _word, _dword, _single, _double to get values from the message

author: thinkfat
author_rank: Unknown
timestamp: January 02, 2020, 06:11:54 am
content: Thanks a lot for the encouraging words. The saving grace: I'll initially not need a lot of different messages. I just need to configure the receiver to output a 128PPS signal and then parse the TP messages as they come in for sawtooth correction.

author: iMo
author_rank: Super Contributor
timestamp: January 02, 2020, 07:24:38 am
content: FYI - I've been using this lib:https://github.com/loginov-rocks/UbxGpsThis works without any library:Code:// setting NEO-7 1PPS freq// an example only, provided as-is// stm32duino on BluePill by iMo 01/2020#define GPS_SERIAL Serial1// Send an UBLOX packet to the NEO receiver - change 1PPS to ppsfreq Hzvoid ubloxsetPPS(uint32_t ppsfreq){// CFG-GNSS packetuint8_t packet[] = {0xB5, // sync char 10x62, // sync char 20x06, // class0x31, // id0x20, // length0x00, // length// LSB----->MSB0x00, 0x01,0x00, 0x00,0x0F, 0x00, // antenna delay 15ns (3m)0x00, 0x00, // RF group delay0x01, 0x00, 0x00, 0x00, // 1Hz when not locked// 0x00, 0x1B, 0xB7, 0x00, // when locked 12MHz 1PPS example(ppsfreq & 0xFF),((ppsfreq >> 8) & 0xFF),((ppsfreq >> 16) & 0xFF),((ppsfreq >> 24) & 0xFF),0x00, 0x00, 0x00, 0x80, // duty cycle 50%0x00, 0x00, 0x00, 0x80, // duty cycle 50%0x00, 0x00, 0x00, 0x00, // user time-pulse delay0x6F, 0x00, 0x00, 0x00, // config flags0x00, // CK_A dummy0x00 // CK_B dummy};sendUbxPacket_crc(packet, sizeof(packet));}// Send the packet specified to the receivervoid sendUbxPacket_crc(uint8_t *packet, uint8_t len){uint8_t ck_a = 0;uint8_t ck_b = 0;for (uint8_t i = 2; i < len-2; i++) {ck_a += packet;ck_b += ck_a;}packet[len-2] = ck_a;packet[len-1] = ck_b;for (uint8_t i = 0; i < len; i++) {GPS_SERIAL.write(packet);}}

author: thinkfat
author_rank: Unknown
timestamp: January 02, 2020, 09:25:55 am
content: Quote from: imo on January 02, 2020, 07:24:38 amEeek! No, thanks. That ishideous. Poking bytes into a C++ object with (char*). Nope, not on my watch. texaspyro's coding style is maybe a bit on the odd side, but at least he's sane.Quote from: imo on January 02, 2020, 07:24:38 amMUCH better

author: iMo
author_rank: Super Contributor
timestamp: January 02, 2020, 09:49:06 am
content: Also mind the output 1PPS frequency with NEOx modules is not corrupted (jittery phase) only when1PPS_freq = 48MHz/N, where N=4,5,6... (N is an integer).That means 10MHz is crappy.

author: thinkfat
author_rank: Unknown
timestamp: January 03, 2020, 12:41:06 pm
content: Stuff is coming together. I can switch the receiver to ublox binary mode, configure the PPS output and start a self-survey. PPS signal is nice and steep, somewhere in the region of <4ns rise time. Here ends what my scope can resolve. I can also parse a couple of common messages, like, clock, nav, tp, svin, status, etc. I think that's enough for now.With the TP message I should be able to perform sawtooth correction, but then of course I can forget about the 128PPS averaging. I'll probably try both and post some data.PS: not convinced that 128PPS is a good idea, I took a look with the scope and I see very frequent 20ns jumps from pulse to pulse.

author: iMo
author_rank: Super Contributor
timestamp: January 04, 2020, 11:43:05 am
content: The NEOs 1PPS is not jitter free. See Lars' thread - the peak to peak jitter with 1PPS (1Hz) is perhaps 50ns.PS: With NEO's 1PPS output you may see two effects:1. the "GPS" related jitter, up to 50ns p-p at 1Hz (or similar with 128Hz), the NEO-M8 datasheet says the timing pulse accuracy is 30ns RMS2. the 1PPS "frequency divider" jitter, when the output frequency is set such the N is not an integer, ie. for 10MHz output freq the N=4.8

author: thinkfat
author_rank: Unknown
timestamp: January 05, 2020, 08:17:44 pm
content: First real world measurements, logfile attached. The measurement data has not changed format, it's just intermixed with log messages from the ublox parser.You can just filter out all lines starting with '#' to have the raw measurements.Conditions:10MHz from the Siglent wavegen. This instrument is externally clocked from a GPSDO.128PPS from the Ublox M8T128 cycle averaging done by the TDC7200You can see from the temperature compensation data that there wasn't much going on, pretty much thermal equilibrium, no large swings at least.The phase measurement data shows at least three components, small jitter on top of larger oszillations on top of a very significant 4500 or so second cycle. My interpretation is that the large 4500s cycle is the GPSDO at work, the small jitter is the TDC7200 granularity and the system phase noise (wavegen, squarer, ...), the larger oszillation is from the Ublox GPS module.

author: thinkfat
author_rank: Unknown
timestamp: January 05, 2020, 08:43:08 pm
content: Doing a bit of processing, attached find the 3rd column filtered through a very steep 1/200Hz high-pass. This very much eliminates the influence of the GPSDO (I assumed the time constant is 200s). The standard deviation of the resulting signal is in the range of 2.9ns. I think that's roughly what one can expect from the Ublox receiver. Note that the measurement was done after the GPS entered "Hold" mode.

author: iMo
author_rank: Super Contributor
timestamp: January 05, 2020, 09:08:25 pm
content: From the first data set the p-p is 13.8ns, it may fit into the M8T's "time pulse jitter +/- 11ns".

author: thinkfat
author_rank: Unknown
timestamp: January 05, 2020, 09:18:02 pm
content: I'm currently doing another test run, this time with the Ublox doing 1PPS output. Not doing sawtooth correction, the pattern is clearly visible if you plot the raw data. I'm logging from cold start of the system to have a comparison between the receiver in 3D mode while performing the self-survey, and in HOLD mode after the survey completes.PS: decided to stop the test and implement sawtooth correction instead, I'm anyway logging the uncorrected ToF and so the difference will become immediately apparent.PPS: see attached plot:top left, uncorrected tofbottom left, tof corrected for temperature and quantization errortop right, temperature correction in picosecondsbottom right, internal temperature sensor of the STM32.

author: iMo
author_rank: Super Contributor
timestamp: January 05, 2020, 11:43:48 pm
content: How did you correct for the quantization error?PS: FYI - a guy with a hydrogen maser in his bedroomhttp://www.efos3.com/index.html

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2020, 06:22:04 am
content: Quote from: imo on January 05, 2020, 11:43:48 pmThat's actually pretty simple. The TP message from the receiver tells you the quantization error in picosecondsfor the next timepulse. So I just store the "qErr" and when the next 1PPS measurement is completed, I just subtract the stored value from the measurement.

author: texaspyro
author_rank: Super Contributor
timestamp: January 06, 2020, 06:37:55 am
content: Quote from: thinkfat on January 06, 2020, 06:22:04 amWell, that is not alway true. Depending upon the receiver you either add/subtract the value to the previous/current/next PPS/phase measurement... that's like 12 different possibilities. Figuring out what the proper combination to use can be a pain in the ass. Some wrong combinations can look a lot like the proper one.

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2020, 07:27:06 am
content: Quote from: texaspyro on January 06, 2020, 06:37:55 amThe relationship between the TP message and the time pulse is documented for the M8T.

author: texaspyro
author_rank: Super Contributor
timestamp: January 06, 2020, 07:29:21 am
content: Quote from: thinkfat on January 06, 2020, 07:27:06 amIt's one of few that document it (or document it properly).

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2020, 09:15:09 am
content: Quote from: texaspyro on January 06, 2020, 07:29:21 amYep, their integration documents and firmware manual are really well done. I was able to design the small breakout board for the M8T looking into just one PDF and it worked right from the first revision. Moreover, the firmware behaves quite exactly as described in the documentation, which is a rare thing, too.Also, I'm not trying to reimplement LadyHeather, for me it's enough if the thing works with just one particular GPS.

author: iMo
author_rank: Super Contributor
timestamp: January 06, 2020, 09:34:50 am
content: Would be interesting to see (after you finalize your GPSDO) how the quant_err correction helps when you do 500-1000secs PID loop averaging (ie. MADEV with and without).It is my understanding the "sawtooth correction" and the "quantization error correction" is the same.

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2020, 10:41:06 am
content: Quote from: imo on January 06, 2020, 09:34:50 amYep, that's also my understanding. The "quantization error" reported by the receiver is the offset in picoseconds of the TIMEPULSE signal, which is aligned to the best fitting clock edge of the internal clock, to the true time mark calculated by the receiver. The "sawtooth" is the visual pattern that you get in the phase measurements if you compare the TIMEPULSE signal to a more stable reference source.The expression of the quantization error in picoseconds is especially convenient since the correction then becomes a simple addition. You just need to figure out the sign correctly, i.e. understand what the receiver is actually reporting. In the ublox case, anegativeqErr means the true timepulse is abs(qErr)earlierthan the TIMEPULSE signal, that means you need toaddabs(qErr) to the measurement. In other words, you just add -qErr to the measurement and you're set.Anyway if you get the sign wrong, the effect is immediately visible in that the "sawtooth" gets much, much more pronounced instead of it disappearing.

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2020, 08:50:59 pm
content: Another interesting dataset, this is the future oscillator for the GPSDO, one of my LPRO-101 Rb standards.As expected, a completely different picture, this is a free-running oscillator against the 1PPS signal from the Ublox receiver. The up- and down movement from the previous data sets, that were still using the GPSDO as the reference are gone. The measurements were started as soon as the Rb steering loop locked, so you can see it warming up and the curve gradually become more and more linear. It looks like there is still a slight curve after 12000 seconds.

author: iMo
author_rank: Super Contributor
timestamp: January 06, 2020, 11:21:21 pm
content: It would drift 1 second in around 800 years

author: thinkfat
author_rank: Unknown
timestamp: January 07, 2020, 08:45:31 am
content: The result of one night of data logged. The mdev graph suggests I will be able to run with a TC of around 4000 seconds or so, if I'm not mistaken.

author: iMo
author_rank: Super Contributor
timestamp: January 07, 2020, 08:50:00 pm
content: How are you going to control the LPRO's freq? Via EXT C-Field input? What is the LPRO's gain (in Hz/Volt)?

author: thinkfat
author_rank: Unknown
timestamp: January 07, 2020, 10:01:14 pm
content: Quote from: imo on January 07, 2020, 08:50:00 pmYes, external C-Field input. The LPRO-101 has a trimming range of at least 3 ppb over 5V, or 0.006Hz/V. "At least" because I only have a vague statement in the LPRO user manual about the trimming range:QuoteIf you look at the layout, the whole PCB is supposed to plug directly onto the front connector of the LPRO, running both from a single 24V power supply.

author: thinkfat
author_rank: Unknown
timestamp: January 09, 2020, 03:45:57 pm
content: Alright, almost roasted the board. I hooked the reset line of the DAC up to the wrong power rail, VDDA instead of VDD, and the DAC pulled VDD up to over 4V. That could have been a costly mistake, but luckily everything still works. I can talk to the DAC and set the output level. Next will be the Opamp, and then I will connect the LPRO and can finally start implementing the actual control loop.

author: iMo
author_rank: Super Contributor
timestamp: January 09, 2020, 04:16:14 pm
content: When printing the data into the .csv file put the #ublox messages at the end of a line such we not need to mess with excel's filterFingers crossed with your first lock!

author: bingo600
author_rank: Super Contributor
timestamp: January 09, 2020, 06:02:36 pm
content: Quote from: imo on January 05, 2020, 11:43:48 pmMagnus just got a "home maser" too/Bingo

author: thinkfat
author_rank: Unknown
timestamp: January 09, 2020, 06:15:46 pm
content: Quote from: imo on January 09, 2020, 04:16:14 pmI keep forgetting that you are not blessed by the powers of 'grep' 😁

author: thinkfat
author_rank: Unknown
timestamp: January 10, 2020, 06:48:38 pm
content: It locks!Took a while of fiddling with Lars' control loop code because my TIC delivers picoseconds rather than nanoseconds. I've thrown out a lot of code, too, the whole linearization stuff for the ADC TIC is not needed, and most of the code for changing and saving parameters, warm up handling, hold mode, temperature compensation etc. I'll have to reimplement later when I do the console command interface. It's really stripped down to the bare minimum PI loop, DAC handling.And immediately I start to wonder about the merit of having a PLL in a design that will not output a 1PPS signal and thus has no requirement for a fixed phase relation to the GPS, let alone UTC. Getting a phase lock is much more demanding that trimming the frequency so that the oscillator stops drifting. Especially since the input to the control loop is a phase error while the output is a frequency correction.

author: iMo
author_rank: Super Contributor
timestamp: January 10, 2020, 09:11:51 pm
content: The oscillator stops drifting when phase error is constant. How did you define phase lock?

author: thinkfat
author_rank: Unknown
timestamp: January 10, 2020, 09:23:40 pm
content: Quote from: imo on January 10, 2020, 09:11:51 pmIf you look at Lars' code, phase lock is defined by means of "TIC_Offset", with "TIC_Value - TIC_Offset" being the error input for the P_term of the PI loop. This steers the phase of the input towards a specific TIC_Value, i.e. towards a specific phase difference between the 1PPS and the oscillator signal. That's what I'd call "phase lock".An alternative could be to do mainly frequency locking, i.e. steering the "diff_ns", which describes the frequency error, towards 0.

author: iMo
author_rank: Super Contributor
timestamp: January 10, 2020, 09:44:54 pm
content: So your tic_offset is 1000ns and tic_value is say from 500ns to 1500ns. Thus "phase lock" will happen when abs(tic_value-tic_offset)<epsilon?

author: thinkfat
author_rank: Unknown
timestamp: January 10, 2020, 10:01:27 pm
content: Quote from: imo on January 10, 2020, 09:44:54 pmYep, that's pretty much it. Lars' code defines something like a "hunting" mode, during which there is no filtering applied to tic_value. This makes the loop very reactive and quickly steers it towards tic_offset, however the result is a lof of DAC movement. The switchover to "locked" mode is defined by "abs(tic_value-tic_offset)<epsilon" for a certain time (5 times TC). But the only thing that changes when a "lock" is achieved is the filter constant for tic_value, which is then set to e.g. TC/2. This slows down the loop response and instead of violent frequency changes you get slow up and down movements.However, the target is always to minimize "tic_value - tic_offset". This isn't really productive if you only care about frequency stability. A FLL should have an advantage here.

author: iMo
author_rank: Super Contributor
timestamp: January 10, 2020, 10:11:01 pm
content: Does the NeoM8T allow to set 10 messages per second (and 10Hz 1PPS) where you get the sawtooth correction data as well?FLL means you are measuring the frequency and adjust the DAC. How would you measure frequency with say 10uHz resolution?

author: thinkfat
author_rank: Unknown
timestamp: January 10, 2020, 10:34:31 pm
content: Frequency is the time derivative of phase. The TIC gives me phase difference in picoseconds and "phase - phase[t-1]" is the frequency difference in ps/s, if I'm not mistaken.So if I use, instead of "tic_value - tic_offset", "diff_ns", or rather "diff_ps" in my case, as the error value in the PI loop, I should get a FLL instead of a PLL.

author: thinkfat
author_rank: Unknown
timestamp: January 11, 2020, 06:15:39 am
content: Dataset of around 44000 measurements, including the "hunting" phase at the beginning. Lock achieved at about 5000s, usable values start at 6000s, I think.Mostly debug relevant output, I am still debugging the PI loop.TC: 1000sFirst column: raw TOF from the TDC in picoseconds2nd column: filtered TOF, scaled to 1ns. Take this with a grain of salt, the output is through a quite crude float-to-string function and probably has some rounding error.3rd column: diff_ps, low-pass filtered with a time constant of 16 seconds4th column: raw DAC values5th column: lock counter, starts counting when the locking criteria are met. When it reaches 5000, the TOF filter time constant is set to 500.DAC LSB: 4e-9 / 65536Note that I didn't yet qualify the true pulling range of the LPRO. I'm just assuming 4e-9, could be something else, but it's in the same ballpark.

author: iMo
author_rank: Super Contributor
timestamp: January 11, 2020, 07:48:55 am
content: Using only 200p-p lsb units off your 16bit DAC. BoringMADEV 2.2e-13 at 10k seconds.YourcompetitorPS: they use an additional "ultra low noise 10MHz Crystal Filter Oscillator".

author: thinkfat
author_rank: Unknown
timestamp: January 11, 2020, 09:26:56 pm
content: Quote from: thinkfat on January 10, 2020, 10:34:31 pmThought about the idea some more - ain't gonna work. Yes, I get the frequency difference by looking at the phase derivative, but I can only measure phase with finite precision and also there's numeric limitations. It's impossible to lock the frequency by just looking at "diff_ps". It will always drift. I need the phase lock as am anchor point.However, I can still use diff_ps as a differential term in the control loop. I'm going to experiment with that (PID instead of PI controller).

author: iMo
author_rank: Super Contributor
timestamp: January 12, 2020, 08:51:00 am
content: I think diff_ps is too noisy to be useful as the D in the PID.

author: thinkfat
author_rank: Unknown
timestamp: January 12, 2020, 01:35:33 pm
content: Quote from: imo on January 12, 2020, 08:51:00 amIndeed. I think it'd be better to go for a "classic" PID approach where D is the error derivative. It might also be interesting to work with different gains for the D term, to help it converge faster while it acquires lock.I also understood now the reason why it converges so slowly towards the phase setpoint: For convergence, it must first eliminate the frequency offset, i.e. it must first center the DAC around the proper setting. But since the control loop doesn't "know" that, it just keeps steering phase towards 1µs. But to align the frequency, it has to allow for a large phase shift first. Instead if constantly tries to adjust the phase towards the setpoint. It will eventually reach the setpoint, but it takes quite a while, especially for longer TC.

author: thinkfat
author_rank: Unknown
timestamp: January 12, 2020, 01:55:36 pm
content: The attached graphs are to illustrate the behavior. Look at especially the TIC values, diff_ns and Raw DAC graphsThe DAC starts out at around 33200, while the correct setting for frequency alignment is around 32200. The TIC graph consequently goes into a downward slope caused by the frequency offset.The control loop tries to counter that movement, notice all the small upwards movements back towards the setpoint. The system is following at first, but since the DAC excursions point away from the "good" value, it goes back into a downward trend away from the setpoint again. This continues until the DAC output finally reaches the "good" value. From this point on, frequency is aligned and you will see DAC excursions up and down while the phase is shifting slowly towards 1µs.This could be improved by introducing a "frequency search" at the beginning, with the control loop only looking at diff_ns to bring the DAC near frequency alignment. Once diff_ns (filtered, of course) stays within a certain range, strategy could be switched to phase locking.

author: iMo
author_rank: Super Contributor
timestamp: January 12, 2020, 02:24:23 pm
content: There is the PII loop as well, it could be it fits this scenario better. I have the C source somewhere, but it basically integrates twice in series.PS: aka PIID, or PI2D

author: iMo
author_rank: Super Contributor
timestamp: January 13, 2020, 09:29:06 am
content: I would not mimic Lars' code with your design. You may do all in double precision to be on the safe side with math. Also Lars is using a low pass in the DAC with much lower BW (yours DAC low pass is 147Hz, btw). Start with a PI regulator off a standard library and tune it for your system. It could be you have to smooth the TIC measurements first, and then pass the result to the PI loop (with say 10-100secs period).PS: As I wrote above your NEO can output messages at 10Hz afaik, with 10Hz 1PPS you may achieve better statistics, imho.PPS: from 5000secs up in your above data the DAC changes are max 1LSB, it could be the 16bit DAC resolution is still too "coarse"..

author: thinkfat
author_rank: Unknown
timestamp: January 13, 2020, 10:18:07 am
content: Quote from: imo on January 13, 2020, 09:29:06 amThat's exactly what I'm doing now. For the first test I have just taken Lars' PI loop and also the averaging filters, but I noticed quickly that there are e.g. terms in the averaging filter that didn't seem to have much merit, and then I looked at the PI loop computation itself and it seemed a little odd and it was a bit hard to match it with what you get from control theory textbooks. Frankly, I didn't understand it and since Lars' is no longer with us I cannot ask. Not a good starting point for experiments.Now I've implemented a "textbook" PID control loop, using this formula from the wikipedia page:It's nice because I get to set the time constant for the integrator (Ti) directly in seconds. Now I need to figure out a proper gain and boundaries for the anti wind-up of the integrator. This type of controller needs a bias term, which I have set to the middle of the DAC range for now, and the integrator is what adjust for frequency offset. So the anti wind-up has to be chosen with some sense to not have a huge overshoot if you start from a large phase error and at the same time deal with LPRO's that are not well calibrated. My own one I have carefully set to 10MHz with the C-Field bias pot, looks like I'm still a little off from center position but it's not a huge amount and the integrator is coping with it.I've also switched to using "double" instead of "float" and the "remainder" trick.PS: if the DAC range is too coarse, I can solve that in the analog output stage. I have a second OP that I could use to create a virtual ground to bias the output amplifier. I've meanwhile checked the pull range of the LPRO, it's indeed 4ppb rather than the 3ppb advertised in the user manual.PPS: DAC low-pass filter - there's a 100/ 10nF RC low-pass at the OP output. That matches with the 147Hz.

author: iMo
author_rank: Super Contributor
timestamp: January 13, 2020, 10:25:35 am
content: QuoteYou may offset the middle of the DAC around the expected 10MHz, and set the opamp gain to -10 for example, thus you get +/- 0.25V around a set point, with 16bit resolution (7.6uV per LSB, the area where TC and noise start to matter, btw).QuoteLook at the above simulation (off the LPRO EXT C input schematics), the 147Hz comes rather from the internal RC stuff.

author: thinkfat
author_rank: Unknown
timestamp: January 13, 2020, 12:53:58 pm
content: Quote from: imo on January 13, 2020, 10:25:35 amHm. The DAC LSB is, as I mentioned, 4ppb / 65536, that's about 6e-14, or 60ppq. That's the minimum disturbance it can cause. It's also roughly 76µV in the current setup. Should I really worry? I'd say there are other disturbance sources that are in the same ballpark. Not sure the overall noise level of the whole thing justifies that change.

author: thinkfat
author_rank: Unknown
timestamp: January 15, 2020, 09:52:46 am
content: Quote from: thinkfat on January 13, 2020, 12:53:58 pmI think I've worked all the necessary corrections into the hardware design now. The layout is done, I'll launch the PCB soon. I've added provisions to limit the DAC pulling range, too. Thinking about it, I did put a lot of effort into getting a clean output, with separate analog ground, point-of-load regulators for the DAC and the output amplifier etc. It'd be a shame to stop there without at least providing means to tune the performance.Another aspect I've been working on is the control loop. I've been reading up on PLL design and especially on using a PID controller for a PLL. One interesting aspect is that the models always contain a frequency component in the error term. So I'm experimenting with using the diff_ps (of course filtered) as an additional input. Not in the sense of a derivative term, but when calculating the error input. It definitely helps the loop converge faster, at the same time it adds some short-term fluctuations which mess a little with the Sigma for small Tau (1Hz).Man, there are really a lot of knobs to twiddle. It's a neverending game.

author: iMo
author_rank: Super Contributor
timestamp: January 15, 2020, 09:57:26 am
content: What kind of low-pass filtering of the TIC output do you use?

author: thinkfat
author_rank: Unknown
timestamp: January 15, 2020, 10:46:25 am
content: Quote from: imo on January 15, 2020, 09:57:26 amSliding window average, I think. I've more or less reused Lars' code here. In pseudo-C it is:tic_filtered += (tic_measured * time_constant - tic_filtered) / time_constantIt's updated with every new measurement, once per second.tic_filteredis scaled by time_constant, preserving the bits added by the averaging.time_constant is in the 100 seconds range.

author: iMo
author_rank: Super Contributor
timestamp: January 15, 2020, 11:03:45 am
content: QuoteThat is somehow modified EMA (exp moving average):tic_filtered = tic_filtered + alpha * (tic_measured - tic_filtered),alpha = 1.0 - exp(-1.0/fs/tau), where "fs" is the sampling frequency , and "tau" is the time constant .You may get "alpha" for a specific -3db corner frequency "f3db":omega3db = f3db * pi/(fs/2),alpha = cos(omega3db) - 1 + sqrt(cos(omega3db)^2 - 4*cos(omega3db) + 3)https://dsp.stackexchange.com/questions/40462/exponential-moving-average-cut-off-frequency

author: thinkfat
author_rank: Unknown
timestamp: January 15, 2020, 01:10:41 pm
content: It's a MMA, if you look at the step response. Wikipedia says MMA is EMA with alpha = 1/N.See this octave/matlab script:Code:## Step response of Lars' low-pass filter#clf;format long;hold off;tc = 10;acc = 0;# larsfor i=1:5*tcacc = acc + (1 * tc - acc) / tc;y(i) = acc / tc;end# mmaacc = 0;for i=1:5*tcacc = ( acc * (tc-1) + 1) / tc;y2(i) = acc;endplot(y);hold on;plot(y2);plot(y2-y);grid on;

author: iMo
author_rank: Super Contributor
timestamp: January 15, 2020, 06:15:40 pm
content: Lars is doing with integers - therefore the MMA. You may do with simple EMA and double precision.PS: I would try with cascading EMAs - two EMAs cascaded with shorter tau could have better effect than a single EMA with longer tau.Also a rolling median works nice for eliminating outliers (in TIC output for example).

author: thinkfat
author_rank: Unknown
timestamp: January 16, 2020, 08:22:52 am
content: Some more data from yesterday.integrator time constant: 4000sFirst column: raw TOF from the TDC in picoseconds2nd column: filtered TOF, scaled to 1ns.3rd column: diff_ps, low-pass filtered with a time constant of 120 seconds (Lars' MMA)4th column: raw DAC values5th column: Smoothed DAC, Lars' MMA with 64 seconds time constant6th column: P_term of the PI loop7th column: I_term of the PI loop8th column: lock counter, starts counting when the locking criteria are met.9th column: loop state, 2 means "locked"

author: thinkfat
author_rank: Unknown
timestamp: January 17, 2020, 07:23:15 am
content: I've been doing some work on the software, mainly implementing the ideas I had floating in my head around improving the startup time until locking. I've come back to using the frequency drift information indiff_psto first find a low drift DAC value for the PI loop to start from. So there's a first state in which a coarse frequency search happens until the drift is within a certain margin for 240 seconds.This creates a pretty hefty offset in the phase error, so after finding a suitable zero state, it very aggressively steers the phase error down to zero, mainly by setting the loop gain very, very high. It's not actually "bang-bang", but it comes close for large phase errors. The main goal in this state is to allow the integrator of the PI loop to center the DAC more finely around the zero-drift value. If the phase error is small enough for an extended amount of time, the control loop moves to "locked" state, which sets the gain back to normal and switches to a larger filter time constant for the TIC measurements.The advantage is mainly a faster time-to-lock and also, since the DAC is already well biased when the loop enters lock state, there's less initial turbulence and the system is usable more quickly.I'll post data as soon as I can gather enough measurements.

author: thinkfat
author_rank: Unknown
timestamp: January 18, 2020, 10:00:37 am
content: Quote from: imo on January 10, 2020, 10:11:01 pmI've tried with 10Hz measurement rate and 10PPS. I loose coherence between the TP message and the 10PPS pulse, it seems. I've tried increasing the baud rate to the maximum the M8T supports, but I still get huge outliers. 5Hz seems to work fine, though.

author: thinkfat
author_rank: Unknown
timestamp: January 18, 2020, 06:39:43 pm
content: There is an interesting regularity in the data. Every 4000 seconds or so, the phase jumps by 10ns. At first I though it's some GPS effect, but 10ns is suspiciously one 10MHz clock period. The TDC gets a 500kHz signal derived from the 10MHz clock, which has a much longer period, but of course it gets the same 10MHz as a reference clock for its cycle counter.Any idea about how to counter that? It causes some unrest in the regulation because the control loop will of course try to reach 1µs phase offset again.It is what limits the stability in the MDEV graph to around 2.5e-12 or thereabouts, for Tau=2000s.

author: iMo
author_rank: Super Contributor
timestamp: January 18, 2020, 07:12:20 pm
content: Quote from: thinkfat on January 18, 2020, 06:39:43 pm10ns is period of 100MHz.

author: thinkfat
author_rank: Unknown
timestamp: January 18, 2020, 07:18:57 pm
content: Quote from: imo on January 18, 2020, 07:12:20 pm

author: iMo
author_rank: Super Contributor
timestamp: January 18, 2020, 07:26:25 pm
content: Could it be math? Rounding? More than 15digits precision?I would get rid of any integer math. Only double precision (15digits only).Sometimes 64bit integer math is required, ie. (32bit * 32bit) / 32bit is not the same as 32bit * (32bit / 32bit) , etc.

author: thinkfat
author_rank: Unknown
timestamp: January 18, 2020, 09:04:02 pm
content: Quote from: imo on January 18, 2020, 07:26:25 pmI'll take a look at the TDC library again. They're doing some scaling tricks with shifting integers up and down to do fixed-point math (Q44.20). You mentioned though, you've used this library already. My own code is entirely converted to floating point now. I do use some "float", though. I should take a closer look and maybe switch everything to "double".

author: iMo
author_rank: Super Contributor
timestamp: January 18, 2020, 09:21:54 pm
content: I was using the 7200 lib in a pretty noisy setup. Cannot confirm it works 100%.Your setup is much better so you may discover even quite subtle bugs.Make a version with double (55ps is well within 15digits) with straight datasheet math and compare against the integer math.What is the clock of your stm32?

author: thinkfat
author_rank: Unknown
timestamp: January 18, 2020, 10:17:01 pm
content: Quote from: imo on January 18, 2020, 09:21:54 pm48MHz. Should be plenty MIPS.

author: thinkfat
author_rank: Unknown
timestamp: January 19, 2020, 08:12:28 am
content: I've meanwhile ordered a couple of OCXOs. The next project, which I have already started in the background, will be a GPSDO cape for the Beaglebone Black. Could be quite nice to run visualization directly on the platform, Lady Heather style.

author: bingo600
author_rank: Super Contributor
timestamp: January 19, 2020, 10:13:37 am
content: Quote from: thinkfat on January 19, 2020, 08:12:28 amWhy a BBB , and not a RasPi / Odroid or ??Are you planning to use the PRU's for some realtime macic ??/Bingo

author: thinkfat
author_rank: Unknown
timestamp: January 19, 2020, 10:29:58 am
content: I think I understand Lars' PI loop now. It's not weird, it's actually a quite clever optimization, though I'm not sure if he didn't make a mistake somewhere with scaling.This is a standard PI computation in pseudo-C (loop time 1 second):Code:error = target - measurement;Integrator += error;P = error;I = Integrator / TimeConstant;dac_out = bias + ( P + I ) * gain;The multiplication withgainis what scales the PI result to DAC units,biasis in DAC units by definition.Now,Integratorandbiasare the same thing andbiascan be in fact become the integrator, by adding the following code after each loop:Code:bias += Integrator * gain / TimeConstant;Integrator = 0;So, after each loop you move the content of theintegratorintobiasand reset it to 0. Now, of course Integrator now doesn't sum anything any more, so, logically, this becomes:Code:error = target - measurement;P = error;I = error / TimeConstant;dac_out = bias + ( P + I ) * gain;bias += I * gain;Now,dac_outis of course:Code:dac_out = bias + P * gain + I * gain;That means you can rewrite the loop as follows:Code:error = target - measurement;P = error * gain;I = P / TimeConstant;dac_out = bias + P + I;bias += I;And a final, clever optimization brings us to Lars' PI loop:Code:error = target - measurement;P = error * gain;I = P / TimeConstant;bias += I;dac_out = bias + P;Really, Lars' was quite a smart guy.PS: no, there's no scaling error in Lars' code.PS2: edited for clarity

author: thinkfat
author_rank: Unknown
timestamp: January 19, 2020, 12:36:37 pm
content: Quote from: bingo600 on January 19, 2020, 10:13:37 amNo plans for the PRU, I just don't think it needs a power house (literally, the thing runs _hot_) like the RasPi to run a program that an STM32 can easily cope with. An ARM Cortex-A8 at 800MHz is plenty oversized already, and much more power conservative than a quad core 64bit A53.

author: thinkfat
author_rank: Unknown
timestamp: January 19, 2020, 04:57:43 pm
content: Quote from: imo on January 18, 2020, 07:26:25 pmI think I found something:The pattern here looks suspicious. I think there's a numerical problem in the filtering of the raw DAC values. I've disconnected the temperature compensation for now to check if the effect goes away.It's a MMA implemented in recursive form:Code:temp_filt = (31 * temp_filt + temp) / 32temp_filt is just a 32bit signed int. I bet there's something overflowing, not properly rounding, something.

author: thinkfat
author_rank: Unknown
timestamp: January 20, 2020, 08:32:15 am
content: I'm probably looking at an environmental effect. During the night, without any disturbance, after the room had cooled, no more events. When I entered the room in the morning, I could immediately see a disturbance in the temperature sensor plot. Shortly after, the amplitude of DAC movement increased. The temperature sensor was only recorded without compensation being applied.PS: the internal temperature sensor of the STM32 is rubbish. It is way too noisy and shows the power consumption of the chip more than anything else. I'm adding an MCP9800 to the new board.

author: thinkfat
author_rank: Unknown
timestamp: January 20, 2020, 04:06:21 pm
content: Alright. Rev2 boards are go. I ordered 3 from Aisler, and decided to get adventurous on another two: I'll be trying JLCPCBs PCBA service. Of course they don't stock the majority of the parts I want, but they will assemble most of the passives, the STM32 and some SOT-23 diodes. Also, the TCL2272. I'll have to assemble the rest myself, they don't have any TSOP or MSOP parts in their library at all. I figure they lack the precision to place those?

author: thinkfat
author_rank: Unknown
timestamp: January 21, 2020, 05:21:34 pm
content: plus=PS: What I meant to say is, it doesn't make sense to do any performance evaluation or look for bugs in the software with this rag-tag setup. It's just too susceptible to all forms of disturbance. The light bulb is one of those LED filament lamps. There's not much in it electronically, but it seems to radiate quite a bit of noise at 100Hz, which is happily picked up by the wiring. I noticed a huge dip in phase error when I switched it on. Also, I noticed that the regulator output is way more quiet when nobody is in the room. But it's not temperature - there is almost no sign of any temperature dependence in the phase movement. But whenever I'm in the room, so is my smartphone...

author: thinkfat
author_rank: Unknown
timestamp: January 28, 2020, 12:39:13 pm
content: Quote from: thinkfat on December 29, 2019, 10:22:29 amWhile waiting for the PCBs to arrive, I was meanwhile able to resolve this issue: Apparently, you need to manually sync the two channels. On the SDG2042X this is done through "Utility -> Output Setup -> EqPhase". After selecting this, the two channels are in phase.Quote

author: thinkfat
author_rank: Unknown
timestamp: February 03, 2020, 09:37:01 am
content: The Rev2 PCBs arrived before the weekend and I've started populating the different sections. So far, the input circuit with reversed-polarity and overvoltage protection checks out OK and I've populated and tuned the sine-to-square circuitry.Looks good so far, though probing the hot end of the inductor turned out to be a little difficult, the 1-2pF probe capacitance is enough to detune the tank. I ended up probing it indirectly, by reducing the input signal until it stopped working and then tuning the tank circuit until it worked again. I get a nice 50% duty cycle square wave from a 1Vpp sine input. I chose a fixed 0805-sized inductor with Q=75, seems to work out OK.Tiny mishap: I changed the footprint of the 74AC04 to TSSOP-14 and forgot to order them. But I managed to fit the previous SSOP-14 version onto the board with some fiddling.On the software side I spent some time working on the command interface and overall cleaning up. I'm running out of flash memory, though. I had to reimplement several standard functions like "strtod" because their library equivalents pull in waay to much stuff that isn't needed. Using double precision floating point math takes its toll, too.

author: iMo
author_rank: Super Contributor
timestamp: February 03, 2020, 11:09:52 am
content: I've been working with pic32MZEF these days - double precision FPU and 512kB sram, 2MB flash, 200MHz - just an idea for your 3rd board revisionhttps://majenko.co.uk/product/chipkit-pro-mzPS: another way how to tune sensitive LC circuits is to make a small "sensing coil", say 2-3turns 15-20mm dia. It loads the LC less than a direct coupling with a capacitor. And no problems with grounding. Keep 2-3cm off the LC.

author: thinkfat
author_rank: Unknown
timestamp: February 03, 2020, 11:27:24 am
content: I have some hope that I don't need to make another revisionBut we know, in war truth dies first and in crisis, hope dies last

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 12:07:43 pm
content: OK, some first results with the new design: The input squarer is giving me a bit of a headache right now. The duty cycle of the output varies a lot with the input signal level. Not sure how much this affects the TDC, but the recommended duty cycle for the reference clock is 50%. I have more like, 60% at the moment. Apart from that it seems to behave well.Schematic for the Sin2Square attached. I'm wondering if I should maybe change R15/R12 to something smaller, 10k maybe.

author: iMo
author_rank: Super Contributor
timestamp: February 04, 2020, 12:17:29 pm
content: I would use the R6=50-100ohm as I recommended in past. And remove R14.PS: the choice of the inductor is important. In ltpsice lib I can see 0805 10uH with 2ohm series and 980ohm parallel eq resistance. That would not work. On the other hand there is a 1210 one with 0.5ohm series and 19k parallel eq. resistance which simulates nice (and it will work fine). With properly tuned LC (and say 1Vpp input) you have to see "almost squared" rail-rail signal at the input of the HC14.

author: Miti
author_rank: Super Contributor
timestamp: February 04, 2020, 12:18:52 pm
content: Make R15 49K series with a 5K trimmer. I experimented with this squarer an the DC bias needs to be adjusted for a 50% duty cycle.

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 01:05:39 pm
content: Quote from: imo on February 04, 2020, 12:17:29 pmHm. R14 is to force the input impedance to 50\$\Omega\$, that's what the LPRO expects to see at its output.I probably misunderstood what R6 in your recommendation was supposed to be: I thought it's the output impedance of the signal source, and since the LPRO has 50\$\Omega\$ there, I replaced it with a bridge.Quote from: Miti on February 04, 2020, 12:18:52 pmOK, worth a consideration. But wouldn't using a lower impedance for the voltage divider also be effective?

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 01:13:17 pm
content: Quote from: imo on February 04, 2020, 12:17:29 pmThe inductor is a TDK MLF2012E100KT. Datasheet:https://www.tme.eu/Document/7c2ace17599f4cca5c72e8cba8620a08/mlf2012.pdf

author: iMo
author_rank: Super Contributor
timestamp: February 04, 2020, 01:18:12 pm
content: The adjusting the R divider with the pot trimmer is not important. It is needed only when your LC tank is low Q and the entire circuit works as a squarer "without LC". With good LC and tuned your signal at the input of the HC14 is rail-rail with 1Vpp input.Let R14 there but add the R6=50.

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 09:31:43 pm
content: Awright. I think I have to postpone the LC tuning a bit. I'm pretty sure I don't have Q enough in the tank to really drive the signal into a square wave, besides, even with 10 Vpp from the wavegen the input of the inverter doesn't saturate. No input protection diodes? Adding a series resistor (R6=50\$\Omega\$) didn't bring any improvement.I have a few other loose ends to tie, the new PCB has a temperature sensor now and a small EEPROM which I'll use to store some parameters. So, temperature compensation and persistent storage next.For the LC tank I'll probably have to prototype it separately. The small-ish PCB doesn't give itself easily to probing and changing components.PS: it's surprisingly difficult to find a high-Q fixed inductor with sufficiently high SRF. Will I really end up winding enamel wire around a core?

author: iMo
author_rank: Super Contributor
timestamp: February 04, 2020, 09:58:10 pm
content: With the worst inductor I've found and your 10Vpp input signal, and both R6 and R14 populated (the diodes do simulate the input clamping diodes of the HC14) you should see pretty saturated input of the HC14.PS: be careful with large powers into the input - with 10Vpp input the currents via those diodes are 5-10mA p-p based on the quality of L.

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 10:27:35 pm
content: Quote from: imo on February 04, 2020, 09:58:10 pmYep, I should, yet, I don't. No clamping action, even though the voltage is high enough for sure. It definitely exceeds Vdd. For now, postponed.This is the inverter:https://www.tme.eu/Document/7b82005d5898e252126b82e3df8b07b1/NC7SZ04M5-DTE.pdfNo Schmitt trigger input, btw. Shouldn't matter.

author: iMo
author_rank: Super Contributor
timestamp: February 04, 2020, 10:34:41 pm
content: What is DC voltage at the 04 input (no signal at input)?Are your resistors of the right value?Isn't your input capacitor shorted?

author: thinkfat
author_rank: Unknown
timestamp: February 04, 2020, 10:47:54 pm
content: Quote from: imo on February 04, 2020, 10:34:41 pmInput voltage is 1.6V. Resistors check out OK, too. The input cap - I'll have another look. Might also play with C35. Maybe I'm just not hitting the resonance.PS: still not getting why R6 should be there and 50\$\Omega\$. I checked the values with a RLC filter calculator (http://sim.okawa-denshi.jp/en/RLCtool.php), all R6 does is limit Q to about 12.

author: iMo
author_rank: Super Contributor
timestamp: February 04, 2020, 10:56:23 pm
content: Also the mid of the resistor divider (creating those 1.65V DC) must be AC blocked (the 100nF capacitor) to GND. Otherwise the LC tank will not work.

author: thinkfat
author_rank: Unknown
timestamp: February 06, 2020, 10:00:49 pm
content: No LT-Spice here on Linux, but KiCAD has a bridge to "ngspice". I've collected a model for an HC04 inverter, added two 1N4148 (model from Diodes Inc.) for input clamping and made up an inductor model from manufacturer data (TDK supplies all necessary values).I agree, it should work. I don't see a strong influence of the series resistor, though (R6 in my schematic). It just limits Q of the tank. Best result (highest gain) with R6=0 Ohm. Spice library and netlist attached.PS: I'm wondering if the 100nF AC block (C33 in my schematic) should better be something with a higher Q. I might replace it with a 1nF C0G/NP0.

author: iMo
author_rank: Super Contributor
timestamp: February 09, 2020, 11:14:37 am
content: A variant with an old school RF transformer. Good for galvanic decoupling of the source.PS: an off the shelf "10.7MHz IF transformer" could be a good candidate in this case.

author: thinkfat
author_rank: Unknown
timestamp: February 09, 2020, 12:10:30 pm
content: Thanks. Could you provide a Bode plot from 1MHz to 100MHz?

author: iMo
author_rank: Super Contributor
timestamp: February 09, 2020, 12:15:23 pm
content: AC sweep.PS: the L1 L2 C1 values are shown as an example, it could be a different value such it tunes at 10MHz (I would not go below 10uH).Another option is a small Amidon Red toroid - ie. T30-2, 10uH=48t, 0.05uH=3t.

author: thinkfat
author_rank: Unknown
timestamp: February 10, 2020, 04:41:45 pm
content: I've been playing with the GPSDO simulator from LeapSecond.com. I'm lacking the oscillator data for a typical rubidium frequency standard, though.Of course I can always "fake" it by assuming a "no drift, no jitter" oscillator, but that's probably not realistic enough?The GPS data set is 400000 seconds long, so I though about creating an oscillator file that would just simulate the drift over 400000 seconds, like with the following matlab script:Code:for i=0:400000-1;osc(i+1) = (i/400000-1)**2 * -1e-13;endThis would describe an oscillator that drifts -1e-13 Hz over 400000 seconds, on a quadratic slope. I don't know if that'd be close enough, but probably better than just assuming zero drift and jitter.PS: got a data file from Tom van Baak (Leapsecond.com) from a PRS10. Should be fine to get me going.

author: thinkfat
author_rank: Unknown
timestamp: February 15, 2020, 02:07:40 pm
content: I'm often hearing about using a Kalman filter for a GPSDO, and while I can see a merit with GPS positioning and navigation, I can't quite see how it would be useful for a GPSDO. What's the general idea here? For a Kalman filter, you need a prediction model and multiple, preferably independent data sources.For example, in positioning, the GPS computes a position, a velocity and a direction independently. Velocity and direction can be used to predict the next position, improving precision.I don't quite see how this would work for a GPSDO, where my only input is the phase measurement. How would the prediction model look like? The only idea I have there is using the output of the control loop to predict the next TIC measurement.

author: Theboel
author_rank: Frequent Contributor
timestamp: February 15, 2020, 03:38:03 pm
content: Hi Mikael,try this link :https://slideplayer.com/slide/4128211/

author: thinkfat
author_rank: Unknown
timestamp: February 16, 2020, 10:52:52 am
content: Quote from: Theboel on February 15, 2020, 03:38:03 pmOK, I understand better now: The input is not just the TIC measurements. The Kalman filter could also integrate other important factors, like frequency drift over time (aka aging) and other environmental effects as far as can be measured (temperature, for example, but also stuff like air pressure which significantly affects Rb oscillators). I'll need some time to grok that. If anyone has a practical example he could share, I'd appreciate it.While experimenting with the platform I found a couple of key factors for good performance:Keeping thermal equilibrium is most important. Temperature changes cause major disturbance. Probably not in the Rb oscillator itself, but the TIC measurements are affected by the temperature and also the DAC and the OpAmp have a temperature dependency which needs to be modeled for compensation. I'm currently trying to figure these out, but it's not really that easy without a stable reference to compare against. I know that I have about -1ns/K on the TIC measurement but to which part it is the TIC or DAC and OpAmp is not quite clear. I'll have to dig out the data sheets to get a ballpark figure for those.GPS configuration: Don't use SBAS, don't enable multiple constellations. Both impact the stability of the 1PPS from the GPS negatively.

author: thinkfat
author_rank: Unknown
timestamp: February 20, 2020, 05:50:06 pm
content: Sneak peek: Beaglebone Black version of the GPSDO. Almost done!

author: texaspyro
author_rank: Super Contributor
timestamp: February 21, 2020, 01:12:14 am
content: Quote from: thinkfat on February 20, 2020, 05:50:06 pmPut some SMA connector footprints for EFC and OSC under the OCXO. Makes it easy to connect/test different OCXOs.

author: thinkfat
author_rank: Unknown
timestamp: February 21, 2020, 09:56:01 am
content: Quote from: texaspyro on February 21, 2020, 01:12:14 amDone, good idea!PS: PCBs launched!

author: thinkfat
author_rank: Unknown
timestamp: February 24, 2020, 04:20:52 pm
content: While waiting for the TAPR TICC to be delivered and the various PCBs to arrive, I decided picking up the GPS simulator from Leapsecond.com again.I reimplemented the simulation engine in Octave to have an integrated solution and tweaked it so that it matches my own STM32 code so that the parameters and results can be shared and compared between the simulator and the real hardware. Also, I'll use it as an experimentation platform for Kalman filtering.Here's some interesting results from the simulator.TIC filtering:Red: short timeconstant (40s)Blue: long timeconstant (1000s)Interestingly, with a longer filter constant you don't get a lot of advantage, for tau=300 you get a slightly lower sigma but you pay for it with a significant bulge at tau=3000Next, PI loop gain:Higher gain gives a quicker decline above tau=2000s, but degrades sigma for tau < 2000s significantly. The red curve is probably optimal.Next, OCXO vs. RB:Yellow trace is the PRS10 dataset I got from TVB with a PI integrator timeconstant of 2000s, blue is the OCXO dataset from leapsecond.com. Red is the same OCXO with timeconstant 200s.

author: AE7OO
author_rank: Regular Contributor
timestamp: March 14, 2020, 07:01:37 am
content: For single gate logics I like the OnSemi(they also have the Fairchild TinyLogics) low gate count devices.Single inverter MC74VHC1G04https://www.onsemi.com/products/standard-logic/buffers/mc74vhc1g04Single inverter MC74VHC1G14https://www.onsemi.com/products/standard-logic/logic-gates/mc74vhc1g14Single NAND MC74VHC1G00https://www.onsemi.com/products/standard-logic/logic-gates/mc74vhc1g00Single NAND MC74VHC1G132https://www.onsemi.com/products/standard-logic/logic-gates/mc74vhc1g132I like the VHC line because they allow up to 5.5VDC input no matter what the actual VCC is. They are fast, so watch out for the edges, or get a 2G part that has slower edges.These are all SC-70-5 and/or SOT-23-5 packages, some are even UDFN6, so they are indeed TinyLogic.Newark was having a sale and I picked up over 200 of the SN74LVC1G80DCKR which is a single flip-flop for 1/10th of a cent each, to join my collection of single gates.I especially love the multi-function packages where you can configure it to do what you want. If you have both a *57 and a *58 that covers almost all logic gates. A *97 can do even more, but are little larger and more expensive.

author: thinkfat
author_rank: Unknown
timestamp: March 14, 2020, 01:03:50 pm
content: Thanks for these references. I have only one single-gate inverter in the input squarer. I might try the MC74VHC1G04, seems like a good fit.

author: thinkfat
author_rank: Unknown
timestamp: June 16, 2020, 10:38:34 pm
content: Just a quick update on the status of the GPSDO for the Beaglebone Black.The project is not dead. In fact it is coming along very nicely and has seen a couple of interesting additions.The most interesting addition is that I'm feeding UTC time and 1PPS timestamps from the GPS into "chrony" (NTP server) to create a stratum-1 time server. I'm also experimenting with PTP so that the device can act as a PTPv2 "Grandmaster" clock.Picture attached shows the first working prototype.

author: dmendesf
author_rank: Frequent Contributor
timestamp: June 18, 2020, 02:14:36 am
content: That's very nice to know. I'm planning a device with a PTPv2 "slave" implementation for STM32 and one thing holding me back was a lack of an affordable grandmaster. Keep up with the good work!

author: dmendesf
author_rank: Frequent Contributor
timestamp: August 24, 2020, 02:17:41 am
content: Hi... how's this project going? Is it selling on Tindie yet?Joking, i'm in need of a cheap PTPv2 grandmaster and looking for the alternatives... anything you can share?Cheers

author: felixd
author_rank: Regular Contributor
timestamp: February 07, 2022, 09:39:22 pm
content: Any updates?

author: thinkfat
author_rank: Unknown
timestamp: February 07, 2022, 09:47:57 pm
content: Not right away. I find myself with little time to work on personal projects nowadays. I'm quite happy with the original STM32 Rubidium GPSDO, but I've abandoned the redesign and am focusing on the Beaglebone Black cape instead. Which is working great already, I'm just implementing some hardware options around the TIC that I wanted to play with, but in fact it's more down to software optimizations. The last problem I'm trying to solve is aligning the 1PPS output to be within a couple 10 nanoseconds around the GPS time pulse.

author: Carsten
author_rank: Contributor
timestamp: April 16, 2022, 02:51:45 pm
content: I'm trying to build sth similar (STM32G4 + TDC7200 + OCXO) using the ZED-F9T, which has superb sub-nanosecond timepulse stabilitywith quantization correction. I have a few concrete technical questions that I haven't been able to answer reading your posts. I'd appreciate it if you could take the time to answer these:Quote from: thinkfat on December 12, 2019, 10:22:34 pmHave you had any issues with continuously feeding a relatively fast, periodic stop signal into the TDC7200 (i.e., without a preceding start signal)?Why are you dividing the 10 MHz down to 500 kHz before feeding it to the TDC's stop input? I'm assuming this is to prevent aliasing, i.e., missing full periods of the 10 MHz signal, resulting in actual drifts outside the +-50 ppb range cyclically mapping into that range. By dividing it the 10 MHz by 20 you achieve a +-1 ppm measurement range. Any reasons other than that? Are there any issues with the TDC's clock and stop signals being the same 10 MHz signal?I intend to directly feed the 10 MHz into the TDC and to resolve the aliasing by using a 32-bit timer capture to measure the GNSS 1PPS with ~6 ns resolution (170 MHz timer clock) relative to the OCXO's 10 MHz, which also serves as the STM32's HSE clock source. Any comments on that?Quote from: thinkfat on February 16, 2020, 10:52:52 amHave you been able to determine the cause of the TIC measurements' -1 ns/K temperature coefficient? It shouldn't be the TDC7200 due to its self-calibration. Could it be 3x the 74HC390 propagation delay, which has alikely non-negligible temperature dependency?Quote from: thinkfat on June 16, 2020, 10:38:34 pmJust asking out of curiosity: How are you feeding time into the BBB? You wrote that you don't plan to use its PRUs. From my understanding the BBB runs from its own (drifting) clock source and any time transfer would also be affected by scheduling and interrupt jitter. Are you using a hardware timestamping Ethernet PHY to overcome that? Which accuracy can you achieve with NTP/PTP?

author: thinkfat
author_rank: Unknown
timestamp: April 16, 2022, 03:42:28 pm
content: Hi Carsten, welcome to the forum.Regarding your question:I did have some issues with the TDC7200 which might have been due to the STOP signal coming too quickly after the START signal. The topic came up in this thread but could not be resolved satisfactorily. However, in praxi I have not seen any issues with sending STOP without a START before, according to the data sheet, the TDC7200 should be fine with this.The divide-down to 500kHz was indeed meant to avoid aliasing. Initially I didn't have a counter connected to the 10MHz, so something had to be done. I did not see any issues with the clock input and the STOP signal being coherent.Feeding the 10MHz into a counter and directly to the TDC7200 works, but it is better to delay the 10MHz STOP signal edge with regards to the 1PPS pulse by e.g. a flip-flop because the TDC7200 cannot measure down to 0ns. This would also prevent feeding constant STOP signals into the TDC. I have seen a circuit from a fellow forum member somewhere that does this, I cannot remember however where. It is remarkably simple, with just a 74HC74. I think it is just by connecting the clock inputs of the two FFs to the 10MHz clock, connecting the 1PPS pulse to the first D input and connecting the first Q output to the D of the second FF. The Q output of the second FF is your STOP. Then you can use the TDC in Mode 1.I've not been able to determine the temperature dependency of the measurements satisfactorily, but I have added a D-FF after the 500KHz signal that synchronizes it with the 10MHz again. I think that has helped.Feeding the time into the BBBThat is a neat trick indeed. The DMTIMERs of the AM3358 can be driven by an external clock. So, I just feed them with the 10MHz OCXO output. Then I capture the 1PPS signal from the GNSS receiver using the same timer, that works in hardware with no latency due to interrupt processing or stuff. I then take timestamps from the captured counter value to have a PPS source for "Chrony". Additionally, I use the exact same timer as the system clocksource. Since the counter is clocked by the disciplined OCXO, it has effectively zero drift against the GNSS. So I get a zero-drift system time:Code:root@ptpgm:~# chronyc trackingReference ID : 50505330 (PPS0)Stratum : 1Ref time (UTC) : Sat Apr 16 15:35:35 2022System time : 0.000000000 seconds fast of NTP timeLast offset : +0.000000000 secondsRMS offset : 0.000000000 secondsFrequency : 0.000 ppm slowResidual freq : +0.000 ppmSkew : 0.000 ppmRoot delay : 0.000000001 secondsRoot dispersion : 0.000002431 secondsUpdate interval : 1.0 secondsLeap status : NormalI hope this answers your question.Best regards,Matthias

author: Carsten
author_rank: Contributor
timestamp: April 16, 2022, 03:51:44 pm
content: Thanks for the welcome and for answering my questions. That is a neat trick indeed.

author: thinkfat
author_rank: Unknown
timestamp: December 29, 2022, 11:16:16 am
content: It's been a while since I was active on this project.I always wanted to characterize the performance of my GPSDO and lacked the equipment to do so, but that has just recently changed.Forum member and fellow time nut @erikka found an ingenious way to turn a nanoVNA-H4 into a very accurate phase and frequency measurement device with just a firmware change. He has started a thread about it on the forum, you can find it here:https://www.eevblog.com/forum/metrology/very-accurate-phase-and-frequency-measurement-using-the-nanovna-h4-hw/msg4594966/The attached graph from TimeLab shows the current BBB-GPSDO hardware against the timebase of my 53132A counter, which is equipped with the high-stability OCXO option. The counter had less than 24h to warm up, it was powered down a couple of months, which is far from ideal for an OCXO, but it was all I could do with reasonable effort for now. I'll later fire up one of my Rubidiums for comparison.The blue trace is the raw measurement, magenta is after removing linear drift, which should compensate the OCXO drift. The green trace is the TIC output from the GPSDO, which shows its phase error against the GNSS reference. It serves as a "worst case" depiction, the GPSDO output can never be worse than this curve.Since I have no way right now to characterize the 53132A timebase itself properly, I cannot give an absolute statement of the GPSDO output yet, I can only say that its stability is "not worse than" what the magenta trace shows. But that's already something.

author: thinkfat
author_rank: Unknown
timestamp: December 31, 2022, 02:22:13 pm
content: And another measurement result, this time referenced against one of my Rb oscillators. I think it is quite interesting.As you can see, up to tau=5s it is much noisier than the previous measurement against the 53132A timebase. That is somewhat expected from a surplus LPRO-101. However, the result above t=5s is _better_. That means the previous measurement was likely dominated by the 53132A timebase above 5s and not the GPSDO.So, up to 5s, the GPSDO is as least as stable as the green curve, and above 5s it is at least as stable as the blue curve.

author: erikka
author_rank: Regular Contributor
timestamp: December 31, 2022, 09:11:22 pm
content: It would be interesting to see the ADEV of the PPS against the RB (should be 1/Tau) till at least 1000s and both the regulated and unregulated gpsdo output.This should show a higher ADEV for the regulated GPSO in the decade before the PPS line starts to bring the ADEV downMany Rb seem to have worse noise around 1s versus a good OCXO

author: cncjerry
author_rank: Unknown
timestamp: December 31, 2022, 09:54:20 pm
content: I'm also converting some arduino + TDC7200 + sawtooth code to an STM32F7 board. I recently added FREERTOS code and TouchGFX but now my TDC code is jumping one count, possibly due to FREERTOS time slicing even though the TDC7200 code runs in a capture compare interrupt level loop. Need to look at it more closely. One thing I found is the clock speed on the TDC7200 should be higher than practical for a 10Mhz based system. You need an accurate clock with 50/50 duty cycle and the highest you can go, I think, is 5Mhz, unless you double it but then jitter might be a factor? Haven't explored all that yet.I have most of it working but got interrupted by the holidays. Getting the TDC7200 SPi calls correct were a pain but I have that all working now. The command interface is working from a PC and the graphing works. I need to take the ADEV code I have and rework the output for the small screen and TouchGFX. Since I have extra usarts on the board, I've been kicking around either using a DMTD system with a TICC (dual 7200 TIC from TAPR) or use a 2ndary PPS reference input directly into the GPSDO system using another TDC7200. Or possibly use the collected data from the PID loop, don't know yet.Once I get this system tested using a standard PID loop I'm going to try to develop a neural network PID loop using the STM library, STMCube.AI. I've seen some examples that look promising. ideally, and I use that term loosely, I would like to have the neural net train all the way from GPS to ADEV using one of the more ideal ADEV masks. I had tested some decent GPSDOs against my Cs beam and you can also get GPSDO ADEV masks from Timelab. I expect this to take the rest of my pre-dementia life.Jerry

author: thinkfat
author_rank: Unknown
timestamp: December 31, 2022, 10:07:44 pm
content: Quote from: erikka on December 31, 2022, 09:11:22 pmYep, but there's no need to make that experiment myself. There's plenty of sample data, e.g. on leapsecond.com, there's sample set of GPS 1PPS against some Rb or Cesium clock, that could be used as a reference.I agree about the Rb clock output. For example, the LPRO-101 has just a regular crystal oscillator that is not even heated. Additionally, those surplus Telecom Rb's all have the same problem, their Rb lamp is showing its wear and the reduced SNR shows up as noise on the output. They do lock, but the output stability is degraded. The FE-5680 are even worse, they have DDS artifacts on the output.The Efratom FRK would likely be a better candidate, at least it has a heated, I think even temperature controlled XO. I have one, but it's broken and I don't find time to repair it.However, I could think of a PLL filter with an OCXO to clean up the Rb output. That could be an interesting project.

author: erikka
author_rank: Regular Contributor
timestamp: January 01, 2023, 09:45:11 am
content: The main reason to do the experiment using your current GPSDO project could be to validate if the GPSDO is working correctlyHere you have a simulation of the GPSDO algorithm using actual PPS data and TCXO stability data and the actual measurements including the performance of the GPSDO (green trace)Seeing the disciplined TCXO trace stay below the PPS trace is confirmation the GPSDO is performing well.

author: thinkfat
author_rank: Unknown
timestamp: January 01, 2023, 11:56:43 am
content: The definition of "performs well" is subject to what you want to do with the GPSDO/GNSSDO. You may choose to have "slow" regulation and sacrifice some stability at tau=1000s, to have the cleanest possible output at small tau, or you may want the stability to be never worse than the 1PPS reference.

author: hgl
author_rank: Regular Contributor
timestamp: January 01, 2023, 12:37:41 pm
content: Quote from: erikka on December 31, 2022, 09:11:22 pmI bought a used UCCM GPSDO module from Samsung on EBAY for about 40$ 3 years ago from China.The picture shows the GPSDO as external reference for the FA-2 vs. my best Temex MCFRS-1 Rb for 24h. The Temex Rb uses an internal 20 Mhz XT-Cut oscillator and the Samsung GPSDO has a STP2945LF oscillator.

author: erikka
author_rank: Regular Contributor
timestamp: January 01, 2023, 12:42:01 pm
content: @hglOut of curiosity, do you know why the noise slope of the FA2 is not 1/Tau?

author: hgl
author_rank: Regular Contributor
timestamp: January 01, 2023, 01:54:03 pm
content: 1/tau only applies to white PM noise. The FA2 also has other noise components generated by the power supply, reference oscillator, nonlinearity of the interpolator, etc. With long-term measurements, the white noise also averages out.

author: erikka
author_rank: Regular Contributor
timestamp: January 01, 2023, 05:43:46 pm
content: @hglDo you still have the .tim file, I'd like to zoom in so I can better understand the nature of the noise.

author: hgl
author_rank: Regular Contributor
timestamp: January 01, 2023, 07:49:23 pm
content: With stable32 (http://www.stable32.com/) you can generate different noise variants and save to file.

author: 0xFFF0
author_rank: Regular Contributor
timestamp: January 01, 2023, 07:54:59 pm
content: the worst: 10 000 000 001 606 448E+07

author: erikka
author_rank: Regular Contributor
timestamp: January 01, 2023, 08:00:19 pm
content: Thanks for the raw measurement.It helps me to understand the amount or other forms of "noise", next to white noise, in the FA2Attached the FA2 noise compared to the tinyPFA noiseThe tinyPFA also has some random walk that becomes visible when running long measurements. A similar bump around 100s

author: hgl
author_rank: Regular Contributor
timestamp: January 01, 2023, 09:55:27 pm
content: Recommendation for further readingW.J.Rileyhttp://www.wriley.com/Learn%20Frequency%20Stability%20Analysis%20Using%20Stable32.pdfEnrico Rubiolahttp://rubiola.org/pdf-slides/2016T-EFTF--Noise-in-digital-electronics.pdf

author: cncjerry
author_rank: Unknown
timestamp: January 02, 2023, 06:16:23 pm
content: The big factor that comes into play is the survey, don't know if your code is sending the message to the GPS or not. You can also use Ublox UCenter, but we found huge differences in performance as the survey completes at less than 1m. It took a few days for my GPS, a Ublox lea-m8t, to finish down to .25m.The attachment below plots the TIC high/low/average (red/blue/black), the DAC EFC voltage (green) and number of sats in view (orange) with the middle being 10 sats and the absolute peak of 15. The survey completed after the 4th block from the left and you can see how the TIC and DAC EFC voltage settled down. This oscillator (Wenzel low noise sprinter, chosen for phase noise opposed to ADEV) is still drifting high as it hadn't been turned on in years. This code was based on Lars, modified quite a bit, and then became the basis for my STM32F7 code. With a time constant of 512 the oscillator will stay less than +/- 5ns if left alone after the survey. But any draft, significant rain, etc., will make it drift as much as +/- 20ns.Jerry

author: 0xFFF0
author_rank: Regular Contributor
timestamp: January 03, 2023, 12:09:24 am
content: Does the survey have to be initiated/activated? What commands do you send or receive from the Ublox?

author: cncjerry
author_rank: Unknown
timestamp: January 03, 2023, 08:12:49 am
content: If you are using a ublox timing receiver, that which you should be using (models ending in T, though I think the models ending in 'F' are timing as well), then it depends on the model. At some point in the 5's or 6's they changed from sending tmode to tmode2. Best way to send it is with Ublox Ucenter code for windows (free). I would stay away from Ucenter V2 and find V1, Release 22.10 or around there as it is much easier to use, no login accounts, etc.You bring up the config messages screen, scroll down to timing, find tmode or tmode2 depending on your model, and then set the parameters to like 10,000 observations and something less than .5 meters. Depending on the Ucenter version, you have to be careful as at one point you could send meters but the model expected centimeters or vice versa. Find v22 and put .25 meters, enable the srvin message and you can watch it count down.Depending on the variance, I use .25m, it will take time to get there. .25m at c (300km/s will give you the minimum possible variance for the accuracy of your GPS and DO. So .25m is 7.5e-10th if I did my math correctly and since it is actually the square root of that variance, and I can't remember if the software takes that into account, you can assume you will be less than 1ns from where the GPS thinks it is. You can see on the chart I posted that the numbers were varying +/- about 25ns or so, maybe even as much as 50ns until the survey completed. At that point, the variance in TIC with sawtooth correction came down to much less than +/5ns. Other factors impact that though, temperature, humidity, power fluctuations, turning the lights on, anything that can upset a low noise oscillator.Instead of using Ucenter, you can send the command from your code and the only tricky part is the CRC characters that need to be calculated. There is a 500 page manual on the Ublox GPS modules that explains all this.I don't know who wrote this code. It was either Lars or Jim Harman, I modified it for the tmode2 message. Only thing to consider is if you send it and change your mind and want to send it with a looser variance, you need to send it with a cancel code (0x00) first. Once you send it, you should also config messages in Ucenter to receive the srvin messages so you can watch the progress. When the observations stop counting up, then the survey is completed.This example is already setup for 1m^2 so you can send it as-is. You don't need to fill in the lat/long/altitude as that will be filled in by the GPS quickly and then resolve to the variance. Once you get it fixed at .5m or less, you can send it a fixed location message at reboot as long as you don't move your antenna.This makes a very big difference in the performance of a GPSDO. Once I get my STM32 code completed, I am going to see if it will count down to 10cm. I've heard of people setting the variance to 1cm. I think you should also set the max number of sats to between 5 and 7 and raise the angle to minimize fluctuations from low sats. There is quite a bit on the web about that. Thinking is that 5 high sats with strong cn ratios is better than 12 sats banging away at your receiver. My variance also correlated more quickly when I did that. I think I used 5 sats and 25 degrees with cn > 35. That is in like the sat5 message? can't remember. Again, Jim H. really helped me with all this. I'm sure there are much more knowledgeable people on here that can throw-in at this point.call this routine with a duration of at least 5,000 to get 1mCode://----------------------------------------------------------------------------------------//----------------------------------------------------------------------------------------// Send the Ublox CFG-TMODE2 message to initiate a survey of length duration secvoid startSurvey(long duration) { // jth changed to tmode2 message as m8t doesn't support tmode// note LSB is sent firstuint8_t packet[] = {0xB5, 0x62, // header0x06, 0x3D, // class = CFG, id = TMODE20x1C, 0x00, // length = 280x01, // 01 survey in, 00 cancel, 02 fixed0x00, // reserved0x00, 0x00, // flags0x00, 0x00, 0x00, 0x00, // X coordinate ignore for survey, set for fixed0x00, 0x00, 0x00, 0x00, // Y coordinate as above0x00, 0x00, 0x00, 0x00, // Z coordinate as above0x00, 0x00, 0x00, 0x00, // position variance measured(uint8_t)(duration & 0xFF), //duration(uint8_t)((duration >> 8) & 0xFF),(uint8_t)((duration >> 16) & 0xFF),(uint8_t)((duration >> 24) & 0xFF),// 0x40, 0x42, 0x0F, 0x00, // position variance = 1 m^20xE8, 0x03, 0x00, 0x00, // position variance = 1 m^20x00, 0x00 // 2 bytes for checksum};sendPacket_crc(packet, sizeof(packet));}//----------------------------------------------------------------------------------------// send a packet to Ublox with crcvoid sendPacket_crc(uint8_t *packet, uint8_t len) {uint8_t ck_a = 0;uint8_t ck_b = 0;for (uint8_t i = 2; i < len-2; i++) { // compute crcck_a += packet;ck_b += ck_a;}packet[len-2] = ck_a; // put crc in packetpacket[len-1] = ck_b;for (uint8_t i = 0; i < len; i++) { // send it outSerial1.write(packet);}}

author: 0xFFF0
author_rank: Regular Contributor
timestamp: January 03, 2023, 08:36:18 am
content: Thanks for the information. Much to learn. I'll try that. So the DynModel stationary command is not enough?

author: hgl
author_rank: Regular Contributor
timestamp: January 03, 2023, 03:19:04 pm
content: Quote from: erikka on January 01, 2023, 05:43:46 pmSorry the old raw data file I had posted was the wrong one. Here are again the image and both data files.

author: thinkfat
author_rank: Unknown
timestamp: January 03, 2023, 04:04:49 pm
content: Quote from: 0xFFF0 on January 03, 2023, 08:36:18 amNo, but using the stationary model will help bringing down the time for the survey-in "somewhat".

author: erikka
author_rank: Regular Contributor
timestamp: January 03, 2023, 04:18:38 pm
content: This noise data makes more sense.The FA2 has very good performance for a counter.Here again compared to tinyPFAWeird the phase of the FA2 has so much drift. I would expect some drift as it measures frequency and not phase but its a lot.There is an average -2e-12 frequency offset

author: cncjerry
author_rank: Unknown
timestamp: January 03, 2023, 04:49:43 pm
content: Quote from: 0xFFF0 on January 03, 2023, 08:36:18 amIt depends on if you have highly accurate location information. You need to run the survey for a day or two at a minimum. That's why it has two parameters for setting the survey. It could converge to less than .25m in 10 minutes but that doesn't mean that is an accurate location.I've not had any luck with setting fixed location. I run the survey with .25m if the antenna moves at all or the GPS reboots. I have an old UPS I am going to put on it with an lt3045 regulator module in between. I had thought about going to all batteries like in my phase noise test system as there you can see the results.I would run just a simple standard deviation on your TIC data and see how it looks before/after a survey.Jerry

author: hgl
author_rank: Regular Contributor
timestamp: January 03, 2023, 04:59:16 pm
content: The TDC7200 measures the elapsed time between a START pulse and up to five STOP pulses , further stops are ignored.Minimum time between Start and Stop must be greater than 12ns and this is not guaranteed with the circuit that was posted here.https://www.eevblog.com/forum/projects/diy-gpsdo-project-w-stm32-tdc7200/msg2826706/#msg2826706.The temperature dependence is compensated by the measurement of reference cycles after the stop.

author: hgl
author_rank: Regular Contributor
timestamp: January 03, 2023, 05:11:34 pm
content: Quote from: erikka on January 03, 2023, 04:18:38 pmThis is perhaps due to timelab, which can only export phase. I attach the tim file as .txt you must rename it then again in tim

author: erikka
author_rank: Regular Contributor
timestamp: January 03, 2023, 09:30:03 pm
content: Thanks for the .tim file.Its clear this is not due to FA-2 but due to processing in TimeLabThanks for all the clarifications!

author: thinkfat
author_rank: Unknown
timestamp: January 06, 2023, 07:45:52 am
content: Quote from: cncjerry on January 03, 2023, 04:49:43 pmIt should not take a day to reach 0.25m position uncertainty. A couple of hours should be enough. There's a couple of things you can do to speed it up, too:For starters, you can increase the measurement frequency to more than 1 Hz. I've experimented with 4 Hz, but 5 Hz should also still work. This trick divides the time necessary by an according factor.Second, disable GLONASS and enable only GPS and Galileo. I've found that GLONASS messes with positioning and also stability in general. At least on a Ublox M8T.Third, enable SBAS while you do the survey, switch it off again after the survey has ended. This will increase precision of the position measurements taken and help drive down uncertainty faster.

author: tomnut
author_rank: Newbie
timestamp: January 24, 2023, 11:26:05 pm
content: FWIW I find that the TDC7200 is absolutely reliable when its STOP is fed from a 10 MHz clean square wave. It will pick one of the rising edges and time that accurately.It will sometimes read under 12 ns, sometimes over 112 ns, but it doesn't seem to make mistakes when the STOP rising edge is near its allowed minimum time. I've probably had some 100k pulses within +-1 ns of the minimum and never seen an incorrect result.The minimum time from ARM to START must be respected, however. If you abuse that (say by trying to start on the edge of a 10 MHz clock of random phase) it will give you garbage.

author: S57UUU
author_rank: Regular Contributor
timestamp: January 25, 2023, 03:40:43 pm
content: The survey should be set to an integer multiple of 24h, to reduce the daily ionosphere variation. The amplitude of elevation error at my place is typically + -1m, see fig 4.3 here:http://lea.hamradio.si/~s57uuu/mischam/gpsy/index.htmledit:or do the survey at night, hours after sunset

author: thinkfat
author_rank: Unknown
timestamp: January 26, 2023, 08:06:22 am
content: Quote from: S57UUU on January 25, 2023, 03:40:43 pmWow. What a write-up! I've always speculated about using the internal state of the GPS receiver for disciplining an oscillator but I was scared of replacing the LO. I know that the Trimble "Thunderbolt" GPSDOs use the same method, while most of the other commercial "telecom" grade UCCM modules just use the 1PPS output and maybe also quantization correction.

author: iMo
author_rank: Super Contributor
timestamp: January 26, 2023, 09:45:48 am
content: Btw. - there is the TDC7201 with 2 channels (and perhaps other features too).. I wonder whether it could provide some improvements over the 7200. It is in a 25balls BGA package, though.. I think I got it in past, but not elaborated yet..

author: Clemgill
author_rank: Contributor
timestamp: July 21, 2024, 12:42:00 pm
content: Quote from: thinkfat on January 06, 2020, 10:41:06 amThanks for this discussion, but if I am not wrong, I seems too me that we should add qErr to the measurement instead of (-qErr)hereafter is the rationale :qErr true timepulse Corrected measerementnegative earleir than TP M - |qErr| = M -(-qErr) = M+qErr because qErr is negativepositive later than TP M +|qErr| = M + qErr because qErr is positiveIs this right ?