Start and stop a loop with push button

Hi all, first post here, read the rules and searched through so many threads with no luck, so I am desperate.

What I need is pretty straightforward: I want to start and stop a loop with the click of a button.

Example:

  1. Arduino on, setup code has run, loop code not running.
  2. Press button, release button.
  3. Loop starts and repeats until I want to stop.
  4. Press button, release button.
  5. Loop stops.
  6. Repeat.

Every example I see on here is mainly focused on turning an LED or motor on or off, which is simple enough. I can’t find anything to actually run a program as there aren’t really “state changes” and I don’t have LEDs. (EDIT: yes I realize this was stupid, I couldn’t figure out how to word “simple state changes like HIGH and LOW”…)

This is for a temperature data logger using a thermocouple module, I want to click a button to start the loop, record temps over a period of time, and stop the recording so I can remove the SD, review the temps on a graph and do it over and over.

#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
#include <max6675.h>

const int chipSelect = 10; 

int ktcSO = 7;
int ktcCS = 6;
int ktcCLK = 5;

int run;
int buttonPin;

MAX6675 ktc(ktcCLK, ktcCS, ktcSO);

File myFile;

RTC_DS1307 rtc;

void setup() 
{
  run = 0; //starts stopped
  buttonPin = 9;
  pinMode(buttonPin, INPUT_PULLUP);
  
  Serial.begin(9600);
  
  // setup for the RTC
  while(!Serial);
    if(! rtc.begin()) {
      Serial.println("Couldn't find RTC");
      while (1);
    }
    else {
      // following line sets the RTC to the date & time this sketch was compiled
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    }
    if(! rtc.isrunning()) {
      Serial.println("RTC is NOT running!");
    }
    
  // setup for the SD card
  Serial.print("Initializing SD card...");

  if(!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
    
  //open file
  myFile=SD.open("Temperature_Logger.txt", FILE_WRITE);

  // if the file opened ok, write to it:
  if (myFile) {
    Serial.println("File opened ok");
    // print the headings for our data
    myFile.println("Date, Time, Temperature ºC");
  }
  myFile.close();
}


void loggingTime() 
{
     DateTime now = rtc.now();
   char dateBuffer[12];

   sprintf(dateBuffer,"%02u-%02u-%04u ",now.month(),now.day(),now.year());
   Serial.print(dateBuffer);

   sprintf(dateBuffer,"%02u:%02u:%02u ",now.hour(),now.minute(),now.second());
   Serial.println(dateBuffer);


  myFile = SD.open("Temperature_Logger.txt", FILE_WRITE);
  if (myFile) {
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print('/');
    myFile.print(now.year(), DEC);
    myFile.print(", ");
    myFile.print(dateBuffer);
    myFile.print(", ");
  }
  Serial.print(dateBuffer);
  Serial.print(", ");
  myFile.close();
  delay(1000);  
}

void loggingTemperature() 
{
  myFile = SD.open("Temperature_Logger.txt.txt", FILE_WRITE);
  if (myFile) {
    Serial.println("open with success");
    Serial.print(ktc.readCelsius());
    Serial.println(",");
    myFile.print(ktc.readCelsius());
    myFile.println(" ");
  }
  myFile.close();
}

void loop() 
{
  {
  loggingTime();
  loggingTemperature();
  delay(1000);
  }
}

loggerMay11.ino (2.35 KB)

there aren’t really “state changes”

Apart from the “loop running” / “loop not running” states.
And the “switch not pressed” / “switch pressed” states.

More members will see your code if you post your code as described in the forum guidelines.

TheMemberFormerlyKnownAsAWOL:
Apart from the "loop running" / "loop not running" states.
And the "switch not pressed" / "switch pressed" states.

Got it. I worded it wrong. Appreciate the wisdom.

groundFungus:
More members will see your code if you post your code as described in the forum guidelines.

Fixed. Sorry about that.

It's rather straightforward:

void loop {
  if(loopRunning) {
    doYourThingHere;
  }

  buttonState = digitalRead(buttonPin);
  if((buttonState==LOW) && (prevButtonState==HIGH)) {
    loopRunning = !loopRunning;
  }
  prevButtonState=buttonState;
}

TimMJN:
It's rather straightforward:

void loop {

if(loopRunning) {
    doYourThingHere;
  }

buttonState = digitalRead(buttonPin);
  if((buttonState==LOW) && (prevButtonState==HIGH)) {
    loopRunning = !loopRunning;
  }
  prevButtonState=buttonState;
}

Tim, thank you so much. I will try it after I get home from work, but from what I can tell this is exactly what I was looking for; I found stuff similar to this but never had the "loop" part in it and only had previous LED states which didn't help me.

Thank you again! I was starting to wonder if it was a mistake to post on here.

h2otwa:
Tim, thank you so much. I will try it after I get home from work, but from what I can tell this is exactly what I was looking for; I found stuff similar to this but never had the "loop" part in it and only had previous LED states which didn't help me.

Thank you again! I was starting to wonder if it was a mistake to post on here.

Happy to help! If you follow some online/free coding lessons, you'll soon be thinking up stuff like this yourself!

So I got home and tried it out, and I'm getting an error message that says:

'loopRunning' was not declared in this scope

My code looks like this after adding that part

void loop() {
  if(loopRunning) {
  loggingTime();
  loggingTemperature();
  delay(1000);
  }

  buttonState = digitalRead(buttonPin);
  if((buttonState==LOW) && (prevButtonState==HIGH)) {
    loopRunning = !loopRunning;
  }
  prevButtonState=buttonState;
}

Am I supposed to declare that somehow? I guess I was assuming loopRunning was a command the system knew that I was unaware of.

You need to define the variable.

larryd:
You need to define the variable.

That's what I'm trying to figure out, what would I even put for that?

int loopRunning = ???

Sorry I'm slowly learning here... how can I define if a loop is running or not?

put this before setup()

bool loopRunning = false;
or
boolean loopRunning = false;

I would use this myselg
byte loopRunning = 0;

then flop it back and forth between 0 and 1,
loopRunning = 1 - loopRunning;

so 1 - 0 = 1
and 1 - 1 = 0

The code I posted was just a little snippet, go ahead and use your own critical thinking to figure out how to make it work for you! Worst case scenario you learn something.