Go Down

Topic: Timer2 Interrups REFUSE to work! :( (Read 5 times) previous topic - next topic

TheStig

Ok, will read through the page. Looks very interesting and I am understanding most of what I read so far.

I /can/ create a debug version, sorta. Mainly the only thing I have that does serial is an arduino board (Uno), or my avrisp mkii/UsbASP (which I dont know if it does serial).

I suppose I could just program the board to output serial, and then just connect RX and TX to the respective/opposite (RX to TX, TX to RX, etc) pins on my Uno board? (I assume RX and TX are all thats needed for the serial output?). That shouldnt be hard. If I am right about the serial comms, it shouldnt be hard...

Nick Gammon

#21
Sep 19, 2012, 05:36 am Last Edit: Sep 19, 2012, 07:06 am by Nick Gammon Reason: 1
Let's get down to basics. You want the timer interrupt to work, right? All the rest is mumbo-jumbo for now. Here is a cut-down sketch:

Code: [Select]

#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/power.h> //Needed for powering down perihperals such as the ADC/TWI and Timers

const byte LED = 8;

//The very important 32.686kHz interrupt handler
ISR (TIMER2_OVF_vect)
{
}

//The interrupt occurs when you push the button
void buttonPress (void)
{
}

void setup()
 {                
 pinMode (LED, OUTPUT);  
 digitalWrite (2, HIGH);  // pull-up

 //Power down various bits of hardware to lower power usage  
 set_sleep_mode (SLEEP_MODE_PWR_SAVE);

 //Shut off ADC, TWI, SPI, Timer1

 ADCSRA &= ~ _BV (ADEN);     // Disable ADC
 ACSR = _BV (ACD);           // Disable the analog comparator
 DIDR0 = 0x3F;               // Disable digital input buffers on all ADC0-ADC5 pins
 DIDR1 = _BV (AIN1D) | _BV (AIN0D); //Disable digital input buffer on AIN1/0

 power_twi_disable();
 power_spi_disable();
 power_usart0_disable();
 power_timer1_disable();
 
 //Setup TIMER2
 TCCR2A = 0;
 TCCR2B = _BV (CS22) | _BV (CS21) | _BV (CS20);
 ASSR   = _BV (AS2);         // Enable asynchronous operation
 TIMSK2 = _BV (TOIE2);       // Enable the timer 2 interrupt

 attachInterrupt (0, buttonPress, FALLING);
 }

void loop()
 {
 digitalWrite (LED, LOW);
 sleep_mode();   //  Stop everything and go to sleep. Wake up if the Timer2 buffer overflows or if you hit the button
 digitalWrite (LED, HIGH);  
 }


On my Uno (which has a 16 MHz resonator) this outputs a pulse on pin 8 with a period of 16.327 mS which is what you expect.

Code: [Select]
1/16 MHz = period of 62.5 nS
62.5 nS * 1024 * 256 = 16.384 mS


(The figure isn't exact, but the resonator would be off by about 0.2% or so).

The 1024 is the prescaler and the 256 is how many counts the timer does before overflowing.

An LED on pin 8 glows faintly (you could make it brighter by putting a small delay after writing it high.

So I suggest you test that. If you can't get the LED to glow there is something fundamentally wrong with the hardware.

Nick Gammon

For my own interest I wired up a "bare bones" board and uploaded that exact program. It worked!



Note that there was a gap of 8 seconds between pulses.

This is the board:




The current drain during the sleeping part was 21 uA.

You can save a considerable amount of power by turning off brown-out enable. This amended sketch does that:

Code: [Select]

#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/power.h> //Needed for powering down perihperals such as the ADC/TWI and Timers

const byte LED = 8;

//The very important 32.686kHz interrupt handler
ISR (TIMER2_OVF_vect)
  {
  }

//The interrupt occurs when you push the button
void buttonPress (void)
  {
  }

void setup()
  {               

  pinMode (LED, OUTPUT); 
  digitalWrite (2, HIGH);  // pull-up

  //Power down various bits of hardware to lower power usage 
  set_sleep_mode (SLEEP_MODE_PWR_SAVE);
  sleep_enable();

  //Shut off ADC, TWI, SPI, Timer1

  ADCSRA &= ~ _BV (ADEN);     // Disable ADC
  ACSR = _BV (ACD);           // Disable the analog comparator
  DIDR0 = 0x3F;               // Disable digital input buffers on all ADC0-ADC5 pins
  DIDR1 = _BV (AIN1D) | _BV (AIN0D); //Disable digital input buffer on AIN1/0

  power_twi_disable();
  power_spi_disable();
  power_usart0_disable();
  power_timer1_disable();
 
  //Setup TIMER2
  TCCR2A = 0;
  TCCR2B = _BV (CS22) | _BV (CS21) | _BV (CS20);
  ASSR   = _BV (AS2);         // Enable asynchronous operation
  TIMSK2 = _BV (TOIE2);       // Enable the timer 2 interrupt

  attachInterrupt (0, buttonPress, FALLING);
  }  // end of setup

void loop()
  {
  digitalWrite (LED, LOW);
  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);  // turn on brown-out enable select
  MCUCR = _BV (BODS);        // this must be done within 4 clock cycles of above
  sleep_cpu ();              // sleep within 3 clock cycles of above
  digitalWrite (LED, HIGH); 
  }  // end of loop


Running that sketch, while the LED was not flashing (ie. during the 8 second interval) it used 1.4 uA of current.

Note that the flash is extremely hard to see. Even with a higher-power LED it is almost invisible. But the logic analyzer detected it.

Nick Gammon


Nick Gammon

Further tests show that if you drop the supply voltage to 3.3V (which may be reasonable) you can reduce the sleep power consumption to around 1 uA.

Go Up