Ending an 'if' statement midway through

I am writing code for a boat to autonomously complete a mission. I'm using a remote to start the mission. I would like to be able to stop the 'if' statement if the boat isn't running correctly by pressing a different button on the remote so I don't have to wait for the entire statement to be completed. I don't know which command to use or where to even begin for this.

Thank you!!

#include <IRremote.h>
#include <Servo.h>

Servo myservo;

#define ONE 0xFF30CF
#define ZERO 0xFF6897
#define LED 3 //LED Pin 3
#define E1 4 //Enable A Pin 4 (RIGHT MOTOR)
#define I1 5 //In 1 Pin 5
#define I2 6 //In 2 Pin 6
#define E2 7 //Enable B Pin 7 (LEFT MOTOR)
#define I3 8 //In 3 Pin 8
#define I4 9 //In 4 Pin 9
#define SERVO 10 //Servo Pin 10
//#define NEUTRAL 270 //Neutral Servo Position at 270 degrees



int RECV_PIN = 2; //IR Receiver Pin 2
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  irrecv.enableIRIn(); // start the receiver
  
  myservo.attach(SERVO);
  
  pinMode(LED, OUTPUT);
  pinMode(E1, OUTPUT); 
  pinMode(I1, OUTPUT);
  pinMode(I2, OUTPUT);
  pinMode(E2, OUTPUT); 
  pinMode(I3, OUTPUT);
  pinMode(I4, OUTPUT);

  digitalWrite(LED, LOW);
  analogWrite(E1, 0);
  analogWrite(E2, 0);
  myservo.write(0);
}

void loop() {
  // put your main code here, to run repeatedly:  
  if(irrecv.decode(&results)) { 
    
    if (results.value == ONE) {
      digitalWrite(I1, LOW);      // Forward: I1 LOW, I2 HIGH, I3 LOW, I4 HIGH
      digitalWrite(I2, HIGH);     // Reverse: I1 HIGH, I2 LOW, I3 HIGH, I4 LOW
      digitalWrite(I3, LOW);
      digitalWrite(I4, HIGH);
      digitalWrite(LED, HIGH);   // Begin testing all functions
      delay(1000);
      digitalWrite(LED, LOW);
      delay(500);
      analogWrite(E1, 200);
      delay(500);
      analogWrite(E1, 0);
      delay(500);
      analogWrite(E2, 200);
      delay(500);
      analogWrite(E2, 0);
      delay(500);
      myservo.write(90);
      delay(500);
      myservo.write(0);         // End testing all functions
      delay(2000); 
      digitalWrite(LED, HIGH);
      analogWrite(E1, 255);
      analogWrite(E2, 255);
      delay(1500);
      analogWrite(E1, 0);
      analogWrite(E2, 0);
      delay(500);
      digitalWrite(I1, HIGH);
      digitalWrite(I2, LOW);
      digitalWrite(I3, HIGH);
      digitalWrite(I4, LOW);
      analogWrite(E1, 200);
      analogWrite(E2, 200);
      delay(1500);
      analogWrite(E1, 0);
      analogWrite(E2, 0);
      myservo.write(140);
      digitalWrite(LED, LOW);
      
      
    }
    else if (results.value == ZERO) {
      myservo.write(0);
      digitalWrite(LED, LOW);
      analogWrite(E1, 0);
      analogWrite(E2, 0);
    }
    irrecv.resume();
  }
  delay(200);
 
}

break;

I would like to recommend the following way:

  • put all code inside "if statement" to a self-defined function.
  • change all delay() function by using while() loop and millis() function
  • inside the while() loop, use a code to check command. if the command is exit, just terminate the self-defined function by using the return statement

break won't work because it's not within a loop or switch.

you could use return.

... I haven’t used break ‘elsewhere’ for a while, sorry, I thought it worked in an if() .
Sorry for the diversion.

This may help

One of the problems you face is that your program is completely occupied executing the actions of "ONE" because it's never given the chance to do other things. Using delay() is one thing contributing to that. The other is perhaps thinking too "linearly" in the order of operations to be done.

In the code below, I took your code and created a state machine (no promises I did it error-free!) that eliminates the delays() and, further, allows the processor to check for things like IR receive events even while it is executing a "ONE" command. This is because, in principle at least, the state machine allows the processor to do a few things, then come back and check the IR, then go do other things, and check IR etc.

If it's executing "ONE and you press ZERO, the intent of the logic below is to sense that you pressed the ZERO and immediately switch to that state.

