Watchdog Timer Seems to Melt Down?

EDIT: I’m using an Arduino Uno R3 and the Arduino IDE 1.0.3. I have pin 11 jumpered to a breadboard housing an LED connected back to GND on the Arduino.

I’m making my first foray into understanding and using the various sleep modes on my Arduino and I’m using some code from Nick Gammon’s outstanding page on the subject. I have modified the code just a little to use PWM on digital pin 11. The code runs just fine, waking up the chip and blinking my LED very dimly once every 8 seconds. If I leave it running long enough, say around 20 minutes, the LED goes to 100% power and stays there and no further action by the chip appears to be taken. This is very strange to me since no line in my code sets power to 100%! The only thing I can figure is I’m using PWM incorrectly and the duty cycle is getting set to 100% due to some error I’ve made but cannot see. I have tried to wade through the 328P’s datasheet but there is a lot of complexity for a newbie like me. The code I’m using is below. I hope someone can point out my mistake!

#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/delay.h>

// watchdog interrupt
ISR (WDT_vect)  {
   wdt_disable();    // disable watchdog
   OCR2A = 1;        // turn the LED on at 0.1% of full intensity
   _delay_ms(10);    // leave it on for 10 ms
   OCR2A = 0;        // turn the LED off
}  // end of WDT_vect
int main(void) {
  DDRB = _BV(PB5) | _BV(PB3);  // Disable the onboard LED as well as allow pin 11 to blink  
  TCCR2A |= _BV(COM2A1) | _BV(WGM20);  // Enable timer 2 to _delay_ms() works properly
  TCCR2B |= CS22;  // set clkT2S/64 (From prescaler)

  for(;;) {
    ADCSRA = 0;  // disable ADC
    MCUSR = 0;   // clear various "reset" flags
    WDTCSR = _BV (WDCE) | _BV (WDE);// allow changes, disable reset
    // set interrupt mode and an interval 
    WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0);    // set WDIE, and 8 seconds delay
    wdt_reset();  // pat the dog
    set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
    // turn off brown-out enable in software
    MCUCR = _BV (BODS) | _BV (BODSE);
    MCUCR = _BV (BODS); 
    sleep_cpu ();  
    sleep_disable();  // cancel sleep as a precaution
  } // end of loop
} // end of main

I pulled the LED out of my breadboard so it doesn’t fry (no resistor, I’m naughty) once it lit to 100% after about 5 minutes of blinking nicely. I replaced it without resetting the board and once again it is blinking nicely as I expect it to. I’ll see if it goes to 100% and stays on again. So far the behavior is totally reproducible which should make finding the error that much easier.

You aren't using Arduino at all, are you? Neither the IDE, nor the runtime library. In that case this forum hardly seems like the right place to ask for help.

I'm using both the Arduino Uno R3 and the IDE 1.0.3. Why would you think otherwise? Just because I'm not using the setup() loop() scheme?

Okay it gets stranger and stranger. Calling init() from Wiring.c at the begining of main() prevents the issue from ever occurring. I put a 15 ohm resistor (biggest I have other than 4,700) on the breadboard to try to protect the LED from 5V and allowed it to stay lit using the code I posted above. It stays lit for one 8s watchdog timer cycle and then resumes normal behavior.

Given this, I'm thinking that the various clocks work in concert and I'm trying to use just one and that is creating the problem. I'll keep plugging away but I suspect someone more knowledgeable about timers and interrupts will see my mistake before I root it out.

Interrupts are disabled in an interrupt service routine. You can NOT call delay in an ISR. ISRs are supposed to be FAST!

Saw this in another thread today and felt it applied to my sketch/issue as well. I’ve moved the blink and delay code out of my WDT_vect and into the main program loop to see if this resolves the issue.

EDIT: No luck, already had another stuck on for 8 seconds event.

ChemE: Just because I'm not using the setup() loop() scheme?


But on closer inspection I see that you are using some functions from the Arduino runtime library, although most of your code bypasses it. Since you aren't using the Arduino main(), none of the normal hardware and software initialisation will have been performed.

If you're going to use the Arduino runtime library, it does not IMO make sense to bypass the normal structure of a sketch and the associated behaviour that is supplied by Arduino. If you do, it should not come as any surprise when things don't work correctly.

If you don't want to write an Arduino sketch then I suggest you might be better off writing this using just the AVR library and development environment.

I'm not surprised that omitting part of Arduino code is causing the issue. I just thought this was the most appropriate place to come for help understanding the chip which runs my Arduino. If there is a more suitable forum I'll take my question there.

I have to confess that I don't understand why this is the solution but I have solved my issue.

Original flawed line of code

TCCR2B |= CS22;  // set clkT2S/64 (From prescaler)

This sets TCCR2B = B00000010 which corresponds to a clkT2S/8 as per Table 17-9 on page 162 of the 328P's data sheet

Corrected line of code

TCCR2B = _BV(CS22);  // set clkT2S/64 (From prescaler)

This sets TCCR2B = B00000100 which corresponds to a clkT2S/64 as per Table 17-9 on page 162 of the 328P's data sheet

I'm not sure what timer 2 running 8 times as fast would periodically cause the PWM code to fail in the way I was seeing but I'm happy to have resolved the issue and learned a bit more about my chip.