Push button pressed once and action done only once

my question is in regards to push button.

say that I have few relays turns on and off with a sketch that runs in the loop and that sketch runs only after the pushbutton is pressed. so , if nothing else in the sketch, that will keep repeating in the loop and look for push button action input. If I press the push button then it will repeat that relay action again.

what I want it to happen is that; one press on the push button and the relays runs on their sketched sequence. but then, the second time the push button is pressed; I don't' want the sketch to do the relay sequence nor anything else until the Arduino is power cycled or rebooted or reset.

so, I only want the push button action done (pressed) only once and the sketch to run the relays sequence and then stops and awaits till the next power cycle but not when the button is pressed the second time.

is there any ways to achieve this?

I've tried adding very long delay (ie: 12 hours) but then the sketch doesn't runs at all. as if though the the long delays stops the sketch runs even once after the 1st push button action.

Before asking questions:


If your sketch was generated with an AI like ChatGPT, tell us prior to asking your questions.

If the sketch you post was mainly written by someone else tell us.


  • Questioners know what their hardware and software looks like but the volunteers here do not; you need to fully explain what’s not working, and how it is supposed to work.
  • Please read all the posting guidelines before asking your questions, follow these guidelines in your posts.

  • Always show us a good schematic of your proposed circuit.
  • Show us good images of your ‘actual’ wiring.
  • Give WEB links to components.

  • In the Arduino IDE, use Ctrl T or CMD T to format your code, then copy the complete sketch.
  • Use the < CODE / > icon from the ‘posting menu’ to attach your copied sketch.

When you follow the posting guidelines, volunteers can be more effective.

2 Likes

Thank you Delta,

I do want nothing happens until power cycle, but I want the sketch to run once with the 1st push button action, however, I don't want the 2nd, 3rd, 4th ...... n th push button action to do noting until next power cycle or reset.

adding very long delay at the end of the sketch doesn't even let it to run even once.

You set a persistent variable up as a one-shot flag, and check the flag before you do the action:


bool armed = true;
...

void loop(){
   if (armed && digitalRead(buttonPin) == PRESSED){
      armed = false;
      ...
   }
   ...
}

// Constants:
int buttonState = 0;
int pushButtonPin = 3;
int pushButton;
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;

void setup() 
{
  // setup code here, to run once:
  pinMode(pushButton, INPUT);
  pinMode(relay_1, OUTPUT);
  pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT);
}

void loop() 
{
  // read the state of the pushbutton
  buttonState = digitalRead(3);
  // check if pushbutton is pressed. if it is, then...
  // button state is HIGH
  if (buttonState == HIGH) 
  {
    // step one:
  digitalWrite(relay_1, HIGH);  
  digitalWrite(relay_2, HIGH);  
   delay(500);					
  digitalWrite(relay_2, LOW); 
  digitalWrite(relay_1, LOW);  
   delay(1000);                
  
  
 // step two:
  digitalWrite(relay_1, HIGH);  
   delay(500);                  
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(500);                 
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(500);                 
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(500);                 
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(500);                 
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(500);                 
  digitalWrite(relay_3, HIGH);  
	delay(500);                 
  digitalWrite(relay_3, LOW);   
	delay(1000);                
  digitalWrite(relay_1, LOW);   
    delay(500);                 
   	
  
 // step three:  
  digitalWrite(relay_1, HIGH);  
  digitalWrite(relay_2, HIGH);  
   delay(500);                  
  digitalWrite(relay_2, LOW);   
  digitalWrite(relay_1, LOW);   
      

  } 
  else 
  {
    digitalWrite(relay_1, LOW);
    digitalWrite(relay_2, LOW);
    digitalWrite(relay_3, LOW);
  }
  delay(43200000); // 
}

Ok Delat_G, here is the code, So how would you use the while (1) to run my requirement.

don't forget; I need the sketch to run and repeat  the loop till I press the Pushbutton and execute the void loop just once, and then it should enter into infinite loop with while(1) till power cycle or reset.

look this over

const byte PinBut = A1;

byte butLst;

enum { Start, Run, WaitForever };
int state = Start;


void loop()
{
    byte but = digitalRead (PinBut);
    if (butLst != but)  {
        butLst = but;
        delay (20);

        if (LOW == but)
            if (WaitForever > state)
                state++;
    }

    switch (state)  {
    case Run:
        Serial.println ("run");
        delay (1000);
        break;

    case WaitForever:
        Serial.println ("waitForever");
        while (1)
            ;
    }
}

