Breaking out of a loop within if statements

I’ve been coding my LCD screen for a project I’ve been working on for some time now and I’m stuck on a small part. I’ve built a simple menu with two options using if statements seen in the code below.

My problem is once you press SELECT to begin data logging, it will continue logging and won’t break out of the code if one wants to go back to the Options menu if someone wanted to scroll between start and stop. I’ve tried a break statement and return statement and nothing works.

My code is not fully complete, just where I’m at right now. Any advice would be great.

#include <Wire.h>

#include <Arduino.h>

#include <Adafruit_MCP23017.h>

#include <Adafruit_RGBLCDShield.h>

#include <stdlib.h>

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

#define WHITE 0x7

int last_button_left = 0;

int last_button_right = 0;

int last_button_select = 0;

void setup(){
 // setting up interrupts
 attachInterrupt(BUTTON_SELECT, loop, RISING);
 
 Serial.begin(9600);
 lcd.begin(16,2);
 
 lcd.setBacklight(WHITE);
 lcd.print("*** WELCOME! ***");
 
 delay(2000);
 //displayMenu();
 lcd.clear();
 
 lcd.setCursor(0,0);
 lcd.print("Select Option:  ");
  
 lcd.setCursor(0,1);
 lcd.print(" >Start     Stop");
  
}

uint8_t i=0;


void loop(){
  
  uint8_t buttons = lcd.readButtons();

    if(buttons) {
       
       if ((buttons & BUTTON_SELECT) && (last_button_left == 0) && (last_button_right == 0) && (last_button_select == 0)){
         lcd.clear();
         
         lcd.setCursor(0,0);
         lcd.print("Selected: Start");
         
         lcd.setCursor(0,1); 
         lcd.print("Collecting data.");
         
         // read the input on analog pin 0:
         while(true){
           int sensorValue = analogRead(A0);
           
         // print out the value you read:
           Serial.println(sensorValue);
           delay(1);        // delay in between reads for stability
         }
         
         last_button_select = 1;
       
       } else if ((buttons & BUTTON_LEFT) && (last_button_left == 0) && (last_button_right == 0) && (last_button_select == 0)){
         
         last_button_left = 0;
     
       } else if ((buttons & BUTTON_RIGHT) && (last_button_left == 0) && (last_button_right == 0) && (last_button_select == 0)){
          lcd.clear();
          
          lcd.setCursor(0,0);
          lcd.print("Select Option:  ");
  
          lcd.setCursor(0,1);
          lcd.print(" Start     >Stop");
          
          last_button_right = 1;
       
       } else if ((buttons & BUTTON_RIGHT) && (last_button_left == 0) && (last_button_right == 0) && (last_button_select == 1)){
          lcd.clear();
          
          lcd.setCursor(0,0);
          lcd.print("Select Option:  ");
  
          lcd.setCursor(0,1);
          lcd.print(" Start     >Stop");
          
          last_button_right = 1; 
        
       } else if ((buttons & BUTTON_SELECT) && (last_button_left == 0) && (last_button_right == 1) && (last_button_select == 0)){
             lcd.clear();
       
             lcd.setCursor(0,0);
             lcd.print("Selected: Stop");
             
             lcd.setCursor(0,1); 
             lcd.print("Done collecting.");
             // add code to stop collecting data
             
             last_button_select = 1; 
  
        } else if ((buttons & BUTTON_LEFT) && (last_button_left == 0) && (last_button_right == 1) && (last_button_select == 1)) {
             lcd.clear();
             
             lcd.setCursor(0,0);
             lcd.print("Select Option:  ");
  
             lcd.setCursor(0,1);
             lcd.print(" >Start     Stop");
             
             last_button_left = 1;
             last_button_right = 0;
             last_button_select = 0;
          
        } else if ((buttons & BUTTON_SELECT) && (last_button_left == 1) && (last_button_right == 0) && (last_button_select == 0)) {
             lcd.clear();
          
             lcd.setCursor(0,0);
             lcd.print("Selected: Start");
         
             lcd.setCursor(0,1); 
             lcd.print("Collecting data.");
             // add code to begin data transfer
         
         last_button_select = 1;
      
        } else if ((buttons & BUTTON_LEFT) && (last_button_left == 0) && (last_button_right == 1) && ((last_button_select == 0) || (last_button_select == 1))) {
          
             lcd.clear();
             
             lcd.setCursor(0,0);
             lcd.print("Select Option:  ");
  
             lcd.setCursor(0,1);
             lcd.print(" >Start     Stop");
             
             last_button_left = 1;
             last_button_right = 0;
             last_button_select = 0;
             
        } else if ((buttons & BUTTON_RIGHT) && (last_button_left == 1) && (last_button_right == 0) && ((last_button_select == 0) || (last_button_select == 1))) {
          
             lcd.clear();
          
             lcd.setCursor(0,0);
             lcd.print("Select Option:  ");
  
             lcd.setCursor(0,1);
             lcd.print(" Start     >Stop");
             
             last_button_left = 0;
             last_button_right = 1;
             last_button_select = 0;
        }
        
  }
}

You have a "while(true)" loop. It is possible to do a "lcd.readButtons()" while being in the loop and use a "break" to get out.

It is better to remove the "while(true)" and use millis() for timing to read the analog value at a certain interval. You will also need a flag (for example a boolean variable) to indicate that the capturing of the analog input is active or not.

Rather than what you have, you should instead implement what is known as a "state machine".

Basically, the concept is that you have - within an infinite loop (the loop() function will do) - a selection mechanism (can be composed of if-then statements, switch-case, or something similar) that only works on one part of the system based on the "current state" of the system.

Let's look at some pseudo-code for an example:

CHECK-BUTTON = 0
OUTPUT-LCD = 1
TURN-ON-LED = 2
CHECK-SERIAL = 3

current-state = CHECK-BUTTON

loop:

  if current-state = CHECK-BUTTON then:
    get input
    if input is true then current-state = OUTPUT-LCD

  else if current-state = OUTPUT-LCD then:
    show output
    get input
    if input is true then current-state = TURN-ON-LED

  else if current-state = TURN-ON-LED then:
    turn on LED
    current-state = CHECK-SERIAL

  else if current-state = CHECK-SERIAL then:
    get input
    if input = 7 then current-state = CHECK-BUTTON
  
  else
    current-state = CHECK-BUTTON

As you can see from the above pseudo-code, we have a series of "constants" defining states, and a state variable "current-state", which we set to an initial state of "CHECK-BUTTON". As the loop processes, we check what state we are in, try to do something (or nothing at all), then change the current-state accordingly - at which point the loop rolls around and that new state is processed accordingly.

Note the curious case of the "last else" - we should never get to this point (as it would imply a current-state not of the set of states defined), but if somehow we do, we set the current-state to the known initial state of CHECK-BUTTON.

Finally, note that nowhere in all of this do we do anything to stop the looping process; that is, we don't "block" the loop from running - this, as opposed to using delays or other methods which would block the loop. We can easily create timers and other such devices within this state machine (and check their values in order to change state accordingly) - and continue to let the loop run (see the "blink-without-delay" example, among others, for more detail).

If you can understand and master the concepts of "state machines" and of "non-blocking functions" - such as this simple pseudo-code example and the "blink-without-delay" example, you will have gained a bit of very valuable knowledge in software development that will set you apart from your peers, while making your code easier to understand and follow, while also functioning better.