7

I am trying to set up a way to reboot arduino on command. The code below should do that but it seems like my arduino just get's stuck in some sort of a loop where I cant upload or get any serial output. The green led (pin 13) flashes very fast. The only way to stop this is to cut power to the device, even reset button does not work. This happens only when "R" is received via serial or if wdt_reset() function is commented out.

#include <avr/io.h>
#include <avr/wdt.h>

int ledPin = 3;

void setup()
{
  MCUSR=0;
  wdt_disable();
  Serial.begin(57600);
  Serial.println("BOOT!");
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  delay(500);
}

void loop(){
  if (Serial.available() > 0){
    char cmd = Serial.read();
    if (cmd == 'R'){
      Serial.println("R received!");
      wdt_enable(WDTO_1S);
      delay(2000);
      Serial.println("1 SEC.");
    }
  }
  wdt_reset();
  digitalWrite(ledPin, HIGH);
}

What am I doing wrong?

DominicM
  • 597
  • 3
  • 7
  • 13

4 Answers4

4

One of the most obvious issues here is that you are enabling the watchdog timer with a delay of 1S and then you are asking the micro controller to sleep for 2S, printing something and then going back into the loop. This, in theory, should be fine(your wdt should trigger a reboot during the 2 second wait) but I've seen it cause issues.

Additionally some bootloaders(notably the Optiboot bootloader on Uno and newer boards) can have issues with watchdog timers causing the wdt to remain enabled after reset even though the setup loop disables it. To start with - try increasing the wdt time to something greater than 2S(you should be able to do WDTO_8S) and see if the issue persists.

EDIT - The OP is using an Arduino Pro Mini clone. The included bootloader on the Arduino Pro Mini does not support system restarts by the WDT. Essentially, on a device with a bootloader that does not support WDT restarts, the board will restart but the timer / reset will not causing the board to continuously reset on reboot. There are alternative bootloaders for Arduino boards that may resolve this issue. Another solution is to use a different method to reboot the board.

Avamander
  • 624
  • 2
  • 11
  • 35
Nahkki
  • 186
  • 3
2

Enabling watchdog timer system restart and waiting in a loop until reset is a legitimate way of SW resetting the µC as is using watchdog for catching µC's misbehavior which can be caused by various reasons.

However, some precautions have to be made when using watchdog system reset because on all AVRs that also have watchdog interrupt the watchdog with prescaler set to 0000 = 16 ms remains active after watchdog system reset condition. It is therefore responsibility of a programmer to clear MCUSR and to disable watchdog timer as soon as possible after occurrence of such a condition. Since LPM routines for initializing .data and .bss sections can last longer than watchdog timeout interval, the code for disabling the watchdog must be placed in .init3 section and the contents of MCUSR can optionally be saved for later reset source examination. Here is the code that does the described:

uint8_t mcusr_copy __attribute__ ((section (".noinit")));
void disable_wdt(void) \
     __attribute__((naked)) \
     __attribute__((section(".init3")));
void disable_wdt(void) {
  mcusr_copy = MCUSR;
  MCUSR = 0x00;
  wdt_disable();
}

However, the problem may arise when using a bootloader which does not account for the possibility of watchdog system reset condition. If that is the case, watchdog timeout will happen inside bootloader (which is executed the first) before the above code will have the chance to disable the watchdog timer and µC will be stuck in an endless reset loop. Since reseting the µC will not clear WDRF flag in MCUSR register (it can be cleared only in software or by Power-on reset) the only way will then be to cycle the power and upload a new code when watchdog timer is still not activated by previous code. WDRF in MCUSR register must be cleared before wdt_disable() because WDE can not be cleared if WDRF is still set - therefore the order of the instrucions in the above code is very important. The function placed in .init3 section must not be called from later code.

Chupo_cro
  • 510
  • 2
  • 9
0

Remove watchdogs flag at init is one solution. I am using optiboot 8.0 and it works perfect.

// Function Pototype
void wdt_init(void) __attribute__ ((naked, used, section(".init3")));

// Function Implementation
void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();
    return;
}
-1

You can restart the Arduino with this command:

asm volatile ("  jmp 0");
geometrikal
  • 2,925
  • 16
  • 21