button to run loop once then await button press

Hi all,

I have been battling away with my first arduino project and now have it doing what I want...

I now want to be able to start my loop to run once with the press of a push button and then when finnished await the next push of the button.

I also want to be able to (in the future) add in other loops in the program linked to other buttons so I can in effect choose which loop to run by what button I press.

I'm pretty sure the answer will be 'if' or 'while' loops but not 100% on howto implement it.

Here is my code, everything in the void loop is my first program to be run once with the push of a button.

thank you in advance

#include <PID_v1.h>

// code to increase pressure to 140 bar in increments with 5 second delay inbetween increases before unloading to zero, waiting 10 seconds and repeating.


int starttime1;     //start time and end time for each while loop
int endtime1;

int starttime2;
int endtime2;

int starttime3;
int endtime3;

int starttime4;
int endtime4;


double Setpoint, Input, Output;


PID myPID(&Input, &Output, &Setpoint, 0.001, 0.6, 0.001, DIRECT);   //tuning parameters P,I,D 


void setup() {

  Input = analogRead(A0);     //pressure sensor signal 

  myPID.SetMode(AUTOMATIC);

  Serial.begin(9600);

}

void loop() {



  analogWrite(5,0);

  myPID.SetTunings(0.001,1.0,0.001);
   
  

  starttime1 = millis();                    //record starttime for while loop below 
  while ((endtime1 - starttime1) <= 32000)  //subtracts start time from end time so loop runs for 32 seconds
  {
    Setpoint = 90;                  //ten bit number for 35 bar assuming full scale 0-400 bar = 0-1023
    Input = analogRead(A0);         //read input from pressure sensor
    myPID.Compute();                //compute relavent output from tuning parameters and sensor reading
    analogWrite(5, Output);         //send output to propertional valve
    Serial.print("pressure = ");`   //next three lines to interpret sensor signal and print the corresponding pressure on serial monitor
    Input=Input*.391;               //calculate pressure in bar from 10 bit number
    Serial.print(Input);
    Serial.println(" BAR");
    delay(1000);                    //1 second delay to allow things to settle
    endtime1 = millis();            //record end time for while loop
    
  }

  Serial.println("5 second pause");

  myPID.SetTunings(0.0001,0.3,0.02);

  delay(5000);

  starttime2 = millis();
  while ((endtime2 - starttime2) <= 32000)
  {
    Setpoint = 180;               // 70 bar     
    Input = analogRead(A0);    
    myPID.Compute();          
    analogWrite(5, Output); 
    Serial.print("pressure = ");
    Input=Input*.391;
    Serial.print(Input);
    Serial.println(" BAR");  
    delay(1000);
    endtime2 = millis();

  }

  Serial.println("5 second pause");

  myPID.SetTunings(0.00001,0.25,0.02);
  
  delay(5000);

  starttime3 = millis();
  while ((endtime3 - starttime3) <= 32000)
  {
    Setpoint = 256;                 // 100 bar
    Input = analogRead(A0);
    myPID.Compute();
    analogWrite(5, Output);
    Serial.print("pressure = ");
    Input=Input*.391;
    Serial.print(Input);
    Serial.println(" BAR");
    delay(1000);
    
   
    endtime3 = millis();
  }

  Serial.println("5 second pause");

  myPID.SetTunings(0.00001,0.26,0.02);
  
  delay(5000);

  starttime4 = millis();
  while ((endtime4 - starttime4) <= 32000)
  {
    Setpoint = 358;                 // 140 bar
    Input = analogRead(A0);
    myPID.Compute();
    analogWrite(5, Output);
    Serial.print("pressure = ");
    Input=Input*.391;
    Serial.print(Input);
    Serial.println(" BAR");
    delay(1000);
    
    
    endtime4 = millis();
  }

  Serial.println("10 second pause and restart");
  
analogWrite(5,0);
delay(10000);
          

}

When you first close the switch 'set' a flag variable.
When the flag variable is set, run your code then 'reset' the flag variable.

Study the 'state change' example in the IDE.

delay(10000); <——<<<< don’t use delay()

Thank your reply, I have added it to my program so will wire up a switch tomorrow and see how it goes.

am I right in saying I can use just an 'if' statement without an 'else' so it will either run when I press the button or just do nothing if I don't?

ignore my last message that is it working now

thank you very much.

so I guess I can just have more button with different names so if the first if statement isn't true it goes to the next etc?

if(there was a change from low to high) //see change in state example for coding
{
flag = true;
}

if(flag == true)
{
//do stuff

flag = false;
}

//more code

so I guess I can just have more button with different names so if the first if statement isn't true it goes to the next etc?

Yes you can

I now want to be able to start my loop to run once with the press of a push button and then when finnished await the next push of the button.

If you only run it once maybe it's not a loop. :wink: If you're only doing it once, it can be a regular if-statement. If you're doing a bunch of stuff when you press a button and bunch of other stuff when you press a different button, you might want to write a [u]function[/u] and then call the function when the button is pushed.

However, you do need to loop while you're waiting for a button-push.... Depending on your program, that might be your main loop...

A "do nothing" while() loop is an easy way to wait for a button push

while (ButtonState == 0)
{
// Run this do-nothing loop until the button is pressed
}

The downside of that is you're "stuck in a loop" doing nothing until the button is pushed, so you have to make sure that's OK in your application.

I also want to be able to (in the future) add in other loops in the program linked to other buttons so I can in effect choose which loop to run by what button I press.

You can use multiple if-statements, or possibly [u]switch-case[/u]. It's very common to call a different function for each "case".

...but not 100% on howto implement it.

You do have to think-about your overall program structure,

You're doing some good work with the millis() based timing - but what are those delay() calls doing there? Get rid of them.

For your button code: do look into state checking (you want to run it only upon the button press, not again and again if the button remains pressed after that) and debouncing.