Pages: 1 2 [3] 4 5   Go Down
Author Topic: Can't find old topic on clock compensation  (Read 4286 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you mean to attach something?
Funny, I thought I did! Here's the download right from Atmel: http://www.atmel.com/Images/AVR4100.zip

EDIT: Whoa. I just now noticed that it's 4100, not 4001. I've been looking at that doc for a couple weeks now, and always thought it was 4001. Sorry for any unnecessary hassle!
« Last Edit: January 30, 2013, 03:24:50 pm by randomizer » Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4093
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you mean to attach something?
Funny, I thought I did! Here's the download right from Atmel: http://www.atmel.com/Images/AVR4100.zip

EDIT: Whoa. I just now noticed that it's 4100, not 4001. I've been looking at that doc for a couple weeks now, and always thought it was 4001. Sorry for any unnecessary hassle!

Ha! No worries, I didn't quite make a career out of searching for it!
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got it! I realized I was being too lame—expecting the Atmel code to work perfectly. This is how I set it up (with an interrupt cobbled from various people online):
Code:
void setup() {
delay(1000); //give watch crystal time to stabilize

// initialize Timer2
    cli();          // disable global interrupts
   
    ASSR = (1<<AS2);
   
    TCCR2A = 0;     // set entire TCCR2A register to 0
    TCCR2B = 0;     // same for TCCR2B
    TCCR2A |= (1 << WGM21); // Configure timer 2 for CTC mode
    TIMSK2 |= (1 << OCIE2A); // Enable CTC interrupt
    TCCR2B = (0<<WGM22)|(0<<CS22)|(0<<CS21)|(1<<CS20); //no prescaler
    OCR2A = 0;           //trigger interrupt every clock cycle
   
   
    // enable global interrupts:
    sei();

pinMode(9, OUTPUT);
}


ISR(TIMER2_COMPA_vect){
    digitalWrite(9,HIGH);
    digitalWrite(9,LOW);
}

void loop() {}

I get 16.38 kHz on my DMM. Assuming that it's not trying to say 16.384, that's ~120ppm (thanks Wolfram|Alpha!). So I don't see why my clock should have been so far off. Perhaps any inaccuracies in the chip get amplified with the prescaler? For the clock, I was prescaling by 1024 to get a 1Hz interrupt...

EDIT: Hmmmmmm. Setting OCR2A to 33 instead of 0 (this is really useful), I get 952.5 Hz instead of 1000 Hz. Or I was, until the DMM decided to quit on me. Aaaaaarg.
« Last Edit: January 30, 2013, 04:19:20 pm by randomizer » Logged

Global Moderator
Melbourne, Australia
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Code:
    OCR2A = 0;           //trigger interrupt every clock cycle

You can't usefully do that with no prescaler. Servicing an interrupt takes at least 19 clock cycles (see: http://www.gammon.com.au/interrupts), then your digital writes will take time, plus the time to leave the ISR.
Logged

http://www.gammon.com.au/electronics

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
expecting the Atmel code to work perfectly.

It will work perfectly, on its intended target.

All you need to do is to understand what the code is doing, read the datasheet of your own target and replicate the same on your target: aka what an application note is designed to do.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Code:
    OCR2A = 0;           //trigger interrupt every clock cycle

You can't usefully do that with no prescaler. Servicing an interrupt takes at least 19 clock cycles.
19 system clock cycles, yes? I'm clocking TIMER2 asynchronously. That's how the Atmel code did it:

