while(1) loop explanation

I was looking thru posts to find a way to reset the arduino in code and found this:

void software_Reboot()
{
  wdt_enable(WDTO_15MS);
  while(1)
  {
  }
}

I understand the wdt_enable line which counts to 15ms and reboots the arduino via the wdt. But why is the while(1) required?

The code turns on the watchdog timer. It then goes into an infinite loop. The watchdog timer
times out after about 15ms and resets the processor.

If the watchdog is enabled you have to keep reseting it before it times out, or it resets the chip.
This is precisely to catch the situation where the code has gone catatonic (due to an unintended
infinite loop or soft-error / glitch).

Yes, the wdt is set and fires after 15ms. This is in author that I'm using to reset the Arduino. So when an error is caught, this method will fire. It would only fire once.

I'm not sure I understand exactly what the infinite loop is needed for.

I'm not sure I understand exactly what the infinite loop is needed for.

In this case it allows the WDT to time out hence, the controller restarts.

When you want to reboot, do you want to:

  1. stop doing anything else

or

  1. keep doing whatever you were doing until the watc

oqibidipo:
When you want to reboot, do you want to:

  1. stop doing anything else

or

  1. keep doing whatever you were doing until the watc

I like that. Funny and accurate...

Marciokoko:
Yes, the wdt is set and fires after 15ms. This is in author that I’m using to reset the Arduino. So when an error is caught, this method will fire. It would only fire once.

I’m not sure I understand exactly what the infinite loop is needed for.

To stop it getting into any more trouble.

The while(1) hinders the processor to execute any wdt_reset(), so the reset will be execeuted 15ms.

Ok Im slow…so bare with me:

void software_Reboot()
{
  wdt_enable(WDTO_15MS); // This line turns on the watchdog timer
  while(1) // This line goes into an infinite loop
  {
  }  //Immediately the wdt timer counts to 15ms and resets the arduino
}

Wdt will reset my arduino unless I pat the dog with wdt_reset(), this much I know.

MarkT wrote:
“This is precisely to catch the situation where the code has gone catatonic (due to an unintended
infinite loop or soft-error / glitch)”

I know, wdt is usually used to catch buggy code that if it makes the arduino hang for some reason, since its hung there is no resetting (patting the dog) and thus the reset is called. But in my case I just want to reset the arduino if a condition is met, which I test for in the loop() function. If, then software_Reboot().

LarryD wrote:

“In this case it allows the WDT to time out hence, the controller restarts.”

So you mean that it allows the wdt to time out and fire the alarm because there is no patting of the dog. You are assuming I have a wdt_reset() call somewhere else in my code. But I dont because Im not using the wdt in that way. At least I dont think.

Whandall says:
“The while(1) hinders the processor to execute any wdt_reset(), so the reset will be execeuted 15ms.”

Again, assuming I have wdt_reset()s in code.

Here is what I have:

// All my imports & var setup

void setup(){
  Serial.begin(9600);  
  Wire.begin();
  rtc.begin();
  //Setup all my alarm code
}

void  loop(){  
  Alarm.delay(10); // wait one second between clock display
  if (wifly.moduleCrashed==true){
   wifiStuff();
   wifly.moduleCrashed=false;
   Serial.println("called wifiStuff & setting bool false"); 
  }
}

void software_Reset(){
  //asm volatile ("  jmp 0"); 
 // or reset using wdt_reset
// #include <avr/wdt.h>
// wdt_enable(WDTO_15MS);while(1)
} 

void MorningAlarm(){
  initialiseSensor(); //start sensor
  delay(3000); // Give sensor time to warm up
  printCO2(); // get data from sensor and print it to monitor
  wifiStuff(); // connects to wifi network
  reportToCloud(); //posts to web
}

void initialiseSensor(){
  //init co2 sensor
}

void printCO2() { //gets data by calling dataReceive()
  // Print CO2 to terminal = serial monitor
}

void wifiStuff(){
//Setup my wifi module
}

void reportToCloud() {
   //Post sensor data to web 
}

void terminal(){
   while (1) {
 if (wifly.available() > 0) {
    Serial.write(wifly.read());
 }
 if (Serial.available() > 0) {
    wifly.write(Serial.read());
 }
   }
}

bool dataRecieve(void) {
  // Gets and parses data from sensor
}

In the WiflyHQ.cpp the method responsible for logging the error message when my wifly crashes is this open method which I’ve posted below. I might get caught on this by the admins, its almost the same post but the question is completely different. In my other post Im trying to figure out why rebooting isnt working. In this post Im simply trying to understand this while(1) loop and I dont think its necessary because Im calling my if-test from the loop method itself. Am I correct?

I’ve attached my complete sketch below and here is the wifly.open() from the WiflyHQ.cpp library.

