Using WDT for Resetting Pro Mini

Good morning, Arduino community!

I've developed significant progress on our project for an IoT-based system, but I have a problem in programmatically "resetting" the Pro Mini with a watchdog timer. I've read a post or two on using the Uno bootloader for the Pro Mini and the ISP programmer thingy and I think I was successful on that part but can't see any progress with the code itself.

The Pro Mini should be able to reset itself after pressing an external button (please don't tell me to use the built-in reset button instead because 1.) the Pro Mini + hardware is going to be mounted on a ceiling, so accessibility would be an issue 2.) the button itself will have 3 functionalities (silence, restore and reset) available depending upon the duration of being pressed and 3.) the following abt the message) for about 7 to 9 seconds OR receiving a message from the Raspberry Pi through XBee communication.

So I have this function which prompts the microcontroller to reset when called. Here are the contents:

void rebootDevice () {
  DebugSerial.println("Rebooting device..");
  sendPacket('r');
  //wdt_disable();
  wdt_enable(WDTO_15MS);
  while(1) {
    wdt_reset();
  }
}

And the following are the codes which call the function itself during manual (first one) and remote (second) activation:

void manCtrl(byte pressB2){     //pass the parameter stated in the function declaration to the function parameter int pressB
  
  if (pressB2 == HIGH && previous == LOW && (millis() - firstTime)>200){
    firstTime = millis();
  }
  millis_held = (millis()-firstTime);
  secs_held = millis_held/1000;
  if (millis_held > 50){
    if (pressB2 ==  HIGH && secs_held  > prev_secs_held){
      notifUnits(1,50,50,goBuzz,ledStat);
    }
    if (pressB2 == LOW && previous  ==  HIGH){
      if (secs_held<=0){
       notifUnits(1,500,500,goBuzz,ledStat);
      }
      else if (secs_held < 1 && secs_held > 9){
        notifUnits(2,250,250,goBuzz,ledStat);
        DebugSerial.println("Invalid counts.");
      }
      else if (secs_held >= 1 && secs_held <= 3){
        if (silFlag != 1){
          silenceNode();
        }
        else if (silFlag == 1){
          DebugSerial.println("Silence duration still on countdown.");
        }
      }
      else if (secs_held >= 4 && secs_held <= 6){
        if (silFlag == 1){
          restoreNode();
        }
        else if (silFlag != 1){
          DebugSerial.println("Silence not active!");
        }
      }
      else if (secs_held >= 7 && secs_held <= 9){
       rebootDevice();
      }
    }
 }
 previous = pressB2;
 prev_secs_held = secs_held;
}

and

void processRxPacketz(ZBRxResponse& rx, uintptr_t) {
  byte actCodeNetAlrm = 13, actCodeNodeStat = 14, actCodeSilence = 15, actCodeRestore = 16, actCodeReset = 17;
  //int actvtnCodeAckFire = ;
  //int actvtnCodeAckTamper = ;
  //int actvtnCodeAckPower = ;
  Buffer b(rx.getData(), rx.getDataLength());
  uint8_t type = b.remove<uint8_t>();
  XBeeAddress64 addr = rx.getRemoteAddress64();
    if (addr == 0x0013A200410407BC && type == 1 && b.len() == 2)
    {
      int codeSqnce = b.remove<int>();
        if (codeSqnce == actCodeNetAlrm){
          DebugSerial.println(F("Fire Alarm: Networked alarm sent by coordinator!!"));
          deployAlarm('f');
          return;         
        }
        else if (codeSqnce == actCodeNodeStat){
          DebugSerial.println(F("Poll received. Sending reply..."));
          sendPacket('p');
          return;         
        }
        else if (codeSqnce == actCodeSilence){
          silenceNode();
          return;         
        }
        else if (codeSqnce == actCodeRestore){
          DebugSerial.println("Restoring system to normal operation...");
          restoreNode(); 
          return;
        }
        else if (codeSqnce == actCodeReset){
          DebugSerial.println("Resetting device...");
          rebootDevice();
          return;
        }
        else{    
          DebugSerial.println(F("Unknown or invalid packet"));
          printResponse(rx, DebugSerial);
        }  
    }
}

I've already visited a lot of sites for this though but can't look for a solution. I'm not really that good in programming and the specifics despite the time I spent using the Arduino itself. I'm open to criticism, if that's going to help. :slight_smile:

If you put the Uno bootloader onto the pro mini, assuming your WDT code is correct, WDT reset should work.

If programming via ISP (and hence overwriting the bootloader), your sketch has to immediately disable the WDT, as it stays running at the minimum timeout after a WDT reset (if using the Uno bootloader, this is done correctly by the bootloader, if using the stock pro mini bootloader, this is not done, and the WDT will reset the board before the bootloader exits, trapping it in a reset loop.

But your code is NOT correct:

  wdt_enable(WDTO_15MS);
  while(1) {
    wdt_reset();
  }

So you enable the WDT.

And then go in an infinite loop where you keep resetting the WDT so it never runs out and the board never resets.

@Drazzy

It seems like all of the examples I've been looking at the web use loops for power-saving and etc. How can I achieve soft reset when called or activated whenever a certain condition has been met? I mean, the logic. Everything I read is convoluted.

I just solved the problem guys. Thank you anyway. I'll just post here what I did.

Since some of the sources say that some Nanos and Pro Minis contain a 'bug' regarding WDTs and bootloaders as said by DrAzzy coincidentally on another post, I tried to flash the Uno's bootloader to the Pro Mini using this method. However, despite several attempts which always end up in failure, I tried to modify the third step's instructions, where instead you choose the Pro Mini as the target board, you choose the Genuino board before burning in the bootloader. Afterwards in my code, I used this function code straight from source of a library named Software Reset:

do
        {
            wdt_enable(WDTO_15MS);
            for(;;) {};

        } while(0);

 MCUSR = 0 ;
 wdt_disable() ;