Comments added for explanation. Compiles, not tested. YMMV.

Too long for one post; had to split it into two.

#include <IRremote.h>
#include <Servo.h>

Servo myservo;

#define ONE     0xFF30CF
#define ZERO    0xFF6897
#define LED     3 //LED Pin 3
#define E1      4 //Enable A Pin 4 (RIGHT MOTOR)
#define I1      5   //In 1 Pin 5
#define I2      6 //In 2 Pin 6
#define E2      7 //Enable B Pin 7 (LEFT MOTOR)
#define I3      8 //In 3 Pin 8
#define I4      9 //In 4 Pin 9
#define SERVO   10 //Servo Pin 10
//#define NEUTRAL 270 //Neutral Servo Position at 270 degrees

int RECV_PIN = 2; //IR Receiver Pin 2
IRrecv irrecv(RECV_PIN);
decode_results results;

uint8_t
    newStateBoat,
    stateBoat;
uint32_t
    timeNow;

enum bsmStates
{
    ST_IDLE = 0,
    ST_ZERO = 1,
    ST_ONE = 2
};

enum soneStates
{
    ST_ONE_DELAY = 0,
    ST_ONE_1 = 1,
    ST_ONE_2 = 2,
    ST_ONE_3 = 3,
    ST_ONE_4 = 4,
    ST_ONE_5 = 5,
    ST_ONE_6 = 6,
    ST_ONE_7 = 7,
    ST_ONE_8 = 8,
    ST_ONE_9 = 9,
    ST_ONE_10 = 10,
    ST_ONE_11 = 11,
    ST_ONE_12 = 12
    
};

void setup() 
{
    // put your setup code here, to run once:
    Serial.begin(9600);
    irrecv.enableIRIn(); // start the receiver
  
    myservo.attach(SERVO);
  
    pinMode(LED, OUTPUT);
    pinMode(E1, OUTPUT); 
    pinMode(I1, OUTPUT);
    pinMode(I2, OUTPUT);
    pinMode(E2, OUTPUT); 
    pinMode(I3, OUTPUT);
    pinMode(I4, OUTPUT);

    digitalWrite(LED, LOW);
    analogWrite(E1, 0);
    analogWrite(E2, 0);
    myservo.write(0);

    newStateBoat = bsmStates::ST_IDLE;
    stateBoat = newStateBoat;
    
}//setup

void loop( void ) 
{
    static uint32_t
        timeLoop;

    //check the BSM (boat state machine) every loop
    BoatStateMachine();

    //every 200mS check the IR receiver
    timeNow = millis();
    if( (timeNow - timeLoop) >= 200ul )
    {
        timeLoop = timeNow;
        if(irrecv.decode(&results)) 
        {     
            switch( results.value )
            {
                case    ZERO:
                    //ZERO pressed
                    //set "new" state to ZERO
                    newStateBoat = bsmStates::ST_ZERO;
                break;
                
                case    ONE:
                    //ONE pressed
                    //set "new" state to ONE
                    newStateBoat = bsmStates::ST_ONE;
                break;
    
            }//switch
            
            irrecv.resume();
            
        }//if
    
    }//if
 
}//loop

