Using external clock generator instead of Arduino Uno's internal clock?

I was wondering if anyone knew of a way to "replace" the Arduino Uno's internal 16MHz cock with an external clock generator. We have a CG635 (Synthesized Clock Generator - CG635) and would like to run the Arduino off of this clock instead of the internal clock. We will be running the CG at 10MHz.

Is there any simple way to do this?

csnsc14320:
I was wondering if anyone knew of a way to "replace" the Arduino Uno's internal 16MHz cock with an external clock generator. We have a CG635 (http://www.thinksrs.com/products/CG635.htm) and would like to run the Arduino off of this clock instead of the internal clock. We will be running the CG at 10MHz.

Is there any simple way to do this?

First the 16Mhz clock source for a arduino is external not internal, it's setup to utilize an external 16Mhz crystal or ceramic resonator.

Second, yes the chip can be setup to utilize an external TTL voltage level clock as the clock source. Section 6.8 of the 328p datasheet covers this. Note that as well as disconnecting the existing crystal one needs to change the fuse settings for the chip per the datasheet. Changing default fuse settings can not be done from within the Arduino IDE software, but would require a proper chip programmer, software and procedure steps.

Lefty

retrolefty:
First the 16Mhz clock source for a arduino is external not internal, it's setup to utilize an external 16Mhz crystal or ceramic resonator.

Second, yes the chip can be setup to utilize an external TTL voltage level clock as the clock source. Section 6.8 of the 328p datasheet covers this. Note that as well as disconnecting the existing crystal one needs to change the fuse settings for the chip per the datasheet. Changing default fuse settings can not be done from within the Arduino IDE software, but would require a proper chip programmer, software and procedure steps.

Lefty

This datasheet? http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
There doesn't seem to be a section 6.8 on this? =\

Is there any way to do this without removing the Arduino's crystal? I thought I saw someone try to do this using the attachInterrupt command, but I have never used that and am not sure how that would work.

If I do need to remove the crystal and change the fuse settings, how difficult is that to come by?

Thanks for the quick response :slight_smile:

Note that your millis() clock will run at the wrong rate unless the system clock is 16MHz or 8MHz, EVEN IF YOU SPECIFY THE NEW CLOCK FREQUENCY.

In that version of the data sheet you want section 8: System Clock and Clock Options

This datasheet? http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
There doesn't seem to be a section 6.8 on this? =\

Section 8.8 (page 34) of that version of the datasheet.

Is there any way to do this without removing the Arduino's crystal? I thought I saw someone try to do this using the attachInterrupt command, but I have never used that and am not sure how that would work.

attachInterrupt (or interrupts in general) has nothing to do with setup of the processors clock source.

If I do need to remove the crystal and change the fuse settings, how difficult is that to come by?

Not something easy to do for a beginner. As I said changing fuse settings requires hardware and software not built into the arduino board or the arduino IDE software. The datasheet has a section of fuse selection and setting, section 27 covers the subject.

Lefty
Thanks for the quick response

johnwasser:
Note that your millis() clock will run at the wrong rate unless the system clock is 16MHz or 8MHz, EVEN IF YOU SPECIFY THE NEW CLOCK FREQUENCY.

In that version of the data sheet you want section 8: System Clock and Clock Options

Are you sure of that? I thought the core libraries utilized the f_cpu=xxxxxxxL variable in the boards.txt file to setup the timer used for millis() and micros() ? So wouldn't he just have to modify the boards.txt entry to whatever clock speed he setup his external clock generator for? A little awkward but certainly doable.

Lefty

retrolefty:

johnwasser:
Note that your millis() clock will run at the wrong rate unless the system clock is 16MHz or 8MHz, EVEN IF YOU SPECIFY THE NEW CLOCK FREQUENCY.

Are you sure of that?

Nearly. To work correctly, the millis code requires F_CPU to be an even power of two (16, 8, 4, ...). So, a few more frequencies are supported.

I thought the core libraries utilized the f_cpu=xxxxxxxL variable in the boards.txt file to setup the timer used for millis() and micros() ?

They do. However...

The Arduino folks wanted an efficient millisecond clock and as many PWM pins as possible. Those three goals drive the structure of the code and limit the clock speed choices.

The simple fact is that the code in wiring.c requires the processor clock to be a power of 2 (1 MHz, 2 MHz, ... 8 MHz, 16 MHz). To support arbitrary clock speeds requires code that is more complicated (less efficient) and, in some cases, giving up PWM on timer 0.

So wouldn't he just have to modify the boards.txt entry to whatever clock speed he setup his external clock generator for?

For non-power of two frequencies, the code in wiring.c has to be modified.

I suspect the millis code could be modified to support a wider range of frequencies (like 20 MHz) but I don't think it can be written to support an arbitrary frequency. The problem is fourth grade math: fractions. Some fractions are easy to determine at compile time like the one currently used in millis (1/1024). Some fractions are not so easy to determine even by a human (what fractions are appropriate for a 14.7456 MHz frequency).

retrolefty:
I thought the core libraries utilized the f_cpu=xxxxxxxL variable in the boards.txt file to setup the timer used for millis() and micros() ? So wouldn't he just have to modify the boards.txt entry to whatever clock speed he setup his external clock generator for?

It won't work. I looked in the core code (wiring.c) and it makes some big assumptions. It first assumes that the value is a multiple of 1,000,000 when it calculates clockCyclesPerMicrosecond(). In micros() it integer divides 64 by clockCyclesPerMicrosecond(). If the value is not an integer factor of 64 that result will get truncated. 10 MHz will be treated like it was 10.666666 MHz (64/10 -> 6.4 -> 6 and 64/6 = 10.666). delay() calls micros() so it will be off the same way. I'm looking at the code now and it looks like millis() might work but I can't be sure. The delayMicroseconds() code is the worst: if the value of F_CPU is not equal to 16000000L it was assumed to be 8000000L. Only those two values work correctly.

I'm not sure how the baud rate calculations work with an unusual clock rate.