Dear Matthias,

On 2022-05-03 10:57, Matthias Welwarsky wrote:
Dear all,

thanks for your kind comments, corrections and suggestions. Please forgive if
I don't reply to all of your comments individually. Summary response follows:

Attila - yes, I realize temperature dependence is one key parameter. I model
this meanwhile as a frequency shift over time.

Bob - I agree in principle, real world data is a good reality check for any
model, but there are only so few datasets available and most of the time they
don't contain associated environmental data. You get a mix of effects without
any chance to isolate them.
Environmental effects tends to be recognizeable by their periodic behavior, i.e. period of the day and the period of the heating/AC. Real oscillator data tends to be quite relevant as you can simulate what it would mean to lock that oscillator up. TvB made a simulator on those grounds. Good exercise.

Magnus, Jim - thanks a lot. Your post encouraged me to look especially into
flicker noise an how to generate it in the time domain. I now use randn() and
a low-pass filter. Also, I think I understood now how to create phase vs
frequency noise.

Happy to get you up to speed on that.

One particular name to check out articles for is Charles "Chuck" Greenhall, JPL.

For early work, also look att James "Jim" Barnes, NBS (later named NIST).

Both these fine gentlement is recommended reading almost anything they write on the topic actually.

I've some Timelab screenshots attached, ADEV and frequency plot of a data set
I generated with the following matlab function, plus some temperature response
modeled outside of this function.

function [phase] = synth_osc(samples,da,wpn,wfn,fpn,ffn)
        # low-pass butterworth filter for 1/f noise generator
        [b,a] = butter(1, 0.1);

Notice that 1/f is power-spectrum density, straight filter will give you 1/f^2 in power-spectrum, just as an integration slope.

One approach to flicker filter is an IIR filter with the weighing of 1/sqrt(n+1) where n is tap index, and feed it normal noise. You need to "flush out" state before you use it so you have a long history to help shaping. For a 1024 sample series, I do 2048 samples and only use the last 1024. Efficient? No. Quick-and-dirty? Yes.

The pole/zero type of filters of Barnes let you synthesize an 1/f slope by balancing the properties. How dense and thus how small ripples you get, you decide. Greenhall made the point of recording the state, and provides BASIC code that calculate the state rather than run an infinite sequence to let the initial state converge to the 1/f state.

Greenhall published an article illustrating a whole range of methods to do it. He wrote the simulation code to be used in JPL for their clock development.

Flicker noise is indeed picky.

Cheers,
Magnus

        # aging
        phase = (((1:samples)/86400).^2)*da;
        # white phase noise
        phase += (randn(1, samples))*wpn;
        # white frequency noise
        phase += cumsum(randn(1, samples))*wfn;
        # 1/f phase noise
        phase += filter(b,a,randn(1,samples))*fpn;
        # 1/f frequency noise
        phase += cumsum(filter(b,a,randn(1,samples))*ffn);
end

osc = synth_osc(400000, -50e-6, 5e-11, 1e-11, 5e-11, 5e-11);

Thanks.

On Montag, 2. Mai 2022 17:12:47 CEST Matthias Welwarsky wrote:
Dear all,

I'm trying to come up with a reasonably simple model for an OCXO that I can
parametrize to experiment with a GPSDO simulator. For now I have the
following matlab function that "somewhat" does what I think is reasonable,
but I would like a reality check.

This is the matlab code:

function [phase] = synth_osc(samples,da,wn,fn)
# aging
phase = (((1:samples)/86400).^2)*da;
# white noise
phase += (rand(1,samples)-0.5)*wn;
# flicker noise
phase += cumsum(rand(1,samples)-0.5)*fn;
end

There are three components in the model, aging, white noise and flicker
noise, with everything expressed in fractions of seconds.

The first term basically creates a base vector that has a quadratic aging
function. It can be parametrized e.g. from an OCXO datasheet, daily aging
given in s/s per day.

The second term models white noise. It's just a random number scaled to the
desired 1-second uncertainty.

The third term is supposed to model flicker noise. It's basically a random
walk scaled to the desired magnitude.

As an example, the following function call would create a phase vector for a
10MHz oscillator with one day worth of samples, with an aging of about 5
Millihertz per day, 10ps/s white noise and 10ns/s of flicker noise:

phase = osc_synth(86400, -44e-6, 10e-12, 10e-9);

What I'd like to know - is that a "reasonable" model or is it just too far
off of reality to be useful? What could be changed or improved?

Best regards,
Matthias


_______________________________________________
time-nuts mailing list -- time-nuts@lists.febo.com -- To unsubscribe send an
email to time-nuts-le...@lists.febo.com To unsubscribe, go to and follow
the instructions there.

_______________________________________________
time-nuts mailing list -- time-nuts@lists.febo.com -- To unsubscribe send an 
email to time-nuts-le...@lists.febo.com
To unsubscribe, go to and follow the instructions there.
_______________________________________________
time-nuts mailing list -- time-nuts@lists.febo.com -- To unsubscribe send an 
email to time-nuts-le...@lists.febo.com
To unsubscribe, go to and follow the instructions there.

Reply via email to