Code:
#ifdef ATMEGA48_88_168
int main( void )
{
// Crystal clock will be output on PORTB3 (divided by 2)
DDRB |= (1<<PORTB3);

// Enable CTC mode with toggle on compare match. Precale 1 and top at 0
OCR2A  =  0;
TCCR2A = (0<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(0<<WGM20);
TCCR2B = (0<<WGM22)|(0<<CS22)|(0<<CS21)|(1<<CS20);
ASSR   = (1<<AS2);

while(1){}
}
#endif
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4093
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Code:
    OCR2A = 0;           //trigger interrupt every clock cycle

You can't usefully do that with no prescaler. Servicing an interrupt takes at least 19 clock cycles (see: http://www.gammon.com.au/interrupts), then your digital writes will take time, plus the time to leave the ISR.

Not using timer interrupts, just using output compare to make its frequency measurable on a pin. Well, half it's frequency is the best that can be done.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Global Moderator
Melbourne, Australia
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

19 system clock cycles, yes? I'm clocking TIMER2 asynchronously. That's how the Atmel code did it:

Oh, OK. Sure.
Logged

http://www.gammon.com.au/electronics

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
19 system clock cycles, yes?

No. The latency varies, depending on many factors, starting from as low as 2.
Logged

Global Moderator
Melbourne, Australia
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, I'm calling you on this one, dhenry. From the datasheet, which you keep recommending people read:



Since we do indeed use an interrupt vector, that is 7 cycles minimum. Add onto that the code in the ISR to, at the very least, save the status register (SREG) and that is another 3 cycles. On top of that you have to push any registers you are planning to use, unless your ISR doesn't do anything.

So, no, it is not "as low as 2".

I was wrong about the 19 cycles. That is the time take, from looking at actual code generated, to leave the ISR. It is 23 cycles to enter it. That would probably vary depending on what the ISR does. The more things it does, the more registers the compiler has to save (and restore later).

Figures, disassembly, etc. on this page:

http://www.gammon.com.au/interrupts
Logged

http://www.gammon.com.au/electronics

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's interesting—with OCR2A set to 0 or 1, I get, as expected, half of 32768—1638(4). But when I up OCR2A to ~31,32,33 to get a 1kHz frequency, I get a 1kHz frequency (or close to it)—not 500Hz. I think that's because in the interrupt, I have
Code:
digitalWrite(9,HIGH);
    digitalWrite(9,LOW);
instead of
Code:
if (toggle2){
    digitalWrite(9,HIGH);
    toggle2 = 0;
  }
  else{
    digitalWrite(9,LOW);
    toggle2 = 1;
  }
which is what it was originally. At the relatively high frequencies, the minuscule gap between HIGH and LOW is... something, and at lower frequencies it... isn't. Not really sure what I'm saying exactly, but I know what I mean. smiley
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At OCR = 0, you get 16khz;
OCR = 1, you get 8khz;
OCR = 31, you get 0.5khz.
...
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, with the original code (using the toggle) I find that OCR=1 generates 1/2 of 16384Hz (interestingly, so does OCR=0). At least, it should. I'm reading 8190, which is ~250ppm off—way more than the ~40 expected from the temperature. That could well be errors in the DMM—I don't really see what else, unless the crystal is picking up parasitic capacitance through the air from the breadboard rails underneath it.

That translates to 21 seconds per day slow, if I define a second as 8292 interrupts. (Or I could just code it as 8190, and assume that my meter isn't off.) That's not ideal, but it's not the second-every-five-minutes loss I was having before.

One thing I've determined: The calculator I linked to earlier rounds the answer it spits out—when I say I want 4 kHz, for example, it tells me I can use no prescaler and OCR=8 and have 0% error, but the fact is I will have error because everything's in factors of two. Nominal 8 kHz is actually 8192 Hz. This is possibly why the clock was so slow earlier.
Logged

Global Moderator
Melbourne, Australia
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Get the timer to toggle a pin, don't rely on an ISR to do it.
Logged

http://www.gammon.com.au/electronics

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Get the timer to toggle a pin, don't rely on an ISR to do it.

What? I thought the ISR was the manifestation of the timer. Are you saying something like this?
Code:
if (TCNT2 = 3){
//toggle pin
}

Because the reason I wanted an interrupt in the first place is so I can sleep the chip in the meantime. I don't know if it's really worth the 17 mA, especially when there'll be lots of LEDs on anyway. But that was my idea.
« Last Edit: January 30, 2013, 09:17:55 pm by randomizer » Logged

Pages: 1 2 [3] 4 5   Go Up
Jump to: