How to Repeat a Function until specified Action (Arduino IDE)

In my code I am displaying time on an OLED via bluetooth from an app I've created on MIT app inventor. While I'm displaying the strings of time I am using code to search for an Up Gesture from the 'Sparkfun APDS9660 Gesture Sensor'. Once I do an up gesture I would like to clear the display and show the string "camera". I would like it to stay in the 'camera' function (in code) until I do a down gesture to return to showing 'time' function

void handleGesture() {
  if ( apds.isGestureAvailable() ) {
      
      if(DIR_UP)
      {
        Serial.println("UP");
        Serial.println("Camera");
         display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,20);
  display.println("Camera");
  display.display(); 
        Q = 0;
        while(Q == 0)
        {
          if (DIR_RIGHT)
          {
             digitalWrite(13, HIGH);  
  delay(1000);             
  digitalWrite(13, LOW);    
  delay(1000); 
          }
        
        if (DIR_LEFT)
        {
           digitalWrite(12, HIGH);  
  delay(1000);             
  digitalWrite(12, LOW);    
  delay(1000);
        }
        if (DIR_DOWN)
        {
          break;
        }
        }
      
        
     
    }
}
}

I'm trying to use a 'while loop' to repeat the code and then a 'break' to exit the code. If anyone knows any better solutions please comment.

Thanks for All Reply's

My suggestion. Comments that I hope is enough for you to implement it in your own program.

void handleGesture() {
  if ( apds.isGestureAvailable() ) {

    if (DIR_UP)
    {
      cameraMode = true;  //cameraMode declared global
    }

    if (DIR_DOWN)
    {
      camerMode = false;
    }

    if (DIR_RIGHT)
    {
      digitalWrite(13, HIGH);
      delay(1000);
      digitalWrite(13, LOW);
      delay(1000);
    }

    if (DIR_LEFT)
    {
      digitalWrite(12, HIGH);
      delay(1000);
      digitalWrite(12, LOW);
      delay(1000);
    }
  }
}

// Following block should be somewhere in loop().
// Include a check for if cameraMode == false in your time routine
if (camerMode = true)
{
  Serial.println("UP");
  Serial.println("Camera");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 20);
  display.println("Camera");
  display.display();
}

Daniel_Quintana:
I'm trying to use a 'while loop' to repeat the code and then a 'break' to exit the code.

Don't use WHILE and then you won't need BREAK

Just let loop() look after the iteration and use a simple IF to determine when something needs to happen. Have a look at the demo Several Things at a Time

...R

Thank you for your reply Robin2 however I am still confused on how I would keep the camera function looping until I gesture down. I'm guessing you mean the loop will look a little like this.

void loop() {

  if( isr_flag == 1 ) {
    detachInterrupt(0);
    Time();
    if(DIR_UP)
{
    Camera();
}
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

How would I keep the camera function repeating(looking for a right or left gesture to control pins 12 and 13) while looking for a down gesture that will go back to time function. Also the interrupt is for the gesture sensor, will the sensor still work if its in camera mode and not the void loop?

Thank your for your reply Delta_G. What you are saying makes sense and works for the simplicity of my code (for now). But later I would like to expand, my train of thought would be like how a smart watch has many apps. If you press one button it goes into Alarms, one button goes into Games and maybe another goes into a Camera, and the last would go to home which would be displaying Time. This is why I was trying to get the code to stay in one function as if they were apps on a smart watch. Maybe I'm still thinking about this wrong? Thank you for your time.

So I think the loop(and interrupt routine) would look like this if I do what your saying.

void loop() {

  if( isr_flag == 1 ) {
    detachInterrupt(0);
    if(DIR_DOWN)
    {
      Serial.print("Down");
      mode = 0;
    }
    if(DIR_UP)
    {
      mode = 1;
    }
    if (mode == 0)
    {
      Time();
    }
    if (mode == 1)
    {
    Camera();
    }
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

void interruptRoutine() {
  isr_flag = 1;
}

Here is the camera function.

void Camera() {
  if ( apds.isGestureAvailable() ) {
      
      if(DIR_UP)
      {
        Serial.println("UP");
        Serial.println("Camera");
         display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,20);
  display.println("Camera");
  display.display(); 
        
        
          if (DIR_RIGHT)
          {
            display.clearDisplay();
             display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("picture");
  display.display();
          }
        
        if (DIR_LEFT)
        {  display.clearDisplay();
           display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,10);
  display.println("video");
  display.display();
        }
        
        }
      
        
     
    }
}

And here is the time function.

void Time(){

  while (BT.available()){  //Check if there is an available byte to read
  
  char c = BT.read(); //Conduct a serial read
   state += c;
  } 

 if (state.startsWith(""))
    {
      display.clearDisplay();
      Serial.println(state);
      display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

       display.print(state);

       display.display();
       
state = "";
      
      
    }
}

As you can see have have some serial print commands to help debug but the serial monitor shows--------------------------------
SparkFun APDS-9960 - GestureTest

APDS-9960 initialization complete
Gesture sensor is now running
DownUP
Camera
DownUP
Camera
DownUP
Camera
DownUP
ect.
Im I doing something wrong?

Daniel_Quintana:
So I think the loop(and interrupt routine) would look like this if I do what your saying.

Post the whole program in one piece - it is much easier to make sense of it that way. If it is too long (I hope not) then add the .ino file as an attachment.

What is the ISR supposed to do and why are you detaching it? Normally ISRs are started in setup() and run continuously, though there are exceptions.

...R

Alright, here is all the code after the suggestion from Delta_G,

#include <SPI.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define APDS9960_INT    2 

SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
int sec = 00;
int mn = 00;
int hr = 00;
int mode = 0;


SoftwareSerial BT(10,11);
String state;

void setup() {
 BT.begin(9600);
  // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();

  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - GestureTest"));
  Serial.println(F("--------------------------------"));
  
  // Initialize interrupt service routine
  attachInterrupt(0, interruptRoutine, FALLING);

  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9960 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9960 init!"));
  }
  
  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) ) {
    Serial.println(F("Gesture sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during gesture sensor init!"));
  }
}

