Endless function call

Guys,

I am working on a project where I have 3 different phases. For easy reading I am planning to put each phase in a separate function. The tricky part is that - based on specific conditions - one phase might end and immediately jump to an other one. Somehow like this:

void Phase1() {
 // Some code here
 if (condition) { Phase2(); }
}

void Phase2() {
 // Some code here
 if (condition) { Phase3(); }
 if (othercondition) { Phase1(); }
}

void Phase3() {
 // Some code here
 if (condition) { Phase2(); }
 if (othercondition) { Phase1(); }
}

void loop() {
 // Nothing else here, directly jump to Phase 1
 Phase1();
}

Now, according to my knowledge in previous programming languages the above setup will jump between functions without actually ending themselves. Like...

loop calls Phase1. Phase1 calls Phase2. Phase2 calls Phase1. Phase1 calls Phase2. Phase2 calls Phase3. Phase3 calls Phase1.

I think at this time we will have 3 instances of Phase1(), 2 instances of Phase2() and 1 instance of Phase3() undended.
Will this cause any memory / buffer overflow, or any other problems if it runs for like... indefinite time?

An other idea is to just define a global variable and actually exit the function, and let the main loop() handle all calls...

void setup() {
 nextphase = 1;
}

void Phase1() {
 // Some code here
 if (condition) {
  nextphase = 2;
  return 0;
 }
}

void Phase2() {
 // Some code here
 if (condition) {
  nextphase = 3;
  return 0;
 }
 if (othercondition) {
  nextphase = 4;
  return 0;
 }
}

void Phase3() {
 // Some code here
 if (condition) {
  nextphase = 2;
  return 0;
 }
 if (othercondition) {
  nextphase = 3;
  return 0;
 }
}

void loop() {
 if (nextphase==1) { Phase1(); }
 if (nextphase==2) { Phase2(); }
 if (nextphase==3) { Phase1(); }
}

What do you think? :slight_smile:

Will this cause any memory / buffer overflow, or any other problems if it runs for like... indefinite time?

Absolutely.

Your second approach is the only way to go.

void Phase1() {
 // Some code here
 if (condition) {
  nextphase = 2;
  return 0;

"void" means "returns nothing, zilch, zip, nada, rien". That includes not returning zero.

I also made a typo in the main loop:

 if (nextphase==3) { Phase3(); } // Was 1 before

aehimself:
An other idea is to just define a global variable and actually exit the function, and let the main loop() handle all calls...

Yes, this is the standard way you manage these problems on Arduino. It's called a state machine.

Personally, I like to use an enum:

enum State {
  INIT,
  EXTRACTING,
  PROCESSING,
  PAUSING,
  REDUCING,
  OUTPUTTING,
  ERROR
} state = INIT;

Furthermore, my loop() function is usually a switch statement:

void loop() {
  // read some inputs

  switch(state) {
     /// etc etc etc 
    case PAUSING:
      if(millis() - pauseStartMs >= PAUSE_MS) {
        // do whatever you have to do to start "reducing"
        state = REDUCING;
      }
      break;
    /// etc etc etc 
  }
}

Changes to state only ever get done inside loop(), even if other functions need to be called to actually do the stuff. That way, you can analyze the transitions just by looking at the loop() function.

Most people call those "states", not phases. Read up on state machines, because that is what you are trying to reinvent.