Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replacing XTAL with a more accurate one #4

Open
mungewell opened this issue Feb 17, 2024 · 12 comments
Open

Replacing XTAL with a more accurate one #4

mungewell opened this issue Feb 17, 2024 · 12 comments

Comments

@mungewell
Copy link
Owner

mungewell commented Feb 17, 2024

It would seem that the stock XTAL (with current code implementation) is not meeting the timing accuracy required - less than 1frame drift in 8hours.

Fortunately we can replace the XTAL with a more accurate TCXO module. I have 2 candidate parts:

The 2nd is more accurate/precise, but with a slightly different frequency it might mean more work. The Pico's SDK has a override for building at different frequencies, so a custom build of microPython is likely needed. The boot-rom also expects 12.0MHz, so using this part might mean that USB is not functional - and 'we' might have to rely on the SWD interface to program the board.

2nd part is also bigger....
vlcsnap-2024-02-17-11h08m43s089

@mungewell
Copy link
Owner Author

mungewell commented Feb 17, 2024

Looking at the Pico's schematic, we can see that the XTAL is fed from the CPU via a series drive resistor (R14), and has a couple of matching caps (C16 and C17) - all of which are not needed for a TCXO module. Isolating the pads for the XTAL may give us more mounting options.
pico_xtal

We can also pull a VCC from the caps next to the CPU. (revised)
pico_closeup

@mungewell
Copy link
Owner Author

mungewell commented Feb 17, 2024

Firstly - Highly recommended that you program the Pico BEFORE replacing components, that way you'll have indications of a working board (flashing LED/serial output/etc)...

12.0MHz 3V0 - https://www.digikey.ca/en/products/detail/ilsi/i538-2o7-12-000-mhz/13682056
replacement_12 0_xtal

This has a different footprint, we can see that the part should be rotated:

  • PCB 1 (XIN - to CPU) = Pin 3 (Output)
  • PCB 2 (GND) = Pin 4 (VCC) - This will need to be isolated, cut 4 links from pad to the ground plane
  • PCB 3 (XOUT - from CPU) = Pin 1 (GND or NC) - Isolate by removing R14 from Pico
  • PCB 4 (GND) = Pin 2 (GND)

Once the part is placed, add a small 'fly-wire' from small cap near CPU to Pin 4 of the TCXO module. Double check this is not shorted to ground before power-up.
replacement_12 0_xtal_cut

Not my best soldering, but it seems to work. Real test will take more time to evaluate it's timing performance.
replacement_12 0_xtal_done

I also realized that I order the WRONG part for a 3V0 (not 3V3) VCC - oh well will try it anyway...

Mouser have an equivalent for 3V3, but wants to sell a full real of qty 3000.
https://www.mouser.ca/ProductDetail/ABRACON/I738-2P3-12.000MHz?qs=vmHwEFxEFR%2FD2ZfWbp716g%3D%3D

@mungewell
Copy link
Owner Author

I have some results.... but not sure what it going on with some 'strangeness'.

Ultimately the 'accuracy' of the tracking is dependent on the system choosing the correct 'micro-adjust', where is modulates between adjacent fractional clock dividers. This is not (presently) compensated with temp, but that is something which might be possible.

I have recently changed this code, and now the system measures the 'phase' in frame duration - considering a wrap point at +/-0.5 (ie +/-40 bits of LTC data).

Anyhow.... I purchased an UltraSync One, and used this as the reference for testing.
rejam2-e

rejam2-t

Note: the point where 'micro-adjust' fixes is where I manually stopped calibration ('CX' mode), and restarted the monitor ('RX' mode).

So the one with the modified XTAL has a weird step, this was also seen in other data-sets from this board. But it does not seem to be present in non-modified board recorded at the same time. Regardless these plots (with a well chosen 'micro-adjust' value) show less than 4bits drift in ~5hrs (noting 80bits would be 1 frame).

My conclusion is that the (noted incorrect voltage) TCXO does not function correctly, and I will look at the alternatives - including the 12.8MHz I have on hand.

@mungewell
Copy link
Owner Author