void loop() {

  if( isr_flag == 1 ) {
    detachInterrupt(0);
    if(DIR_DOWN)
    {
      Serial.print("Down");
      mode = 0;
    }
    if(DIR_UP)
    {
      mode = 1;
    }
    if (mode == 0)
    {
      Time();
    }
    if (mode == 1)
    {
    Camera();
    }
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

void interruptRoutine() {
  isr_flag = 1;
}

void Camera() {
  if ( apds.isGestureAvailable() ) {
      
      if(DIR_UP)
      {
        Serial.println("UP");
        Serial.println("Camera");
         display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,20);
  display.println("Camera");
  display.display(); 
        
        
          if (DIR_RIGHT)
          {
            display.clearDisplay();
             display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("picture");
  display.display();
          }
        
        if (DIR_LEFT)
        {  display.clearDisplay();
           display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,10);
  display.println("video");
  display.display();
        }
        
        }
      
        
     
    }
}


void Time(){

  while (BT.available()){  //Check if there is an available byte to read
  
  char c = BT.read(); //Conduct a serial read
   state += c;
  } 

 if (state.startsWith(""))
    {
      display.clearDisplay();
      Serial.println(state);
      display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

       display.print(state);

       display.display();
       
state = "";
      
      
    }
}

The reason for the ISR is I am trying to keep the code close the the Sparkfun APDS 9960 Gesture test.

#include <SPI.h>
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <SFE_MicroOLED.h>
#define PIN_RESET 9  // Connect RST to pin 9
#define PIN_DC    8  // Connect DC to pin 8
#define PIN_CS    10 // Connect CS to pin 10
#define DC_JUMPER 0
// Pins
#define APDS9960_INT    1 // Needs to be an interrupt pin

// Constants

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
int sec = 00;
int mn = 00;
int hr = 00;
MicroOLED oled(PIN_RESET, PIN_DC, PIN_CS);

void setup() {

  // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT);
oled.begin();    // Initialize the OLED
  oled.clear(ALL); // Clear the display's internal memory
  oled.display();
  oled.clear(PAGE);
  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - GestureTest"));
  Serial.println(F("--------------------------------"));
  
  // Initialize interrupt service routine
  attachInterrupt(0, interruptRoutine, FALLING);

  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9960 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9960 init!"));
  }
  
  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) ) {
    Serial.println(F("Gesture sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during gesture sensor init!"));
  }
}

void loop() {
  if( isr_flag == 1 ) {
    detachInterrupt(0);
    handleGesture();
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

void interruptRoutine() {
  isr_flag = 1;
}

void handleGesture() {
    if ( apds.isGestureAvailable() ) {
    switch ( apds.readGesture() ) {
      case DIR_UP:
        Serial.println("UP");
        break;
      case DIR_DOWN:
        Serial.println("DOWN");
        break;
      case DIR_LEFT:
        Serial.println("LEFT");
        break;
      case DIR_RIGHT:
        Serial.println("RIGHT");
        break;
      case DIR_NEAR:
        Serial.println("NEAR");
        break;
      case DIR_FAR:
        Serial.println("FAR");
        break;
      default:
        Serial.println("NONE");
    }
  }
}

You have not explained what triggers the interrupt. How does it relate to apds.isGestureAvailable()

I think understanding that is key to sorting out your problem.

...R

Also posted at while loop - Repeat a Function until specified Action (Aruino IDE) - Stack Overflow