void setup() {
    Serial.begin(9600);
    Serial.println ("ready");

    pinMode (PinBut, INPUT_PULLUP);
    butLst = digitalRead (PinBut);
}

As a fairly newbie programmer, it looks like both gcjr and Delta_G code snippets would work. However gcjr's is a little complex looking with the case/switch stuff, and Delta_G's might be hard to modify in the future. I would set it up like DaveX suggested, with a "flag" to control it. I'd do something like this. It is probably not the most efficient way to do it but it makes sense to me and I think it would be easy to modify in the future.

//Stuff I am adding
int buttonPressed = 0;

// Constants:
int buttonState = 0;
int pushButtonPin = 3;
int pushButton;
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;

void setup()
{
  // setup code here, to run once:
  pinMode(pushButton, INPUT);
  pinMode(relay_1, OUTPUT);
  pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT);

  //Putting this here since it seems to be the default state of your sketch. (I'm not sure it's even needed though, I assume the Arduino treats them as LOW if it's not told otherwise)
  digitalWrite(relay_1, LOW);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_3, LOW);
}

void loop()
{
  if (buttonPressed == 0) { //(only need to read this if it hasn't been pressed yet)
  // read the state of the pushbutton
  buttonState = digitalRead(3);

    // check if pushbutton is pressed. if it is, then...
    // button state is HIGH
    if (buttonState == HIGH)
    {
      // step one:
      buttonPressed = 1; // ensure none of the loop ever happens again since this will never be 0 again
      digitalWrite(relay_1, HIGH);
      digitalWrite(relay_2, HIGH);
      delay(500);
      digitalWrite(relay_2, LOW);
      digitalWrite(relay_1, LOW);
      delay(1000);


      // step two:
      digitalWrite(relay_1, HIGH);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(500);
      digitalWrite(relay_3, HIGH);
      delay(500);
      digitalWrite(relay_3, LOW);
      delay(1000);
      digitalWrite(relay_1, LOW);
      delay(500);


      // step three:
      digitalWrite(relay_1, HIGH);
      digitalWrite(relay_2, HIGH);
      delay(500);
      digitalWrite(relay_2, LOW);
      digitalWrite(relay_1, LOW);
    }
  }
}
1 Like

Looks good-- Good luck!

Using buttonPressed as a "flag" to control whether the chunk of code works is very close to the same mechanics as @gcjr's solution. Consider @gcjr's 'state' variable to work much the same as 'buttonPressed' instead of 0 and not-0, it has three different options, and changes to 'state' control which chunk of code operates.

Both of them are "state machines" which are a basic building block for code that ever needs to do more than one thing at a time.

