Tuning the internal osccillator on AVR chips

 

If you try to use an AVR chip running off the internal oscillator (no external crystal or resonator), you will notice that it is not very accurat.
The datasheet states for most chips that the tolerance is +-10%.
This can be a problem for example if you are using serial communication.

However the internal oscillator can be calibrated or tuned to be within +-1% by setting the OSCCAL register.
Below are some methods to determine the value to be used.

 

TinyTuner 1

Also known as Poor Man's Tiny Tuner
Download TinyTuner1
Download it and place it where your librarys are stored.
You will also need a seril/usb converter to see the result. You can use an Arduino for this (See this)
Upload the Interactive_to_Serial.pde to the target

Follow the instructions in the sketch.
For the ATtiny84 they are like this (For ATtiny85 the pin numbers are different, see the sketch)
Connect PB3 / Pin 3 to receive on the serial converter
Connect PB4 / Pin 4 to transmit on the serial converter
Start your favorite terminal program (f.ex the serial monitor in your Arduino IDE, open the correct serial port, change the baud rate to 9600
Reset the processor by breefly connecting the reset pin PB3 to ground.
A welcome message like this should be displayed.
--------------------------------------------------------------------------------
Poor Man's Tiny Tuner
Slowly send lowercase 'x' to tune the oscillator...

  // Starting OSCCAL value is 0x9C

Step  OSCCAL
Continue sending single 'x' characters (no carriage-return; no line-feed) until the calibration finishes
You will see something like this (all tiny's are different, so your result will be different):
Poor Man's Tiny Tuner
Slowly send lowercase 'x' to tune the oscillator...

  // Starting OSCCAL value is 0x9C

Step  OSCCAL
  1     9F
  2     9E
  3     9F
.
.
 12     A0
 13     A0
 14     9F

Copy-and-paste the following line of code at the top of setup...

  OSCCAL = 0x9F;
In your sketch you place this value in the setup() like this:
void setup(){
  OSCCAL = 0x9F;
  //other code
}


http://forum.arduino.cc/index.php?topic=221296.0

 

TinyTuner2

What you need:

1.An Arduino UNO or similar board

2. The sketch TinyISP, which is a replacemment for the usual Arduino as ISP sketch found in the examples that comes with the Arduino IDE. You can download it here:
TinyISP

3. The TinyTuner2 library:
Download it here and place it where your librarys are stored.
TinyTuner2

4. The TinyDebugKnockBang library
Download it here and place it where your librarys are stored.
TinyDebugKnockBang


Setting it up:
In the _TinyISP_BuildOptions.h tab and copy/paste these lines


//Set to 1 if using KnockBang and comment out #include <SoftwareSerial.h> in TinyISP
#define RELAY_KNOCK_BANG_ENABLED 1

//Set to 1 if using Serial Relay, and uncomment #include <SoftwareSerial.h> in TinyISP
//Transmit on Arduino is A0
#define RELAY_SERIAL_ENABLED  0

//Set to 1 if using TinyTuner2
//Tuning signal pin 3 on UNO, connect to xtal2 on target
#define TUNING_SIGNAL_ENABLED  1


The tuning signal comes from pin 3 on the UNO so you need to connect a jumper wire from pin 3 on the UNO to XTAL2 pin on the target.
Now you can open one of the example sketches, that comes with the library and upload to your tiny.
If you use the sketch called PrintUsingKnockBang, the result can be seen in the serial monitor
Set the baudrate in the serial monitor to 19.200
Send an exclamationmark (!) to start the monitor, and you should see the OSCCAL value in the monitor
If you want to reset the target, send a (#)
The sketch will output to the serial monitor, where you can see the OSCCAL value to use.

 

Using serial communication

Another option is to use SoftwareSerial as an indicator for the tuning. If you load this sketch to your Attiny84 it will output the OSCCAL value to the serial monitor. A potmeter connected to PA3 will vary the OSCALL value, and you will see the output going from garbled to readable and garbled again. Then you pick a value in the midlle of the readable text.
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2,3 ); //rx=PB2,tx=PA7 setup of software serial

void setup() {
  mySerial.begin(9600);
}

void loop() {
  int val=analogRead(3); //PA3
  OSCCAL=val/4;
  mySerial.print("Osccal= ");  
  mySerial.println(OSCCAL,HEX);
  delay(200);
}

 

Using frequence counter

If you have a frequence counter you can use the sketch below. With a attiny84 @ 8MHz it will output 1MHz on pin5, if it is tuned correct. Again a potmeter is connected to PA3, which will alter OSCCAL. When you read 1 MHz on the frequence counter, you can read the OSCCAL value on the serial monitor.

 

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2,3 ); //rx=PB2,tx=PA7 setup of software serial

void setup(){
  mySerial.begin(9600);
  OSCCAL = 0x9F;  
  pinMode(5,OUTPUT);
  noInterrupts();  
  TCNT1 = 0;
  TCCR1A=0;
  TCCR1B=0;
  TCCR1B |=(1<<WGM12); //Start timer 1 in CTC mode Table 14.4
  TCCR1A |=(1<<COM1B0); //Timer1 in toggle mode Table 14-1
  TCCR1B |=(1<<CS10) ; //prescaler Table 14-5, no prescal
  interrupts();
  OCR1A=3; //CTC Compare value
 }

void loop(){
  int val=analogRead(3); //PA3
  OSCCAL=val/4;
  mySerial.print("Osccal= ");  
  mySerial.println(OSCCAL,HEX);
  delay(200);
}

Useful links:

For more info on TinyTuner2 see:this

For more info on TinyISP Arduino Forum

Configuring TinyTuner 1-2 for other AVR's Arduino Forum

 

Credits:

The Tiny core, TinyISP and TinyTuner are developed and maintained by Coding Badly