How to start over before finishing void() loop

I have a sketch that starts on an event, then learns it is a false start and wants to go back to the beginning and wait for another event. Since good old "goto's" are frowned upon, can someone enlighten me on the best general approach to do this. I'm not clear on the use of the "return" and "break" statements.

Tommy Tyler

You can find information on return and break here:

There are multiple ways to accomplish what you want to do, but return and break are both possible answers. If you want specific help, you'll need to post your code. Please use code tags (</> button on the forum toolbar).

Your loop() is going to go round and round. It is always looking for the next "event" to occur. You just need to check for them. For example:

void loop(){
  if(intruderDetected){
    //sound buzzer
  }

  if(isOnLightShow){
    //display lighting effects
  }

  if(startingEventSignal){
    //do starting event stuff

    if(badConditions){
      //do nothing
    }
    else{
      //do more stating event stuff
    }
  }
}

If you post all of your code between code tags (</> button top left of posts) we can be more specific to your sketch you are writing.

While you can break out of a code block or return from a function to get out of what you are doing, I don't recommend it for what I think you are asking.

return especially, is to leave a function and send a value back to the point at which the function was called. Your loop() is a void function meaning it has no return value so you would not be returning a value nor is your sketch ever calling loop(), that is done by the Arduino core. It calls void setup() and void loop() for you. I'm not entirely sure what happens if you return from loop. It may throw you back into the start of loop, but I don't think this is a good programming strategy.

I'd use a state machine. Post your code.

i would follow Thee_Captain sugestion, loop is going round and round and round (always returning to the beginning)

if(badConditions){
      //do nothing
    }

Thee_Captain:
Your loop() is a void function meaning it has no return value so you would not be returning a value nor is your sketch ever calling loop(), that is done by the Arduino core. It calls void setup() and void loop() for you. I'm not entirely sure what happens if you return from loop. It may throw you back into the start of loop, but I don't think this is a good programming strategy.

return is valid in void function

return does the same as leaving the function at closing }

core does no magic. see main.cpp in core

	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}

I would try something like this (very off the top of my head, and I'm just on my way out so can't elaborate), using a state machine as Blackfin suggests, ie a bunch of cases in a switch...case.

  • In state_idle (ie, a case in the switch...case) look (delay()-lessly of course :wink: ) for the event, and switch case to state_running1 if it happens
  • In state_running1, monitor whatever it is that tells you it was a false start
  • If you get that signal, set the case of the switch_case back to state_idle; next time thru loop() it will take you back there. (Might have to "undo" any stuff you already did in state_running1)
  • If state_running1 completes correctly, ie no abend signal, set the case to state_running2 (if there is one) and continue

Here's a sketch I wrote for a timer application. When a switch is closed momentarily, a pulse is sent to LED2 and LED1 is turned on for N seconds. At the end of that time, send another pulse to LED2 and turn off LED1. If the switch is closed again while running, the timer operation is terminated immediately. To calibrate a different run time, hold the switch closed longer than 2 seconds. That starts LED1 blinking once per second. Press the switch again during the Nth blink, where N = the desired run time in seconds. That saves the run time in EEPROM and uses the new value thereafter.

//  6/22/19

const int SW1 = 0;                             // manual input
const int LED1 = 1;                            // simulates timer output signal
const int LED2 = 2;                            // simulates auxiliary pulse output signal
unsigned long longTime = 2000;                 // >2000 mS ON defines long SW1 press
unsigned long SW1on = 0;                       // time when SW1 pressed
unsigned long SW1off = 0;                      // time when SW1 released
unsigned long runTime = 0;                     // duration of timer output signal to LED1
unsigned long nowTime = 0;                     // millis() readings during calibration procedure   
#include <EEPROM.h>

void setup() {
  pinMode(SW1, INPUT_PULLUP);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  digitalWrite(LED1, HIGH);                    //initialize LED1 off
  digitalWrite(LED2, HIGH);                    //initialize LED2 off
}
void loop() {
  while (digitalRead(SW1) == LOW) {}           // don't start anything while SW1 is closed
  while (digitalRead(SW1) == HIGH) {}          // don't start loop until SW1 closes
  SW1on = millis();                            // save SW1 closed time
  while (digitalRead(SW1) == LOW) {}           // wait until SW1 opens
  SW1off = millis();                           // save SW1 opened time
  if ((SW1off - SW1on) > longTime) {           // was it a long switch press ?
  runTime = 0;                                 // yes, prepare to calibrate
  goto calibrate; }                            // go calibrate

  runTime = EEPROM.read(0);                    // fetch saved runTime seconds
  pulse();                                     // blink LED2  
  digitalWrite (LED1, LOW);                    // turn on LED1 
  SW1off = millis() + (1000 * runTime);        // convert runTime from seconds to milliseconds
  while ((millis()<= SW1off)&&(digitalRead(SW1)==HIGH)){}
           // do nothing until time's up, unless there's another SW1 closure to abort
  pulse();                                     // blink LED2        
  digitalWrite (LED1, HIGH);                   // turn off LED1
  while (digitalRead(SW1) == LOW) { }          // do nothing until SW1 opens
  return;

calibrate: // recalibrate runTime following long switch press    
  digitalWrite (LED1, HIGH);                   // turn off LED1 
  delay (200);                                 // leave it off for 0.2 sec
  digitalWrite (LED1, LOW);                    // turn on LED1 for 0.8 sec
  runTime ++;                                  // add 1-sec to runTime
  nowTime = millis();                          // get current time
  while ((millis()<(nowTime+800))&&(digitalRead(SW1)==HIGH)){}
             // wait until end of 1 second unless SW1 pressed to terminate calibration
  if (millis() >= (nowTime + 800))             // end of a second ? 
  goto calibrate;                              // yes, loop again
  digitalWrite (LED1, HIGH);                   // done cal, turn off LED1
  EEPROM.write(0, runTime);                    // save new runTime in EEPROM
  while (digitalRead(SW1) == LOW) { }          // wait until SW1 is open
}  
void pulse(){        // function for sending short pulse to LED2
  digitalWrite (LED2, LOW);
  delay (100);
  digitalWrite (LED2, HIGH);
  delay (100);
  }

The sketch works fine, but I also need another version that has a run time of several minutes, and calibrating that by counting seconds is too time consuming. I've tried to write a version that operates this way: If the system is idle, holding the switch longer than 2 seconds starts calibration, which is then done with short switch presses where each press represents 1 minute of run time. Calibration is terminated by again holding the switch longer than 2 seconds, or by no switch activity for 10 seconds. If at least one press has been counted the count is saved to EEPROM and the new run time is used thereafter.

This sketch (my first and only attempt at Arduino programming) took many hours of tedious work to weed out the syntax errors by trial-and-error recompiling to get all the semicolons, parenthesis, and curly brackets right. I've been trying very hard to write the faster calibrate version, so far without success. As you can tell I'm not a very skilled programmer. But at 88 years of age I don't have time to learn C++. I'm going to continue trying to write the faster version, but if there's anyone who thinks it might be fun to take a shot at, and help out an old fart, be my guest.

Give this minutes version a try. Your use of pins 0 and 1 are unorthodox as they are usually used for serial port use. YMMV.

sketch_jun22a.ino (9.57 KB)