Another trick that all three codes share is the 'while(1){;}' trick, which in state machines is called an "absorbing state" because once it gets into that infinite loop, it never gets out of the state. @gcjr's absorbing state is the while(1); infinite loop inside of the Waitforever case, @Delta_G's absorbing state is the while(1); at the end of the code in loop(), and mine/yours is that there isn't anything left in loop() when the flag is triggered. It may not look like a while, but 'loop()' is called from a '`while(true){ loop();...}' line in the Arduino initialization code.

there is another solution for code that shall run only once until next power-up:
do you recognize this comment?

put the code in setup() and you are done.

a shortened version of setup to give the overview

void setup() {
  // setup code here, to run once:
  // define IO-pins
  // switch relays off
  while (digitalRead(pushButtonPin) == LOW)  // wait for the button-press
    ;
  
  //when the while-loop is left as the last thing to do
  relaySwitching();  
  //then exiting setup() // and NEVER execute the code in setup again. NEVER executing code again is the ONE AND ONLY purpose of setup()
}

void loop() {
  // stays totally empty to really do nothing
}

the full code

// Constants:
int buttonState = 0;
int pushButtonPin = 3;
int pushButton;
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;

void setup() {
  // setup code here, to run once:
  pinMode(pushButton, INPUT);
  pinMode(relay_1, OUTPUT);
  pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT);

  digitalWrite(relay_1, LOW);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_3, LOW);

  while (digitalRead(pushButtonPin) == LOW)  // wait for the button-press
    ;
  
  //when the while-loop is left as the last thing to do
  relaySwitching();  
  //then exiting setup()
}

void loop() {
  // stays totally empty to really do nothing
}


void relaySwitching() {
  // step one:
  digitalWrite(relay_1, HIGH);
  digitalWrite(relay_2, HIGH);
  delay(500);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_1, LOW);
  delay(1000);


  // step two:
  digitalWrite(relay_1, HIGH);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(1000);
  digitalWrite(relay_1, LOW);
  delay(500);


  // step three:
  digitalWrite(relay_1, HIGH);
  digitalWrite(relay_2, HIGH);
  delay(500);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_1, LOW);
}

best regards Stefan

1 Like

this portion of the code executed prior to the button-press is a permanently repeated switching off of the relays

can be done before the while-loop in setup()

1 Like
if (pb_permitted)
{
  digitalRead(pushbutton);  
  // by implication --
  // if (!permitted)
  // {pb isn't looked at}
}
1 Like

Thank you guys, all of you.

its great that there are more than one way get things done.
all the options discussed could work i think, I was originally interested in while(1) as Delta_G's, for the simplicity, as it was just a simple word and number, but as everyone says that it just stops my code dead in its track, not a very good approach and everyone agrees (including me) . since all of your inputs, I have decided to try all the different approaches and modify my code.

1 Like

I am afraid I've setteld for while(1) as per Delta_G's suggestion. All because, I need part of the code to loop until I hit the pushbutton. So, I need the sketch to loop until I hit the button. Then I need it to stop till next powercycle or board reset. Unless anyone has better suggestion, this seems to be the best solution.

depending on what the code is that needs to loop
just put it inside the while-loop that is waiting for the button-press
like shown in this WOKWI-simulation

The code you have really posted just has a switching off of the relays

The IO-pins keep their logic state
until you change the logic state
so a single time executing

    digitalWrite(relay_1, LOW);
    digitalWrite(relay_2, LOW);
    digitalWrite(relay_3, LOW);

is completely sufficient to keep the relays switched off for years

If you need any other code to loop this looping can be done
inside function setup()
like shown in this code

I have added serial printing to make visible what the code is doing

// Constants:
int buttonState = 0;
int pushButtonPin = 3;
int pushButton;
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  // setup code here, to run once:
  pinMode(pushButton, INPUT);
  pinMode(relay_1, OUTPUT);
  pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT);
  Serial.println("IO-pins configured");

  digitalWrite(relay_1, LOW);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_3, LOW);
  Serial.println("all relays LOW");
  
  Serial.println("waiting for button-press");
  while (digitalRead(pushButtonPin) == LOW) { // wait for the button-press
    // remove the two lines for real application
    Serial.println("inside loop waiting for buttonpress");
    delay(500);
  } 
  
  Serial.println("button-press detected execute relay-ON/OFF-Sequence");
  //when the while-loop is left as the last thing to do
  relaySwitching();  
  Serial.println("relaySwitching done exiting setup");

  //then exiting setup()
}

void loop() {
  // stays totally empty to really do nothing
  delay(2000);
  Serial.println("loop can be empty then really NOTHING happends");
}


void relaySwitching() {
  // step one:
  Serial.println("step one");

  digitalWrite(relay_1, HIGH);
  digitalWrite(relay_2, HIGH);
  delay(500);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_1, LOW);
  delay(1000);


  // step two:
  Serial.println("step two");
  digitalWrite(relay_1, HIGH);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(500);
  digitalWrite(relay_3, HIGH);
  delay(500);
  digitalWrite(relay_3, LOW);
  delay(1000);
  digitalWrite(relay_1, LOW);
  delay(500);


  // step three:
  Serial.println("step three");

  digitalWrite(relay_1, HIGH);
  digitalWrite(relay_2, HIGH);
  delay(500);
  digitalWrite(relay_2, LOW);
  digitalWrite(relay_1, LOW);
}

here is a WOWKI-simulation of that code

this is the serial printing

Setup-Start
IO-pins configured
all relays LOW
waiting for button-press
inside loop waiting for buttonpress
inside loop waiting for buttonpress
inside loop waiting for buttonpress
inside loop waiting for buttonpress
inside loop waiting for buttonpress
button-press detected execute relay-ON/OFF-Sequence
step one
step two
step three
relaySwitching done exiting setup
loop can be empty then really NOTHING happends
loop can be empty then really NOTHING happends
loop can be empty then really NOTHING happends
loop can be empty then really NOTHING happends
loop can be empty then really NOTHING happends
loop can be empty then really NOTHING happends

Would you mind posting your final code that I can see what code you have to loop
before the button-press

best regards Stefan

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.