After spending some time digging through DigiKey, I think that this might be the 'Best' replacement...
"ECS-TXO-3225-120-TR"
https://www.digikey.ca/en/products/detail/ecs-inc/ECS-TXO-3225-120-TR/5357946?s=N4IgTCBcDaIKIGEDKBaAKgDQPIoMxjAFYUBGMABnQCUQBdAXyA

There is also this (much more expensive) 12.8MHz part with really low PPM that will fit on the footprint.
"LFTCXO075793REEL"
https://www.digikey.ca/en/products/detail/iqd-frequency-products/LFTCXO075793REEL/8633985?s=N4IgTCBcDaIDIDEAqBhAGgeQAwHYCsOAnAMwBKAouXCALoC%2BQA

The following is a suggestion to modify the Pico PCB, should it ever be relaid:

By adding 2 resistor footprints to connect to pin 2 of the XTAL, we could configure the board to take either a passive XTAL or a (user performed modification) TCXO. Only extra one resistor, connecting to ground, would be fitted for mass production.

pico_schematic_mod

@mungewell
Copy link
Owner Author

Another candidate for the 'ugly mod' competition.... But this ($15) module is certainly holding it's own, showing less than 0.25 frames drift in 20hrs... though it's been at that value for hours, so maybe (at least some of) the drift is from initial warm up.
IMG_20240306_180737402
IMG_20240306_180606988_HDR

I also learnt a lot about how the USB doesn't work after you change XTAL frequency (to 12.8MHz for this). You can upload a special build of microPython with SWD interface, but the bootloader will be forever broken.

@mungewell
Copy link
Owner Author

mungewell commented Mar 20, 2024

I was able to automate the testing of the stock XTAL, where performance is inferred from what the unit determines the 'calibration' value to be. This conclusively shows that the calibration DOES change with temperature.

The temp shown is not itself calibrated, but shows first plot at ambient (purple trace before I realized unit(s) were in the sun) and then second plot in the freezer.

ttyACM0_combo
ttyACM0_combo

Note: the fractional part of the calibration value represents modulating the between smallest fractional values of the PIO divider, ie between '1562+(128/256)' and '1562+(127/256)'.

So a 'calibration delta' of 1.0, would be roughly equivalent to 2.5PPM XTAL variance.

Note: Temp vs Freq will not be linear, it depends on XTAL type. Some plots are 'S' shaped.

@mungewell
Copy link
Owner Author

mungewell commented Oct 17, 2024

So after being away for a while, I have amassed more hardware and improved the code/testing scripts....
IMG_20241014_131224724

This takes a reference Timecode from the UltraSync One, splits/amplifies it to the 4 test units. The USB hub support power management, test scripts running on PC turn the units off/on to cycle/restart the calibration process and record the resultant data.

I have been running a few tests and this plot definitely shows a correlation between temp in the top plot and changing (computed) calibration in the lower plot.
combo_ttyACM2_anot

As the selected calibration moves from the value required by particular XTAL and temperature, the resultant timecode will slowly drift from perfect.

Note: the calibration value is defined in two parts, the integer value define the clock division value in the smallest possible difference in value (on the PIO clocks this is 1/256th of a divider). The fractional part of the calibration value is a duty factor, for dithering between one divider value, and the next (depending on sign).

So for 30fps, and a calibration value of -0.3 the code will dither between 1562.5 (1562 + 128/256) for 70% of the time and 1562.50390625 (1562 + 129/256) for 30% of the time.

This gives 'apparent divisor' of 1562.501171875; about 1.00000075 speed adjustment from nominal XTAL frequency, or about 0.75 PPM.

@mungewell
Copy link
Owner Author

A little glimpse into how calibration process runs....
cal_ttyACM0_anot

@mungewell
Copy link
Owner Author

I don't have a temp chamber, but I 'folded up' my test rig up and put in a box... along with a USB load tester to add 7.5W of heating.
IMG_20241017_125558040_HDR
IMG_20241017_134007393_HDR

This resulted in a little warming which definitely shows up in the calibration.
combo_ttyACM3

