Pages: 1 ... 3 4 [5]   Go Down
Author Topic: Can't find old topic on clock compensation  (Read 4033 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18810
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just to prove it to myself, I made this amended sketch:

Code:
#include <avr/sleep.h>
#include <avr/power.h>

const byte tick = 3;

// interrupt on Timer 2 compare "A" completion - does nothing
EMPTY_INTERRUPT (TIMER2_COMPA_vect);

void setup()
 {
  pinMode (tick, OUTPUT);
  
  // clock input to timer 2 from XTAL1/XTAL2
  ASSR = _BV (AS2);  

  // set up timer 2 to count up to 32 * 1024  (32768)
  TCCR2A = _BV (WGM21);                             // CTC
  TCCR2B = _BV (CS20) | _BV (CS21) | _BV (CS22);    // Prescaler of 1024                                  
  OCR2A =  31;              // count to 32 (zero-relative)                  

  // enable timer interrupts
  TIMSK2 |= _BV (OCIE2A);
  
  // disable ADC
  ADCSRA = 0;  
  
  // turn off everything we can
  power_adc_disable ();
  power_spi_disable();
  power_twi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_usart0_disable();
  
  // full power-down doesn't respond to Timer 2
  set_sleep_mode (SLEEP_MODE_PWR_SAVE);  

  // get ready ...
  sleep_enable();
  
  }  // end of setup

void loop()
  {

  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);
  MCUCR = _BV (BODS);
  
  // sleep, finally!
  sleep_cpu ();  

  // we awoke! pulse the clock hand
  digitalWrite (tick, ! digitalRead (tick));
  
  }  // end of loop

With the 32.768 KHz crystal the LED (on pin 3 toggles every second). Now as this is under software control, you could do anything you want in the main loop, instead of the digitalWrite (eg. update a display).

The current consumption, when the LED is not lit, was 1.46 uA, which is pretty low.

(edit) And 1.1 uA at 3.3V power supply.
« Last Edit: February 01, 2013, 12:25:56 am by Nick Gammon » Logged


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

Just to prove it to myself, I made this amended sketch:

Okay, I am seriously upset/confused right now.

When I use your code (with the EMPTY_INTERRUPT), changing the value of OCR2A changes the frequency of the blinking. As expected.

If I change EMPTY_INTERRUPT to an ISR, move the digitalWrite up into the ISR, and comment out all the sleepy-stuff, changing OCR2A has no effect at all. Zip. Nada. Using the exact same TCCR2A/B values. The frequency is always the base frequency of the prescaler, as if OCR2A is 0.

What am I not seeing here?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18810
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Post the amended sketch, don't just describe it.
Logged


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

Code:

#include <avr/sleep.h>
#include <avr/power.h>

const byte tick = 11;

// interrupt on Timer 2 compare "A" completion - does nothing
ISR(TIMER2_COMPA_vect) {
  digitalWrite (tick, ! digitalRead (tick));
}

void setup()
 {
  pinMode (tick, OUTPUT);
 
  // clock input to timer 2 from XTAL1/XTAL2
  ASSR = _BV (AS2); 

  // set up timer 2 to count up to 32 * 1024  (32768)
  TCCR2A = _BV (WGM21);                             // CTC
  TCCR2B = _BV (CS20) | _BV (CS21) | _BV (CS22);    // Prescaler of 1024                                 
  OCR2A =  15;              // count to 32 (zero-relative)                 

  // enable timer interrupts
  TIMSK2 |= _BV (OCIE2A);
/* 
  // disable ADC
  ADCSRA = 0; 
 
  // turn off everything we can
  power_adc_disable ();
  power_spi_disable();
  power_twi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_usart0_disable();
 
  // full power-down doesn't respond to Timer 2
  set_sleep_mode (SLEEP_MODE_PWR_SAVE); 
 
  // get ready ...
  sleep_enable();
  */
  }  // end of setup

void loop()
  {
/*
  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);
  MCUCR = _BV (BODS);
 
  // sleep, finally!
  sleep_cpu (); 

  // we awoke! pulse the clock hand
  digitalWrite (tick, ! digitalRead (tick));
  */
  }  // end of loop

Always blinks at 15.99 Hz, regardless of ACR2A.
Thanks!
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18810
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

To save fetching out the board with the extra crystal, I tried on my Uno this slight variation:

Code:
const byte tick = 11;

// interrupt on Timer 2 compare "A" completion
ISR(TIMER2_COMPA_vect)
  {
  digitalWrite (tick, ! digitalRead (tick));
  }

void setup()
 {
  pinMode (tick, OUTPUT);
  
  // clock input to timer 2 from XTAL1/XTAL2
  ASSR = _BV (AS2);  

  // set up timer 2 to count up to 32 * 1024  (32768)
  TCCR2A = _BV (WGM21);                             // CTC
  TCCR2B = _BV (CS20) | _BV (CS21) | _BV (CS22);    // Prescaler of 1024                                  
  OCR2A =  63;              // count to 64 (zero-relative)                  

  // enable timer interrupts
  TIMSK2 |= _BV (OCIE2A);
  }  // end of setup

void loop() { }

This gave a frequency of 122 Hz as predicted by the theory:

Code:
1 / (1/16e6 * 1024 * 64) / 2 = 122.0703125

You divide by 2 because it takes two pulses to complete one cycle. Changing OCR2A changed the frequency.
Logged


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

I've still got the problem. Changing the prescaler changes the frequency; changing OCR2A changes absolutely nothing. I guess there's something screwy inside the chip, and I'll just work around that in my code.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18810
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Are you measuring the right pin?

Sometimes I found that where the OCR2A line was affected thing. Try moving that line earlier up.
Logged


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

Well! I tried moving the OCR2A line up; nothing changed. I added the TCCR2A = 0 and TCCR2B = 0 lines at the top and it works! Which is strange, because in other non-working sketches I've tried it hasn't worked. Must've been a combination of that and moving the OCR2A line.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18810
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Adding those lines stops the timer. I think in some modes the OCR2A changes are buffered, so it makes some sense to stop it first.
Logged


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