Start Stop Pause with Button

I’m doing a project with an arduino, a gps module, a microSD module and a bluetooth module.
There is also 2 buttons for the project, one is in charge of sending coordinates to the microSD card and the other one through bluetooth. The first button, the one for microSd card, it has 3 functions: Start, pause, and stop. This is where I need some guidance please!
I’m confused as to how to make a button to pause, and either wait for the start of stop command.
This code is checking buttn1 and 2. If button 1 is pressed, then there will be 3 cases (plus default). This is where I need some suggestions. Please help! How do I make it to where case 2 pauses the loop, and case 3 would I need to add an empty loop too?

thanks

Here is my code so far:

#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#define button1 7
//#define button2 
#define redLED 4
#define greenLED 3

//Pins
const int chipSelect = 10; // setup SD Card Chip Select Pin
int gpsTxPin = A0;
int gpsRxPin = A1;
SoftwareSerial gpsSerial(gpsTxPin, gpsRxPin);
TinyGPSPlus gps;

int state = 0;
int old = 0;
int buttonPoll = 0;
int buttonPoll2 = 0;
pinMode(LED,OUTPUT);

void setup() {
  pinMode(button, INPUT);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED,OUTPUT);
  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, LOW);
 
  Serial.begin(9600);
  gpsSerial.begin(9600);

  while (!Serial) {
    ;
  }
   Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed!");
    digitalWrite(redLED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(redLED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);               // wait for a second
    return;
  }
  Serial.println("card initialized.");
}
void loop() {
  CheckButton1();
  CheckButton2();
  }

void CheckButton1()
{
  buttonPoll = digitalRead(button1); //poll the state of button
  if buttonPoll == 1){
    delay(50);
    buttonPoll = digitalRead(button1); //poll button again
    if(buttonPoll ==0) { //if it's 0 considered one press
    state = old + 1; //incrase stte by 1
  }}
  else{
    delay(100);
  }
  switch (state) {
    case 1: //Start
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
      old = state;
      File dataFile = SD.open("GPSdata.txt", FILE_WRITE);
        // Read GPS Data
      while(gpsSerial.available()>0){
        gps.encode(gpsSerial.read());
      if (gps.location.isUpdated()){
        dataFile.print("Latitude= ");
        dataFile.print(gps.location.lat(), 6);
        dataFile.print(" Longitude= ");
        dataFile.println(gps.location.lng(), 6);
      }dataFile.close();
      break;
    case 2: //Pause
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
      old = state;
      break;
    case 3: //Stop
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
      old = state;
      break;
    default;
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, LOW);
      old = 0;
    break;
  }
  }

void CheckButton2()
{
  while   (digitalRead(button2)   ==   HIGH){
    while(gpsSerial.available()>0){
      gps.encode(gpsSerial.read());
      if (gps.location.isUpdated()){
        Serial.print("Latitude= ");
        Serial.print(gps.location.lat(), 6);
        Serial.print(" Longitude= ");
        Serial.println(gps.location.lng(), 6); 
      }
    }
  }
  else
    digitalWrite(greenLED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(greenLED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);
  }

Hi,

Although I did not read through your entire code (I trust most of it is unrelated to your question), try creating a "state machine" for your button.
You can do this by defining an enum as following:

typedef enum
{
START = 0,
PAUSE = 1,
STOP = 2,
} BUTTON_STATE_E;

Then you can define a variable to represent the state of your button as following:

BUTTON_STATE_E button1State = START;

Each time you detect the button is pushed, advance the state.
In your loop check the state (with a simple "switch-case") and if it's in PAUSE state, just do nothing.

Another more advanced option would be to define button1 as an interrupt and send the device to sleep when it is stopped or paused, but as I'm not familiar with your entire system functionality, I'm not certain this would be the best solution.

Would that be kinda similar to the switch case statements?
Not familiar with state machines with arduino, but I'll take a look at it !

Thank you!

Any clue as to how to Pause/Stop a loop?
The way it is now Case 1 is for Start, case 2 for Pause, and case 3 for stop. Is there a way that Case 2 halts/pauses case 1? and then Case 3 leave it blank.

I did it this way so it would be set for the buttons with each push.

What I'm trying to do is like a stopwatch: you start the time, and you can either pause it or stop it from there. This would be something like with millis, right?

Hi,

The state machine isn’t an arduino specific term. It is a programming method which is useful for when you want to maintain states in your code. In your case, “start”, “pause” and “stop” can be referred to as states.
the switch case is used to determine which state you are in.
Your code is actually doing something similar by incrementing state+1. This is just a more structural way of doing things.

Regarding the loop:
Other than sending the device to sleep, I’m unaware of a way to pause it. But if you’re not trying to save on power, why should this matter to you?

In your loop you can check whether the button has been pushed, update the state accordingly and then check the state using the switch-case as you’re already doing.
If the state reaches the “PAUSE” state you can just “break;”

Meir

I will be implementing a sleep state to make it easier to pause it actually.

For cases statements, is it easier to add the code inside the case statement, or create a void (insert name loop) inside the case statement?
So,

case 1:
code
code
code
code
.....
break;

OR

case 1:
void Code();
break;

void Code()
{
code
code
code
....}

Thank you!

In general, it makes the code more readable and structural when using functions instead of just spilling all the code in one long switch-case statement.

There are real-time implications to function calls, but I trust your system isn't extremely time critical (in the usec resolution), so using functions would probably make more sense in this case.

Meir