boolean WiFly::open(const char *addr, uint16_t port, boolean block)
{
    char buf[20];
    char ch;

    if (connecting) {
 /* an open is already in progress */
 return false;
    }

    startCommand();

    /* Already connected? Close the connection first */
    if (connected) {
 close();
    }

    simple_utoa(port, 10, buf, sizeof(buf));
    debug.print(F("open ")); debug.print(addr); debug.print(' '); debug.println(buf);
    send_P(PSTR("open "));
    send(addr);
    send(" ");
    send(buf);
    send_P(PSTR("\r"));

    if (!getPrompt()) {
 debug.println(F("Failed to get prompt"));
 debug.println(F("WiFly has crashed and will reboot..."));
 //Add reboot code
 reboot();
[color=red] moduleCrashed = true;
[/color] while (1); // wait for the reboot
 return false;
    }

    if (!block) {
 /* Non-blocking connect, user will poll for result */
 connecting = true;
 return true;
    }

    /* Expect "*OPEN*" or "Connect FAILED" */

    while (readTimeout(&ch,10000)) {
 switch (ch) {
 case '*':
    if (match_P(PSTR("OPEN*"))) {
 DPRINT(F("Connected\n\r"));
 connected = true;
 /* successful connection exits command mode */
 inCommandMode = false;
 return true;
    } else {
 finishCommand();
 return false;
    }
    break;
 case 'C': {
 buf[0] = ch;
 gets(&buf[1], sizeof(buf)-1);
 debug.print(F("Failed to connect: ")); debug.println(buf);
 finishCommand();
 return false;
    }

 default:
    if (debugOn) {
 debug.print(F("Unexpected char: "));
 debug.print(ch,HEX);
 if (isprint(ch)) {
    debug.print(' ');
    debug.print(ch);
 }
 debug.println();
    }
    break;
 }
    }

    debug.println(F("<timeout>"));
    finishCommand();
    return false;
}

co2sampling.txt (6.15 KB)

Marciokoko:
I understand the wdt_enable line which counts to 15ms and reboots the arduino via the wdt. But why is the while(1) required?

The while(1) is just to fake the sort of problem that the wdt is intended to solve. It is just for demonstration purposes.

...R

Thanks Robin2, that's what I wanted to make sure.

When you call software_Reboot( ) it will set the wdt time, and without the while{ }, it would return
to the caller. With the infinite loop, software_Reboot( ) will never return.

Which behavior is desired depends upon the remainder of the program. Since we don't know what that
is, we can't really say anything.

If the function was to return, the program would continue running for 15mS. A lot of code can be
executed in 15mS. If you are requesting a reset, you probably have good reason to prevent the
code from continuing.

On the other hand, if it makes no real difference if code execution continues, then you don't need
the infinite loop.

Yes, it doesn't matter where it returns because after the reset happens, it should just return to the loop method, right?

Oh but the setup will not be called again right?

It's RESET. The whole system starts, probably with the bootloader.

OK then I don't need the while because all I need is setup and loop to run. I don't need it to pick up anywhere specific.

The reason people often set the watchdog and then go into an infinite loop is just for simplicity. If you set the watchdog from a function and return to your loop, or if you just set the watchdog in the loop, and your intention was to reset your processor you would then need to do some extra checking of your logic to make sure the same conditions won't be met again to make the loop decide to set the watchdog again. So, rather than think about all that, it is easier to just stop all other processing and wait for the reboot to happen, by going into an infinite loop right after setting the watchdog.

Setup is run once after a reset or power on, then loop is run over and over.

If you want to reset, set the watchdog and go into an infinite loop, that is probably the best way. In my opinion.

OK then I don't need the while because all I need is setup and loop to run. I don't need it to pick up anywhere specific.

Just go with dmjlambert and leave it in!

And "...all I need is setup and loop to run"

What does that mean? You don't need to run anything while waiting for reset.

Marciokoko:
OK then I don't need the while because all I need is setup and loop to run. I don't need it to pick up anywhere specific.

See:

oqibidipo:
When you want to reboot, do you want to:

  1. stop doing anything else

or

  1. keep doing whatever you were doing until the watc

Very humorous response there.

I don't need the while ...

What were you planning to do while you were waiting 15 ms, exactly?

Nothing.

I have a sketch that takes measurements every 30 minutes using time alarms and a co2 sensor. The data is posted to a Web server after sampling.

Every 10 or so measurements (sometimes fewer) the wifi module crashes and supposedly reboots. But sampling doesn’t resume.

If I tap the reset button on the WiFi module, it resets the Arduino because I see the led13 blink, and sampling resumes.

So I’m thinking that resetting the uc might do the trick from code.

Marciokoko:
Every 10 or so measurements (sometimes fewer) the wifi module crashes and supposedly reboots. But sampling doesn't resume.

Find out what is causing the problem and fix it. Don't just put a BandAid on it.

...R