void BoatStateMachine( void )
{
    static uint8_t
        stateONECurrent,
        stateONENext;
    static uint32_t
        timeDelay,
        timeBoat;

    //check for a change of state
    //if "new" state does not equal current state, set up for the change
    if( newStateBoat != stateBoat )
    {
        stateBoat = newStateBoat;
        switch( stateBoat )
        {
            case    bsmStates::ST_ZERO:
                //request to change to state ZERO
                //no init required
            break;

            case    bsmStates::ST_ONE:
                //request to change to state ONE
                //init the boat and ST_ONE state machine
                myservo.write(0);
                digitalWrite(LED, LOW);
                analogWrite(E1, 0);
                analogWrite(E2, 0);
                
                stateONECurrent = soneStates::ST_ONE_1;
            break;
            
        }////switch
        
    }//if

    timeNow = millis();

Part II follows...

Part II:

   switch( stateBoat )
    {
        case    bsmStates::ST_IDLE:
            //do nothing in idle state
        break;
        
        case    bsmStates::ST_ZERO:
            //original ZERO code
            myservo.write(0);
            digitalWrite(LED, LOW);
            analogWrite(E1, 0);
            analogWrite(E2, 0);

            //when complete, return to IDLE state
            stateBoat = bsmStates::ST_IDLE;                
            
        break;
        
        case    bsmStates::ST_ONE:
            //because of the complexity of things going on in ONE
            //and because there are numerous time delays, an "inner state machine" is
            //used to sequence all that
            switch( stateONECurrent )
            {
                case    soneStates::ST_ONE_DELAY:
                    //common delay for all ST_ONE sub-states
                    //when the delay is finished, stateONECurrent is set to
                    //the value Next that was set in the calling state
                    if( (timeNow - timeBoat) >= timeDelay )
                        stateONECurrent = stateONENext;
                break;

                case    soneStates::ST_ONE_1:
                    digitalWrite(I1, LOW);      // Forward: I1 LOW, I2 HIGH, I3 LOW, I4 HIGH
                    digitalWrite(I2, HIGH);     // Reverse: I1 HIGH, I2 LOW, I3 HIGH, I4 LOW
                    digitalWrite(I3, LOW);
                    digitalWrite(I4, HIGH);
                    digitalWrite(LED, HIGH);   // Begin testing all functions
                    //grab the time now
                    timeBoat = timeNow;
                    //the size of the delay
                    timeDelay = 1000ul;
                    //next state will be the delay
                    stateONECurrent = soneStates::ST_ONE_DELAY;                    
                    //when the delay is finished, next state will be ST_ONE_2
                    stateONENext = soneStates::ST_ONE_2;
                    
                break;

                case    soneStates::ST_ONE_2:
                    digitalWrite(LED, LOW);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_3;
                break;

                case    soneStates::ST_ONE_3:
                    analogWrite(E1, 200);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_4;
                break;

                case    soneStates::ST_ONE_4:
                    analogWrite(E1, 0);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_5;
                break;
                
                case    soneStates::ST_ONE_5:
                    analogWrite(E2, 200);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_6;
                break;

                case    soneStates::ST_ONE_6:
                    analogWrite(E2, 0);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_7;
                break;

                case    soneStates::ST_ONE_7:
                    myservo.write(90);
                    timeBoat = timeNow;
                    timeDelay = 2000ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_8;
                break;
                
                case    soneStates::ST_ONE_8:
                    myservo.write(0);         // End testing all functions
                    timeBoat = timeNow;
                    timeDelay = 2000ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_9;
                break;
            
                case    soneStates::ST_ONE_9:
                    digitalWrite(LED, HIGH);
                    analogWrite(E1, 255);
                    analogWrite(E2, 255);
                    timeBoat = timeNow;
                    timeDelay = 1500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_10;
                break;
            
                case    soneStates::ST_ONE_10:
                    analogWrite(E1, 0);
                    analogWrite(E2, 0);
                    timeBoat = timeNow;
                    timeDelay = 500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_11;
                break;
            
                case    soneStates::ST_ONE_11:
                    digitalWrite(I1, HIGH);
                    digitalWrite(I2, LOW);
                    digitalWrite(I3, HIGH);
                    digitalWrite(I4, LOW);
                    analogWrite(E1, 200);
                    analogWrite(E2, 200);
                    timeBoat = timeNow;
                    timeDelay = 1500ul;
                    stateONECurrent = soneStates::ST_ONE_DELAY;
                    stateONENext = soneStates::ST_ONE_12;                    
                break;
            
                case    soneStates::ST_ONE_12:
                    analogWrite(E1, 0);
                    analogWrite(E2, 0);
                    myservo.write(140);
                    digitalWrite(LED, LOW);

                    //when finished sequence, return stateBoat to the IDLE state
                    stateBoat = bsmStates::ST_IDLE;
                break;
                                
            }//switch
            
        break;

    }//switch
    
}//BoatStateMachine

you can use an "if" inside an "if" !!!

if(something == true) {

   // I will always do this if something is true

       if(someotherthing == true){

             // i will only do this if something is true AND someotherthing is true

        }

}

gcjr:
break won't work because it's not within a loop or switch.

you could use return.

In that case the execution would not continue after the 'if' statement closing bracket, though...

aarg:
In that case the execution would not continue after the 'if' statement closing bracket, though...

in that case, the code containing the if could be in a sub-function which is a not such a bad thing to do

I reckon the problem here is in the text of the Title.

There is no such thing as the middle of an IF statement. An IF statement is a single line of code that results in a true or false result.

That result may cause other code to run and the OP may wish to exit from that other code part way through. But that has nothing at all to do with the IF statement. A simple way to achieve that is to use the IF statement to call a function and then the return statement can be used at the place in the function where the OP wants it to exit.

The problem needs to be explained more clearly.

...R