Go Down

Topic: Using the internal 8MHz oscillator? Library to tune it and keep serial working. (Read 183 times) previous topic - next topic

cirthix

I started playing with OSCCAL and got carried away.  OSCCAL lets you tune the internal 8MHz oscillator roughly between 5MHz and 15MHz.  While it isn't a high-precision clock, it turns out that you *can* use the watchdog oscillator to tune OSCCAL and it seems to work pretty well.

This library tunes OSCCAL to a target frequency and reconfigures Serial.begin() to keep the same real baudrate at the new speed.  It is also very simple to use.

Output:
Hello from setup().
Default Clock: 8000000
OC Clock: 15587208
16M Clock: 15621856
14M Clock: 14057328
12M Clock: 11963320
10M Clock: 10039136
8M Clock: 8000000
6M Clock: 6008744
4M Clock: 5103016

Code: [Select]

#include <avr/wdt.h>
#include "Overclock.h"

const uint32_t SERIAL_BAUD = 115200 ;  // Recommend 38400, 19200, or 9600 for better stability.  115200 works for me, but may be less stable in some setups.


Overclock my_Overclock_object=Overclock((uint32_t)14000000, (uint32_t)SERIAL_BAUD);

ISR(WDT_vect) {
my_Overclock_object.WatchdogFired();
// Add your other watchdog code here.
}


< somewhere later on>

  my_Overclock_object.SetClockSpeedOC();
or
  my_Overclock_object.SetClockSpeed((uint32_t)12000000);


 




Full code and example can be found at:

https://github.com/cirthix/Overclock

Robin2

Does you library affect the timing of millis() and micros()

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cirthix

Yes, it will.

Does it have a way to compensate? Not built in, but not hard to deal with.

AFAIK (heard but havent looked), the delay and delayMicroseconds functions are determined at compile-time.  Would be nice to have a way to provide the current clockspeed.

I suppose it could be added (without modifying the delay libs) by either:

1) Add functions for delay and delayMicroseconds.  These functions first change clock back to stock, then do the delay, then change to whatever it was before.  This has the downside of breaking buffered serial communications or causing interrupts to not run at full speed.

2) Calculate an equivalent delay based on the ratio of stock clock vrs new clock, then do a delay with the new value.

3) Because calibration against the watchdog timer is not an exact process anyway, you could let the compiler figure out an equivalent delay based on the set point (so long as the requested/expected speed is within the OSCCAL calibration range).  This incurs no performance penalty but will be slightly less accurate.  Will it matter based on the other inaccuracies in the system?  Probably not.  Using the example,


const uint32_t SERIAL_BAUD = 115200 ;
const uint32_t OVERCLOCK_SPEED = 15000000; //Note: should be within the OSCCAL calibration range.

Overclock my_Overclock_object=Overclock(OVERCLOCK_SPEED, SERIAL_BAUD);
.
.
.
  delay(1000*(OVERCLOCK_SPEED/F_CPU));  This should delay for 1 second if you're at the overclocked speed.


Maybe I should add an IsStock() function so you can do something like this with very little overhead?


if(my_Overclock_object.IsStock()) {delay(delayvalue);}
else {delay(delayvalue*(OVERCLOCK_SPEED/F_CPU)); }




Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy