How to properly use 'if' command with a button

New to coding with IDE. I want to be able to start my program when I push a button. I've experimented with an If statement along the lines of

`if (buttonStatus == pinValue) {

where buttonStatus is declared as 1 and pinValue is the return from the button.

When using this code, the If function only occurs when the button is pushed down, when it is released the statement is no longer true.

If I want my program to be repeatable, so it will start when ever the button is pressed, but to run longer than the duration the button is pressed, how would I do that?

Post your code.

Post Your schematics.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
// put your setup code here, to run once:
pinMode(2, INPUT_PULLUP);
Serial.begin(9600);
lcd.init();
lcd.init();
lcd.backlight();

}
int buttonStatus = 0;

void loop() {

int pinValue = digitalRead(2);
delay(10);
lcd.setCursor(3,0);
lcd.print("Hello, world!");

if (buttonStatus != pinValue) {
buttonStatus = pinValue;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Yay Button");
Serial.println(buttonStatus);
}
}

What's not repeating there?

(Plese remember to use code tags when osting code)

Sorry the formatting is still new to me and I'm still figuring it out.

The code is repeatable, but the second message, 'yay button', leaves the display as soon as I release the button, and I want it to stay until a later requirement is met.

You are currently overwriting the screen every loop.

Move this code to setup so it only runs once.

  lcd.setCursor(3, 0);
  lcd.print("Hello, world!");

What if I want to make the 2nd message stay only until I pressed the button a second time. Would this be possible with leaving the first message in the setup?

  if (button1State == HIGH) {
    dispensingFunction();
    lcd.clear();
    lcd.print("Pick second container");
    lcd.setCursor(0,1);
    lcd.print("Press button 1 to begin dispensing");
      if (button1State == HIGH) {
        dispensing2Function();
        lcd.clear();
        lcd.print("Coffee Dispensed");
        lcd.setCursor(0,1);
        lcd.print("Press button 2 to grind");
        if (button2State == HIGH) {
          preloaderFunction(); 
          relayFunction();
          lcd.clear();
          lcd.print("Coffee ground");
          lcd.setCursor(0,1);
          lcd.print("Enjoy!");
          
        }
      }
  }

This is part of a larger program. I want to be able to use the buttons to work in steps, then at the end it will start back from the first step if that makes sense.

How many buttons ? How many steps?

Do you have complete set of requirements? It is quite hard to provide advice when you provide the requirements one at a time.

  if (button1State == HIGH) {
    dispensingFunction();
    lcd.clear();
    lcd.print("Pick second container");
    lcd.setCursor(0,1);
    lcd.print("Press button 1 to begin dispensing");
      if (button1State == HIGH) {
        dispensing2Function();
        lcd.clear();
        lcd.print("Coffee Dispensed");
        lcd.setCursor(0,1);
        lcd.print("Press button 2 to grind");
        if (button2State == HIGH) {
          preloaderFunction(); 
          relayFunction();
          lcd.clear();
          lcd.print("Coffee ground");
          lcd.setCursor(0,1);
          lcd.print("Enjoy!");
          
        }
      }
  }

What about this code? It uses functions that I wrote and tested independently, I want to control when each program occurs using 2 buttons. Because the 'if' statements are only true while the button is held down, it makes compounding statements like this not work the way I wanted them too and am looking for a solution

The „trick" is to use a boolean variable that changes it's value everytime when a button is released not only while a button is pressed.

Just google for „debouncing button Arduino”
and you should find several examples. Do not use the state of the button directly but use it to change the value of the boolean like

boolean toggle= true;

if (buttonReleased()) toggle = !toggle;

if (toggle) DoSomething();

I think I get what you're saying, but dont completely understand the example you gave. Do you mind giving me a similar example using variable names from the code I posted?

And what if I wanted to sequential statements, like work them in steps. So after the button was pressed once an LCD would display something. If it was pressed again after that, the LCD would display something different

To ask my question better:

I'm writing a program which will hopefully allow a user to interface with a device through two buttons and an LCD screen.

Essentially there are a number of steps that require user a user input before they can be completed, and I want the steps to happen sequentially. The way I initially tried to do this was to write compound if statements, I'll attach the portion of the code below, that become true when the button is pressed.

The issue I've run into is that the 'if' statements are only true while the button is pressed, as soon as they are released it stops working. Is there a way to make the 'if' statement permanently true as soon as the button is pressed. Or is there a better way to do this instead of using 'if' statements?

Also, what is the best way to make the code pause and wait for a user input? The code will loop through without waiting for an input.

Here's the portion of the code I need help with

  if (button1State == HIGH) {
    dispensingFunction();
    lcd.clear();
    lcd.print("Pick second container");
    lcd.setCursor(0,1);
    lcd.print("Press button 1 to begin dispensing");
      if (button1State == HIGH) {
        dispensing2Function();
        lcd.clear();
        lcd.print("Coffee Dispensed");
        lcd.setCursor(0,1);
        lcd.print("Press button 2 to grind");
        if (button2State == HIGH) {
          preloaderFunction(); 
          relayFunction();
          lcd.clear();
          lcd.print("Coffee ground");
          lcd.setCursor(0,1);
          lcd.print("Enjoy!");
          
        }
      }
  }

Because the action required after each button press, depends on exactly where you are in the sequence of actions, you need to keep track of the program "state".

The example below is a simple state machine, and uses a variable to keep track of where it is. You could use something similar in your code.

int state = 0;
boolean buttonPressed = false;
boolean previousValue = false;
unsigned long currentTime = 0;
unsigned long previousTime = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);

  Serial.println("Simple state machine");
}


void loop()
{
  // Check the state of the button
  if (digitalRead(2) == LOW)
    buttonPressed = true;
  else
    buttonPressed = false;


  // Check when a button first gets pressed.
  currentTime = millis();
  if (buttonPressed && !previousValue and currentTime - previousTime > 200)
  {
    previousTime = currentTime;
    
    switch (state)
    {
      case 0:
        {
          Serial.println("Do stuff required on first button press");
          break;
        }
      case 1:
        {
          Serial.println("Do stuff required on secord button press");
          break;
        }
      case 2:
        {
          Serial.println("Do stuff required on third button press");
          break;
        }
    }

    // Move to the next state.
    state++;
    if (state > 2)
      state = 0;
 
  }


  // Keep track of the button value, so we don't keep actioning while button is being pressed.
  previousValue = buttonPressed;

}

1 Like

Thank you this looks very helpful, however I'm not super familiar with what is going on in this section. Do you mind explaining the function of the 'switch' and 'case' commands in this scenario?

A Switch/Case statement is just a tidier way to do if/else.

if (state == 0)
{
  // First press
}
else if (state == 1)
{
  // Second press
}
else if (state == 2)
{
  // Third press
}
1 Like

And if I wanted to increase the time increment needed between each press, I would just increase the 200 value here?

This bit of code is used to "debounce" the push button.

When a button is pressed it doesn't go perfectly from high to low (or low to high) instantly... the button is said to "bounce" first... where is will move between states before it settles. This small delay (1/5 second) avoids that issue.

More detail here... https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce

Try the code without this and see what happens.