This pushed the calibration spread to quite a bit, over 1 unit!!

  • "Minimum Calibration -0.5558637 "
  • "Maximum Calibration 0.4578195 "
  • "Average Calibration 0.03432039166666662 "

A Pico with the XTAL replaced with TCXO faired much better:
combo_ttyACM0

  • "Minimum Calibration -0.3945614 "
  • "Maximum Calibration -0.3196151 "
  • "Average Calibration -0.3487558142857142 "

@mungewell
Copy link
Owner Author

mungewell commented Oct 22, 2024

I modified a total of 6 boards with TCXO's, although I struggled with recreating my 'ugly' mod. I actually found it easier to stand the TCXO on end, and fly-wire 3.3v to power it... maybe not mechanically sound, but good enough for now.

TCXO_mod

I'm trying to understand the best way(s) to validate these, on the outset it looks like they are much better than the stock XTAL, but there still seems to be some temperature variance....

This is the one I used:
https://www.digikey.ca/en/products/detail/ecs-inc/ECS-TXO-3225-120-TR/5357946

@mungewell
Copy link
Owner Author

So this is a thing now....
master_chef

At 10'C

20241128_10C$ find . -name '*.py' -exec python3 {} \;
set yrange[-0.6668293000000001:-0.1901701]
set title "T006 Minimum : -0.4668293 "
set title "T006 Maximum : -0.3901701 "
set title "T006 Median : -0.42849970000000004 "
set title "T006 Average : -0.43838419999999995 "
set yrange[-0.8526231:-0.37128829999999996]
set title "T004 Minimum : -0.6526231 "
set title "T004 Maximum : -0.5712883 "
set title "T004 Median : -0.6119557 "
set title "T004 Average : -0.6167881100000001 "
set yrange[-0.5918292:-0.1394613]
set title "PT-3 Minimum : -0.3918292 "
set title "PT-3 Maximum : -0.3394613 "
set title "PT-3 Median : -0.36564525000000003 "
set title "PT-3 Average : -0.37087760000000003 "
set yrange[-0.7329938:-0.2569399]
set title "T002 Minimum : -0.5329938 "
set title "T002 Maximum : -0.4569399 "
set title "T002 Median : -0.49496684999999996 "
set title "T002 Average : -0.49475629000000004 "

At 40'C

20241128_40C$ find . -name '*.py' -exec python3 {} \;
set yrange[-0.6557084:-0.2088253]
set title "T006 Minimum : -0.4557084 "
set title "T006 Maximum : -0.4088253 "
set title "T006 Median : -0.43226685 "
set title "T006 Average : -0.43405330000000003 "
set yrange[-0.8128355:-0.3960141]
set title "T004 Minimum : -0.6128355 "
set title "T004 Maximum : -0.5960141 "
set title "T004 Median : -0.6044248 "
set title "T004 Average : -0.606632025 "
set yrange[-0.600455:-0.17753370000000002]
set title "PT-3 Minimum : -0.400455 "
set title "PT-3 Maximum : -0.3775337 "
set title "PT-3 Median : -0.38899435000000004 "
set title "PT-3 Average : -0.3892936000000001 "
set yrange[-0.7598024999999999:-0.35273879999999996]
set title "T002 Minimum : -0.5598025 "
set title "T002 Maximum : -0.5527388 "
set title "T002 Median : -0.55627065 "
set title "T002 Average : -0.5556236999999999 "

I also found that the Hub in my test setup doesn't apparently like the higher temps... as it locked up several times. :-(

@mungewell
Copy link
Owner Author

mungewell commented Dec 2, 2024

Calibration sheet:
calibration.pdf

So the 'temp shift' in calibation depends on each unit (there may have also been temp variation within the oven), the WORST shift between 10'C and 40'C is 152ppb for 'average vs nominal/null calibration' and the typical is in the 10's of ppb.

This is SIGNIFICANTLY better than the shift we saw in calibration with the stock XTAL....

For reference our target is: +/-0.5 frames in 8hrs; ie '8 * 3600 * 30fps = 864000 frames', so for accuracy we'd want '864000.5 / 864000 = 1.000000579' (around +/-0.6 ppm).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant