Timer2 Interrups REFUSE to work! :(

Watch is sleeping to save massive amounts of power.

Not working saves even more power? Just trying to eliminate possible areas of conflict.

there is a button interrupt attached to pin D2 i believe.

I'd check... I also don't see where you connect that ISR to that pin. The attachInterrupt() function is usually called to make an association.

I think, at this point, that we need to see all of your code.

This is timed by generating interrupts on the clock pins.

Which pins would that be? What code, of yours, is supposed to respond to those interrupts?

We need to see your circuit to understand this, some of your code suggests you are clocking timer2's prescaler at 32768Hz, is this true and if so how?

Ok, here goes

Code is attached in arduino formatting (as INO file). Code also references a couple LIBs but they should be in arduino program by default. This is literally all the code i have on this, soo...

Also attached is the schematic and rough board layout in EAGLE.

Posted by: MarkT
Insert Quote
We need to see your circuit to understand this, some of your code suggests you are clocking timer2's prescaler at 32768Hz, is this true and if so how?

To be honest, I have no idea what you just said. I am just trying to get timer2 to inturrupt every 8s from a 32.768 crystal. Most of my code was copied from sparkfuns example, so it should work, but as I said, hardware and software level inturrupts are not exactly my strongpoint.

Posted by: PaulS
Not working saves even more power? Just trying to eliminate possible areas of conflict.

Yep :D, well at least at the moment...

I'd check... I also don't see where you connect that ISR to that pin. The attachInterrupt() function is usually called to make an association.
I think this deos it

//Setup external INT0 interrupt
  EICRA = (1<<ISC01); //Interrupt on falling edge
  EIMSK = (1<<INT0); //Enable INT0 interrupt

Which pins would that be? What code, of yours, is supposed to respond to those interrupts?
Pins TOSC1 & TOSC2 if I got the names right. Just XTAL1 and XTAL2 on the schematic. This code is what is supposed to be run when it interrupts.

SIGNAL(TIMER2_OVF_vect){
  seconds += 8; //We sleep for 8 seconds instead of 1 to save more power
  //seconds++; //Use this if we are waking up every second

  if(seconds > 59){
    minutes++;
    seconds = seconds - 59;
  }

  if(minutes > 59){
    hours++;
    minutes = minutes - 59;
  }

BinaTime2.ino (28.4 KB)

Watch-v13.brd (60.6 KB)

Watch-v13.sch (164 KB)

Can't read those files, despite having Eagle, wrong version - if you export as image then its much more friendly to us (not everyone uses Eagle). In general it helps to present all the relevant information (provide links, photos, etc)

Looking at the bigTime thing on sparkfun it seems all confused (comments about not using delay / delayMicroseconds, yet it does use them. It seems to be using a non-standard fuse option on the ATmega, namely the internal RC oscillator (allowing TOSC1/2 to be used as timer clock). Is your microcontroller suitable programmed with the right fuse options? Note if using the internal oscillator you may have to use an ICMP programmer to upload sketches (I may be a bit rusty about this).

The quality control on sparkfun site is not the best I've seen BTW, so I wouldn't trust the online files to necessarily be up-to-date or even self-consistent (if not tell them so they notice and fix it for others).

Other comments on the sparkfun page imply a standard Arduino Mini 8MHz can be used, which obviously is not the case as the crystal is hard-wired on that board yet the sparkfun schematic shows a 32,768Hz xtal, not an 8MHz one.

Images! :slight_smile:

I used an ICSP programmer to set the fuse settings accordingly. I think they are correct, AVR studio 4 says its using the internal oscillator. I will email sparkfun and see if that is the most recent version of the code and see what they are doing- anything specific i need to ask?

I'm a little curious about this bit:

  if(seconds > 59){
    minutes++;
    seconds = seconds - 59;
  }

  if(minutes > 59){
    hours++;
    minutes = minutes - 59;
  }

Aren't there 60 seconds to a minute, and 60 minutes to an hour?

Hmmm, have you proof that the 32768 xtal is actually oscillating? Have you calculated load caps as per table 8-8 and associated text in the datasheet? Have you read section 17.9 of the datasheet and checked the code is DTRT?

Why do you have 0.1 uF caps between the crystal and earth? That wasn't in the Sparkfun circuit.

Here, to save other people searching for it: BigTime Watch Kit - KIT-10870 - SparkFun Electronics

They are not used at the moment, they are just places for xtal load caps but I havnt loaded the crystal at all.


I'm a little curious about this bit:

Code:
if(seconds > 59){
minutes++;
seconds = seconds - 59;
}

if(minutes > 59){
hours++;
minutes = minutes - 59;
}

Aren't there 60 seconds to a minute, and 60 minutes to an hour?

Yes, but I am using > not >=. So anything greater than 59 (60), will go back down to 1. Course I need to add 0s to it but havnt yet.


Hmmm, have you proof that the 32768 xtal is actually oscillating? Have you calculated load caps as per table 8-8 and associated text in the datasheet? Have you read section 17.9 of the datasheet and checked the code is DTRT?

I don't have an oscilloscope but I can check (earliest I could do it is tomorrow). I think somewhere else in the data sheet it says not to use load crystals for that slow of a crystal, I have not added them (but can).

Read through 17.9 and didnt undertand much of it :frowning: , or rather, I understood most of it, just not how to create a practical example.

Thank you all so much with your help thus far, I really appreciate it and am eager to learn more. Sorry my coding is not up to par, but i really dont code that often so I never quite "learned" it. Mostly just taught myself...

May I suggest you learn how to use the "quote" button above the posting box? Putting your comments and other people's all together looks confusing. eg.

Yes, but I am using > not >=. So anything greater than 59 (60), will go back down to 1. Course I need to add 0s to it but havnt yet.

60 is not the only thing greater than 59. For example, 61 is. And since you are adding 8 it is more likely you will get from 56 to 64.

  seconds += 8; //We sleep for 8 seconds instead of 1 to save more power
  //seconds++; //Use this if we are waking up every second

  if(seconds > 59){
    minutes++;
    seconds = seconds - 59;
  }

My point is that after adding 1 to the number of minutes, surely you need to subtract 60 from the number of seconds? Not 59?

They are not used at the moment, they are just places for xtal load caps but I havnt loaded the crystal at all.

So the circuit you posted is not the one you are using?

60 is not the only thing greater than 59. For example, 61 is. And since you are adding 8 it is more likely you will get from 56 to 64.

I am adding 8s, but taking off 60 will keep the timing in check. If I reset every 60, the timer could be anywhere up to 8 seconds off. Makes sense to me.
Eg:
Seconds = 56,
then the timer overflows, seconds now = 64. Seconds - 60 = 4. Now if I went to 0 on that, what happened to the extra 4 seconds the timer counted??

My point is that after adding 1 to the number of minutes, surely you need to subtract 60 from the number of seconds? Not 59?
True, thanks for correcting me on that. Guess I got messed up on timing in my head :stuck_out_tongue: . Wasnt exactly having a great day when I wrote it :smiley:

So the circuit you posted is not the one you are using?

Everything is the exact circuit I am using, but I put the load caps in for my board design, just in case I needed some load caps on the crystal. They are merely placeholders. Sorry for the confusion this might have caused.

I don't see any variables being declared as volatile. If an interrupt service routine is going to update variables they should be marked as volatile.

Specifically:
seconds -- TIMER2_OVF_vect
minutes -- TIMER2_OVF_vect
hours -- TIMER2_OVF_vect
show_the_time -- INT0_vect

Like this?

volatile long seconds = 54;
volatile int minutes = 24;
volatile int hours = 3;

So... volatile just means they are handled from RAM instead of being loaded and changed from a memory bank?

Edit: BTW doing this even with the show_the_time variable didn't seem to change anything, still no incrementing.

Consider this code which "checks" the value of foo, a global variable that gets updated via ISR

unsigned int foo = 0;
ISR(blahblah) 
{
//update foo here
}

void loop ()
{
 while (foo == 0); /wait for foo to get updated
//do stuff after foo gets updated
}

Your while loop would never exit, because the compiler will read from the register(memory bank) which previously held "latest" value of foo instead of force reading the actual value from RAM.

Check out Nicks awesome page about interrupts: http://www.gammon.com.au/forum/?id=11488

Is there any way you can add in some debugging functions to send some output to the serial port, etc? I think that will be the easiest way to debug whats going on instead of just eye-balling the code and making changes

I also didn't see anything referring to #include <interrupts.h> (I didn't need to in my case) nor interrupts() or sei()

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...

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:

#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.

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.

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:

#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.