Can't get watchdog reset to work on a Leonardo

I’m trying to trigger a soft reset using the watchdog timer on my Arduino Leonardo.

My (simplified) code looks like the following:

#include <avr/wdt.h>

int outputPin = LED_BUILTIN;

void setup() {
  MCUSR = 0;
  wdt_disable();
  digitalWrite(outputPin, HIGH);
  delay(500);
  digitalWrite(outputPin, LOW);
  delay(500);
  digitalWrite(outputPin, HIGH);
  delay(500);
  digitalWrite(outputPin, LOW);
  delay(1000);
}

void loop() {
  wdt_enable(WDTO_15MS);
  while (true) {}
}

I would expect the LED to blink indefinitely, but it only blinks twice, and after it stays on (even though the last instruction is to turn off). After this, the RX light starts blinking about once every two seconds.

I also tried using Serial to debug the program, using one print in the setup and one in the loop. The initial line gets printed, and then the one in the loop, but only a couple of times. So it seems like the watchdog interrupt gets triggered, but there is some issue with properly resetting, the board just hangs after the reset.

I’ve seen that other people were having a similar problem (although with different boards), but unfortunately none of the solutions I tried based on the other threads (setting register values instead of using the functions, setting a longer timeout) worked.

You forgot to set outputPin as an output:

pinMode(outputPin, OUTPUT);

I think what was happening is that the bootloader sets that pin as an output to do the fade thing that indicates the bootloader is running. But the bootloader doesn't run after the WDT reset so after the first two blinks the pin is in input mode and so you don't get any more blinks, even though the microcontroller continues to be reset every 2515 ms.

Huh, this is vey strange. You’re right, I did forget to set it as an output pin, and adding that line solved the problem, the LED now blinks continuously.

That was only supposed to be a minimal example however (my actual program is much longer), and using Serial seems to already break it again. For the following program:

#include <avr/wdt.h>

void setup() {
  MCUSR = 0;
  wdt_disable();
  Serial.begin(9600);
  while (!Serial);
  Serial.println("Hello");
}

void loop() {
  wdt_enable(WDTO_15MS);
  while (true) {}
}

“Hello” only gets printed once. Maybe I’m missing something trivial again? I tried explicitly calling Serial.end(); before the loop, in case it shouldn’t be reinitialized across resets, but it didn’t help.

Oh hold on, I think the problem might just be that after every reset the serial monitor disconnects (even though it doesn't get greyed out), and that's why I can't see the following "Hello"s. I'll investigate a bit further.

Edit: yes, that was the problem... I feel pretty stupid now, but thanks for the help nevertheless! :D

One thing to keep in mind when using Serial.println() debug output is that it takes time to get sent out. If the program crashes or resets before the send buffer is emptied then that data never goes out. In that case, it might be helpful to add a Serial.flush() statement, which will block the program until the send buffer is empty. In your code, the 15 ms watchdog timeout should be long enough, but this has caused me some difficulty in the past when troubleshooting bugs.