Prescaler on Watchdog timer interrupt??

I'm wondering if someone knows how to change the prescaler on the watchdog timer enabled as an interrupt?

So far I have been successful enabling the WDT as an interrupt but I can't get the Prescaler to work.

I'm trying to make the WDT interrupt every 1 second so I can make a 24 hr clock with it. In the reference manual it says you can prescale it down to 1 second by setting 1<<WDP2 and 1<<WDP1, but it seems as tho it has no prescaler at all.

Here is a portion of my code so far:

void setup()
cli(); // stop interrupts
WDTCSR = (1<<WDCE); // watchdog change enable
WDTCSR = (0<<WDP3)|(1<<WDP2) | (1<<WDP1); // set
//prescaler to 1 second
WDTCSR = (1<<WDIE) | (0<<WDE); // enable wdt interrupt
sei(); // start interrupts


/WDT interrupt/



I think you're confusing the hardware timers (TIMER0 & TIMER1) with the watchdog timer.

The watchdog is mainly designed to reset the chip if it freezes. The hardware timers are meant for programmatic events (like being triggered every second).

it's very possible my friend. I'm attaching the documentation of what I read from the ATmega datasheet.. this is the reason i thought that I could use it as an interrupt.


10.9.2 WDTCSR – Watchdog Timer Control Register


? Bit 6 - WDIE: Watchdog Interrupt Enable
When this bit is written to one and the I-bit in the Status Register is set, the Watchdog Interrupt is
enabled. If WDE is cleared in combination with this setting, the Watchdog Timer is in Interrupt
Mode, and the corresponding interrupt is executed if time-out in the Watchdog Timer occurs.

Watchdog Timer Configuration

WDTON(1) WDE WDIE Mode Action on Time-out

1 0 0 Stopped None

1 0 1 Interrupt Mode Interrupt

1 1 0 System Reset Mode Reset

1 1 1 Interrupt interrupt
System Reset then go
Mode to system

0 x x System Reset Mode Reset

? Bit 5, 2..0 - WDP3..0: Watchdog Timer Prescaler 3, 2, 1 and 0

The WDP3..0 bits determine the Watchdog Timer prescaling when the Watchdog Timer is running.

Watchdog Timer Prescale Select

WDP3 WDP2 WDP1 WDP0 Number of WDT Typical Time-out at
Oscillator Cycles VCC = 5.0V

0 0 0 0 2K (2048) cycles 16 ms
0 0 0 1 4K (4096) cycles 32 ms
0 0 1 0 8K (8192) cycles 64 ms
0 0 1 1 16K (16384) cycles 0.125 s
0 1 0 0 32K (32768) cycles 0.25 s
0 1 0 1 64K (65536) cycles 0.5 s
0 1 1 0 128K (131072) cycles 1.0 s
0 1 1 1 256K (262144) cycles 2.0 s
1 0 0 0 512K (524288) cycles 4.0 s
1 0 0 1 1024K (1048576) cycles 8.0 s

Well I guess you can use it for a "time-based" interrupt. But that's what the hardware timers really are for. They can also generate a number of different interrupts based on how you configure them.

The watchdog timer is really designed to allow some event to happen if the watchdog doesn't get reset before it expires. Normally the "something" is reset the chip. The code then must reset the timer frequently (at least faster than the timeout) to prevent the watchdog from firing. This is sometimes referred to as "feeding the dog". Then if the chip crashes or the code goes awry, the watchdog timer will expire and fire the "something" (reset the chip).

The other problem with using the watchdog is that if it triggers a reset it's still enabled when the chip restarts. The bootloader doesn't disable it or regularly "feed the dog" since it doesn't expect the watchdog to be enabled. This can then lead to an endless loop of resets that can only be resolved by reburning the bootloader with a programmer.

So the short answer is the hardware timers are designed to be used for what you're trying to do, not the watchdog timer.

Ignore the part about having to reburn the bootloader. That only applies if the watchdog fuses were set which isn't a normal Arduino occurrence.

You will still get into an annoying reset loop, but it can be cured by power cycling the chip (which is annoying if your trying to upload a program).

Also note that the watchdog timer uses an internal, uncalibrated, RC clock that has a very low accuracy compared to the crystal-based "normal" timers; it will probably make a lousy "24 hour clock."

 WDTCSR  = (1<<WDCE);     // watchdog change enable
 WDTCSR  = (0<<WDP3)|(1<<WDP2) | (1<<WDP1); // set
                  //prescaler to 1 second
 WDTCSR  = (1<<WDIE) | (0<<WDE);   // enable wdt interrupt

Your second write to WDTCSR is overwriting the prescaler bits, I think. And/or apparently you need to set WDE to change the prescaler, even if you're going to immediately clear it. See the bottom of page 49 of the Atmega168 datasheet. This sequence seems to work:

 cli();          // stop interrupts
 WDTCSR  = (1<<WDCE | 1<<WDE);     // watchdog change enable
 WDTCSR  = 1<<WDIE | (0<<WDP3)|(1<<WDP2) | (1<<WDP1); // set  prescaler to 1 second
 sei();        // start interrupts

Thanks so much for the advise! I will probably stick to other interrupts beings that the watchdog is not entended for that reason.

Thx for all the help my friends!! :smiley:

Has anyone managed to get an interrupt from a wdt?

I'm trying with:

      cli();      // important: disable interrupts
      WDTCSR = (1 << WDCE); // watchdog change enable
      WDTCSR |= (1 << WDIE) | (0 << WDE); // enable wdt interrupt


      Serial.println("Got watchdog reset...");

Sleep modes and watchdog interrupt: