Driving the Arduino Clock with a 3.3V TCXO

In order to decrease the bandwidth (and thus the increase noise tolerance) for my DCF77 project The Clock | Blinkenlight I need a more accurate oscillator. My idea was to search for a 16 MHz TCXO. However I found only 3.3V types, none with 5V. Now I wonder if a 3.3V oscillator (decoupled with a cap) would be able to drive the Atmega clock. I looked up the datasheet and it seems that this might not be sufficient.

Of course I can add a level shifter. However I wonder if there would be some neat trick to avoid a level shifter. Are there any ideas / hints on this topic?

How accurate is "more accurate"? Are you using a stock board or a custom designed one?

The spec for the XTAL1 pin (external clock input) is 0.7Vcc for a high level, so if the MCU is running at 5V, then that would be 3.5V, which a 3.3V external circuit is not likely to provide.

Does the MCU have to run at 16MHz? One option would be to run it at 8MHz and 3.3V. Another would be to use a crystal for the system clock.

328p runs fine @3V3 and 16MHz. I do not use 5V for ages..

Cheap TCXOs easily achieve 2.5ppm, standard crystals usually achieve something around 30ppm, sometimes slightly better and often worse.

Lets say the board would be customized. That is I will desolder the crystal and add a tcxo. If necessary I will fire up eagle and design a custom board. But I doubt that this would be necessary.

And 328p @16 MHz is outside the spec. If it works for someone else fine. But I would rather stay in the specified SOA.

And 328p @16 MHz is outside the spec.

:slight_smile:

PS:Are you able to lock on the DCF77 carrier??

Yes and no. The DCF77 module does lock to the carrier. However I do not want to use a PLL because I want to retain the precise clock even when the carrier gets lost. The point is that I am optimizing for noisy reception. And there the issue is that the carrier will not be reliable. If I can get 16 times better clock precision to what I have now I can reduce the bandwidth accordingly to get 6dB better noise tolerance.

Not that it would really matter any more. I just want to overdo it slightly. If I would want really overdo it I would run the Arduino from a 10 MHz rubidium clock :wink:

The DCF77 module does lock to the carrier.

It does not, the module just does an AM demodulation to get the time information. The carrier is not 100% AM modulated so the carrier is always there. Locking on the 77.5kHz carrier would be nice to have as it is cesium precise..

The RECEIVED 77.5 kHz is way less precise than you might imagine. The issue is that due to run time differences in the atmosphere is has a crappy short term stability. So it is completely useless to extract a controller clock from it. The only way to use it for something reasonable is to have a precise local clock and to lock the local clock to DCF77 with a very long time constant. The optimal time constant can of course be computed by the comparing the Alan deviations.

I still would like to know if there is some way to avoid the level shifter. Maybe by using a resonant circuit. How would I have to set this up? Or is this considered unreliable?

The X1 input does not require a 5Vp-p amplitude, 1V is ok. So simply connect it via a 10nf 100pF-1nF ceramic capacitor and leave the 22pF to ground there. Do experiment, be creative, have fun :slight_smile:

You might also add a pullup to 5V... start @ 10K. It will increase the output by the protection diode voltage drop, only a few hundred uA should be necessary.. Was an old trick to get RTL and later TTL Logic interfaced across multiple supply voltages. If 10 K is too high.. not enough drive, you could go as low as 4K7 or about 900 uA with no issues.. try it it can't hurt anything although a scope is best for looking at the rise time.

Doc

@Pito: do you have any datasheet refererence on this?

@Docedison: very interesting indeed.

My thought was to reuse the existing crystal oscillator as a "transformer". The idea would have been to disconnect the X2 output and connect the cap + crystal to ground. Then disconnect the former ground connection, that is the connection between the two caps and drive the 3.3V output into this. If this resonates the X1 connection should see a full swing amplitude.

Has anyone ever tried this?

Lower Vcc to the oscillator?
Part TCXO such as

has Vout-high of 0.8 * Vcc.
At 3.3V, that is 2.64V.
Solving for Vcc:
2.64V = 0.7V * Vcc-uC
Vcc-uC = 3.77V.
Extrapoloting into Figure 29.3 of the datasheet, 3.77V yields a max operating speed of 15.94MHz.
Right on the edge, eh?
So run the oscillator output thru a logic gate with open drain output pulled up to 5V to achieve full swing:
http://www.digikey.com/product-detail/en/74LVC1G38GW,125/568-7769-1-ND/2753913

pito:
The X1 input does not require a 5Vp-p amplitude, 1V is ok. So simply connect it via a 10nf 100pF-1nF ceramic capacitor and leave the 22pF to ground there. Do experiment, be creative, have fun :slight_smile:

The XTAL1 pin does have slightly different specs, but not 1V, the way I read it.

How about a Schmitt Trigger? See section 13: http://www.nxp.com/documents/data_sheet/74HC_HCT14.pdf It could result in something other than a 50% duty cycle, not sure if that's important.

I now decided to drive it with a 5V 32768 Hz TCXO (DS3231 that is) into T1.

The crucial part is this piece of code.

SR(TIMER1_COMPA_vect) {
    // input is 32768 Hz but we want 1000 Hz
    // 32768 / 1000 = 32 + 768/1000 = 32 + 96/125
    // we use Bresenham Algorithm to deal with the fractional steps
    static uint8_t fractional_steps = 0;
    
    if (fractional_steps >= 125-96) {
        // 125-96 = 29 --> this branch will be processed 96 out of 125 times
        fractional_steps -= (125-96);
        OCR1A = 32;
    } else {
        // this step will be processed 125-96 = 29 out of 125 times
        fractional_steps += 96;
        OCR1A = 31;
    }
    
    process_one_sample();
}

void init_timer_1() {
    // Pin 5 == T1 input
    pinMode(T1_input_pin, INPUT);
    
    // no outputs, CTC mode using OCR1A
    TCCR1A = 0;
    // CTC mode using OCR1A, external clock on T1 (PD5, Arduino D5), on rising edge
    TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS11) | (1<<CS10);

    // input is 32768 Hz but we want 1000 Hz --> 32768/1000 ~ 32
    // 32 -1 = 32
    OCR1A = 31;
    TCNT1 = 0;

    // enable Timer 1 interrupts
    TIMSK1 = (1<<OCIE1A);
}

It even worked on the first try. Now I can narrow down the bandwith / increase SNR again one step further :slight_smile: