Stop a void function when another one is running

Hi everybody
I can't solve this and I need your help.

this is the part of the sketch that I'm talking about:

void IMM()

{while (digitalRead(immediateREED) == HIGH) 

ALL();}


void ALL()
{digitalWrite(redLED, HIGH); 
digitalWrite(greenLED, HIGH); 
digitalWrite(BUZZER, HIGH);
}


void RIT()

{  
  while (digitalRead(delayedREED) == HIGH)  
  {PRE();}
}

void PRE()

{  // there is a code for several blinking sequences, both redLED and greenLED, no delay

}

the IMM() function reads the input coming from a reed switch, so when the read is HIGH the ALL() function is called and running.
Now, I need to completely stop the IMM() function as soon as the ALL() function starts. I tried with return, with no luck.

hope you can help me
thanks
Have a good day

The functions never run at the same time...

You arrive in IMM if the reed value is HIGH th microprocessor jumps to the ALL function and that’s what is executed. Then ALL terminates, you go back to where you came from and since this is all that you have in your while, the while ‘loops’ and test your REED sensor again, if it’s still HIGH you go back into ALL and the cycle continues.

If you want to call ALL only ONCE in IMM when the reed value is HIGH, don’t use a while, use a if statement

Please edit and fix your post and use code tags around the code. (see how to use the forum)

Now, I need to completely stop the IMM() function as soon as the ALL() function starts. I tried with return, with no luck.

Then why do you have a while loop that will keep calling that function over and over. Just make it an if statement. That way it calls ALL() once and then when ALL is over IMM returns as well and you have the same effect (I think) that you are asking for.

J-M-L and Delta_G are spot on about just using an if statement, but I have one small thing to add. If in the future you had a bigger function and want to call another function and terminate the current function look into 'return'.

void function() {
  ...some function code...

  if (whatever == true) {
    otherFunction(); //calls otherFunction, once otherFunction is complete the program continues here
    return *note*; //possibly return some data, and end
  }

  ...some more function code...
}

note: you need to return a relevant data type, if applicable. void functions don't need to return anything, int functions need to return an integer, string functions need to return a string, etc.

Read up on how 'return' works in C++, it's pretty straightforward and might help in the future if you want to terminate a function in a specific spot.

Yes if you really need a while and depending on what's going on in the function decide to exit the while or not, then a possible construct is to have the function returns if it needs to break the while or not

boolean functionDecidesItsTimeToBreak()
{
   Instruction;
   Instruction;
   if (functionNeedsToContinue) return false;
   else return true;
}

...
  // somewhere in the code
  while (true) { // never ends unless the code in the while decides to break
    if (functionDecidesItsTimeToBreak()) break;
  }

...

J-M-L:
The functions never run at the same time...

You arrive in IMM if the reed value is HIGH th microprocessor jumps to the ALL function and that’s what is executed. Then ALL terminates, you go back to where you came from and since this is all that you have in your while, the while ‘loops’ and test your REED sensor again, if it’s still HIGH you go back into ALL and the cycle continues.

If you want to call ALL only ONCE in IMM when the reed value is HIGH, don’t use a while, use a if statement

Please edit and fix your post and use code tags around the code. (see how to use the forum)

Hi everybody
Thanks for your replies.
I edited my first post as J-M-L suggested :wink: I also added some part of the entire sketch to explain the problem in a better way.

First of all, the whole sketch is about a multi-zone anti-theft system using PIR sensors, a gyroscope, reed switches (can be immediate or delayed), RFID for disarming, etc.

I didn't post the whole sketch for basically 2 reasons: it's already pretty big even though it's still incomplete, and many parts (functions, comments, etc.) are written in Italian.

Now, when i move the magnet away from the immediate reed (void IMM()) the ALL() function is run; so Buzzer, green and red leds are on. But if i move the magnet close to the reed sensor again, the buzzer keeps buzzing but the leds turn off.

Or if ALL() function is running because the immediateREED value was HIGH, and while the alarm is on (so buzzer and LEDs are on) I make the delayedREED value be HIGH as well, the buzzer keeps buzzing but the LEDs start blinking at the same sequences described in the PRE() function.

Both of the issues above happen if I use both "while" and "if".

I tried with the return as well, just after ALL() function is called...nothing's changed.

So I need a way to stop everything once ALL() in running, except the RFID() function that will allow me to disarm the alarm system.

I hope I made everything clearer now, and sorry for my typos or similar.

P.s. I haven't completely understood the functionNeedsToContinue and functionDecidesItsTimeToBreak stuff...

I hope I made everything clearer now,

clear as mud... sorry.. but we don't see what your code does so ...

J-M-L:
clear as mud... sorry.. but we don't see what your code does so ...

:sweat_smile:

Do you think that posting the whole sketch would be better?

I didn't post the whole sketch for basically 2 reasons: it's already pretty big even though it's still incomplete, and many parts (functions, comments, etc.) are written in Italian.

You'll admit this makes it difficult for us to understand the rest of your post

--> how do you want us to get what you do...

Now, when i move the magnet away from the immediate reed (void IMM()) the ALL() function is run; so Buzzer, green and red leds are on. But if i move the magnet close to the reed sensor again, the buzzer keeps buzzing but the leds turn off.

Or if ALL() function is running because the immediateREED value was HIGH, and while the alarm is on (so buzzer and LEDs are on) I make the delayedREED value be HIGH as well, the buzzer keeps buzzing but the LEDs start blinking at the same sequences described in the PRE() function.

Both of the issues above happen if I use both "while" and "if".

You're right, I'm working on it. I will need some time to edit the sketch and post it... Thanks and excuse me fo the mess..

So...I cropped the part of the sketch that could be easily "disconnected" from the rest without afflicting interactions. I tested it and works exactly the same, with the same problems. I translated the more I could, but I had to cheep something in Italian because of connections and interactions through the rest of the sketch.

#define immediateREED 2
#define delayedREED 3
#define PIR 4
#define BUZZER 5
#define greenLED 6
#define redLED 7
#define SIREN 14

#define LED_ONavvio 500
#define LED_OFFavvio 500
#define LED_ONarmed 80
#define LED_OFFarmed 4920

#define redLED_ON1 100
#define redLED_OFF1 900
#define redLED_ON2 100 
#define redLED_OFF2 400
#define redLED_ON3 100
#define redLED_OFF3 250
#define redLED_ON4 100
#define redLED_OFF4 100

unsigned long ms;        //time from millis()
unsigned long msLast;    //last time the redLED changed state
unsigned long redmsLast;    //last time the redLED changed state
unsigned long greenmsLast;    //last time the redLED changed state

boolean redLEDState;
boolean greenLEDState;
boolean ledState;        //current redLED state
boolean buzState;

int  RedCount = 0;
int  StartCount;
int RitardoAvvio=20;   //the number is the double of the delay (seconds) for RITARDATO()
void setup() 
{ pinMode(immediateREED, INPUT_PULLUP);
  pinMode(delayedREED, INPUT_PULLUP);
  pinMode(PIR, INPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(SIREN, OUTPUT);
  

}

void loop() 
{
  ms = millis(); 

  AVVIO();
 

  
  
}

void AVVIO()
{
  {if(StartCount<6)
    {while (ms - redmsLast > (redLEDState ? 100 : 100))
      {digitalWrite(BUZZER, redLEDState = !redLEDState); redmsLast = ms; StartCount =  StartCount+1;}
    }
  }

  {if(StartCount>5 and StartCount<RitardoAvvio)
    {while (ms - redmsLast > (redLEDState ? LED_ONavvio : LED_OFFavvio))
    {digitalWrite(redLED, redLEDState = !redLEDState); redmsLast = ms; StartCount =  StartCount+1;}
      
    while (ms - greenmsLast > (greenLEDState ? LED_ONavvio : LED_OFFavvio))
    {digitalWrite(greenLED, greenLEDState = !redLEDState); greenmsLast = ms;}
    }
  }


  {if(StartCount>(RitardoAvvio-1))
    {digitalWrite (redLED, LOW); digitalWrite (greenLED, LOW); IMMEDIATO(); RITARDATO(); MOVIMENTO();}
  } 
 
}

void IMMEDIATO()

{  
  if (digitalRead(immediateREED) == HIGH) 
  ALLARME();
}

void RITARDATO()

{  
  if (digitalRead(delayedREED) == HIGH)  
  PREALLARME();
}

void MOVIMENTO()
{
  digitalWrite (PIR, LOW);
  if (digitalRead(PIR) == HIGH)
  PREALLARME();
}

void PREALLARME()
        
{while( RedCount<26) {ms = millis(); blinkLED1();}

while ( RedCount>25 and  RedCount<50) {ms = millis(); blink1();}
    
while ( RedCount>49 and  RedCount<90) {ms = millis(); blink2();}

while ( RedCount>89 and  RedCount<170) {ms = millis(); blink3();}   
  
while ( RedCount>169 and  RedCount<300) {ms = millis(); blink4();}

while ( RedCount>299) ALLARME();
}

void ALLARME()
{digitalWrite(redLED, HIGH); 
digitalWrite(greenLED, HIGH); 
digitalWrite(BUZZER, HIGH);
digitalWrite (SIREN, HIGH); 
}
    
void blinkLED1()
{if (digitalRead(immediateREED) == LOW)
  {while (ms - msLast > (ledState ? redLED_ON1 : redLED_OFF1))
    {digitalWrite(redLED, ledState = !ledState);
    msLast = ms;  RedCount =  RedCount + 1;}}
else ALLARME();}

void blink1()
{if (digitalRead(immediateREED) == LOW)
  {while (ms - msLast > (ledState ? redLED_ON1 : redLED_OFF1))
    {digitalWrite(redLED, ledState = !ledState);
    digitalWrite(BUZZER, buzState = !buzState);
    msLast = ms;  RedCount =  RedCount + 1;}}
else ALLARME();}

void blink2()
{if (digitalRead(immediateREED) == LOW)
  {while (ms - msLast > (ledState ? redLED_ON2 : redLED_OFF2))
    {digitalWrite(redLED, ledState = !ledState);
    digitalWrite(BUZZER, buzState = !buzState);
    msLast = ms;  RedCount =  RedCount + 1;}}
else ALLARME();}

void blink3()
{if (digitalRead(immediateREED) == LOW)
  {while (ms - msLast > (ledState ? redLED_ON3 : redLED_OFF3))
    {digitalWrite(redLED, ledState = !ledState);
    digitalWrite(BUZZER, buzState = !buzState);
    msLast = ms;  RedCount =  RedCount + 1;}}
else ALLARME();}

void blink4()
{if (digitalRead(immediateREED) == LOW)
  {while (ms - msLast > (ledState ? redLED_ON4 : redLED_OFF4))
    {digitalWrite(redLED, ledState = !ledState);    //PREAVVISO redLED E BUZZER
    digitalWrite(BUZZER, buzState = !buzState);
    msLast = ms;  RedCount =  RedCount + 1;}}
else ALLARME();}

I also attached the schematics

If you don't have exception handling available, the alternative is to set a variable when an exceptional
event happens, and check that variable wherever it matters to handle or propagate the fact.

boolean fault = false ;


void my_fun ()
{
  ...
  ...
  if (<something goes wrong>)
  {
    fault = true ;
    return ;
  }
  ....
}

void looping_function ()
{
  while (<whatever>)
  {
    ...
    my_fun() ;   // whenever call something that might provoke a fault condition, test for it
    if (fault)   // and propagate out
      return ;
    ...
  }
}

void loop()
{
  looping_function() ;
  if (fault)    // here we can handle the fault condition at top level.
    handle_fault () ;
}

I can't read Italian but I can read C++. So post the code un-translated. Otherwise you have to translate it back and that will add more mistakes.

While comments are sometimes helpful, comments in Italian can be more helpful because then I don't read them and get upset that your code no longer does what you wrote in that comment last week.

Names are just names. It doesn't make much difference what you name the pins and variables, so long as it makes sense to you.

So, on to the code...

{You} {have} too many {} in your AVVIO() function.

You have a lot of lines with { followed by code. It is a lot easier to read if you never write anything after the {. Additionally, sometimes you put the { on a line after the if() or while() and sometimes you don't. Pick one style and keep that style.

      while (ms - redmsLast > (redLEDState ? 100 : 100))

{
        digitalWrite(BUZZER, redLEDState = !redLEDState);
        redmsLast = ms;
        StartCount =  StartCount + 1;
      }

Is this supposed to stick in this loop for 100ms? It doesn't. It just turns the buzzer on, updates the LED state, redmslast and StartCount and then exits, with the buzzer still buzzing. This would make sense if it was written as an if().

Is the red LED supposed to flash at the same time as the buzzer? This doesn't do a digitalWrite() to the redLED pin, so it's not going to do anything.

I see large amounts of blocking code. While you have used millis() in many places, each time you blink an LED you're stuck in that function for many, many seconds. A delayed alarm trigger followed by an "immediato" will ignore the immediato because it is still blinking the LED.

Have a look at Planning and Implementing an Arduino Program.