I need help with arduino pushbuttons- up/down/select

Hello, I want to create "code" for my other project. I need some help because I dont know how to do something like : (I need help with this part) if button 2 is pressed for x times, select option x --> (I know how to do this part) if button 1 is pressed y=y+1 or if button 3 is pressed y=y-1 --> (and I need help with this part) if nothing is pressed for over 3 seconds, go back (continue void loop).

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


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

I want something like that.

and if its possible - hold button for 2 seconds than -->

if button is pressed 1x select option 1

or

if button is pressed 2x select option 2

if nothing is pressed over 3 seconds go back to Void loop (code for my egg incubator)



int button_1 = 8;
int button_2 = 9;
int button_3 = 10;

float y=10;
float z=10;

int buttonState1 = 0;         // current state of the button
int lastButtonState1 = 0;     // previous state of the button


int buttonState2 = 0;         // current state of the button
int lastButtonState2 = 0;     // previous state of the button


int buttonState3 = 0;         // current state of the button
int lastButtonState3 = 0;     // previous state of the button


void setup()
{
  
  	pinMode(button_1, INPUT_PULLUP);
    pinMode(button_2, INPUT_PULLUP);
    pinMode(button_3, INPUT_PULLUP);
}

void loop(){
  lcd.setCursor(0,0);
  
  
  // option 1
 buttonState = digitalRead(button_1);
 	 if (buttonState1 != lastButtonState1) {
    	if (buttonState1 == HIGH) { 
     		 y=y+0.1;
  }  
    delay(50);
  }
  
  lastButtonState1 = buttonState1;

  
  
  
   buttonState3 = digitalRead(button_3);

  if (buttonState3 != lastButtonState3) {
    
    if (buttonState3 == HIGH) {
     
      x=x-0.1;
     
    } 
 
    delay(50);
  }
 
  lastButtonState3 = buttonState3;
  
  
  // option 2
  
 buttonState = digitalRead(button_1);
 	 if (buttonState1 != lastButtonState1) {
    	if (buttonState1 == HIGH) { 
     		 z=z+0.1;
  }  
    delay(50);
  }
  
  lastButtonState1 = buttonState1;

  
  
  
   buttonState3 = digitalRead(button_3);
 	 if (buttonState3 != lastButtonState3) { 
   		 if (buttonState3 == HIGH) {
     		 z=z-0.1;     
    } 
 
    delay(50);
  }
 
  lastButtonState3 = buttonState3;
  
  
  }

Why do you have this line of code ?

Please explain exactly what is to happen using words and full sentences.

Ok. I want to open 'select' menu with holding button 1 for 2 seconds. When i open menu i want to use button 1 for selecting first or second option by pressing one press or two presses. When i selwct rifht option I want to use button 2 and 3 for adjusting number (button 1 - +1), button 2 - -1.

  • Is this what is needed ?

Pressing switch 1 for longer than 2 seconds displays a menu.

Tapping switch 1 once, selects menu Option1

Tapping switch 1 twice, selects menu Option 2


Switch 2 increments a variable

Switch 3 decrements the variable.


  • Why do you have this line of code ?

  • What are the Options ?

Yes, this it what I need, this line of code is there because I forget to delete it, options are increasing or decreasing humidity and temperature.

Hi iziga55,
no one to help you ?

Nope. :frowning:

do you want line by line help, or a ready made code ?

I think line by line help would be better.
I can upload code of my project which I want to do if it helps.

It's the same code as the one you gave above? it's good to start with a code that deals only with buttons, at first.
We can copy it here to test it (just copy and paste your code in the left window, if you don't know it)

The code I gave above its just a part which I want to include in my other code for egg incubator ( I want to change temperature and humidity but just one at a time and with just temp. / hum. displayed on lcd).
And this is what I dont know how to do.

Aaaaaah I need an egg incubator ! I have hens

when you declare variables, no need to set them to zero, they are automatically set to zero

if the pins of the arduino are configured in INPUT_PULLUP, then pressing a key will give an information to LOW

The first part (option 1) is corrected, but I did not take care of y=y+ for the moment

Oh, nice, I have hens too. My incubator is working fine (haven't tested it with eggs yet, but empty was working).

Because diffrent eggs require diffrent temperatures I want to set twmperature using buttons. And there is that problem.

I don't know how to do this part: when I hold button for 2 seconds menu opens, in menu I want to have humidity and temperature option, when I select one, I want to change this x number with buttons for +/-0.1 per press, if nothing is pressed for 3 seconds, I want void loop to continue.

OK, I see.
I don't have a rooster, my neighbors are too close...

did you see the code in the wokwi link given above ? I started to correct your code. You can correct it too, and save before leaving (the top left button). I don't know yet how we share the changes we make on each side, we'll see...

delay(50) for each key is not a good thing, the arduino stops for 50 ms at each key, it works but it can be avoided: we create a single delay for all keys, and we use the internal timer of the arduino. I give an example in the wokwi

This should be what you asked for.

  • This shows how to write a non blocking sketch.
  • It uses TIMERs based on the millis() function and it uses a State Machine to present the menus.

It would be simple to add more code as needed.



//https://forum.arduino.cc/t/i-need-help-with-arduino-pushbuttons-up-down-select/1040798

//********************************************^************************************************
// Version    YY/MM/DD    Description
// 1.00       22/10/11    Running sketch
// 1.01       22/10/11    Added some comments
//
//

//********************************************^************************************************
#define resetTime                  millis()

#define HUMIDITY                   true
#define TEMPERATURE                false

#define CLOSED                     LOW
#define OPENED                     HIGH

#define PUSHED                     LOW
#define notPUSHED                  HIGH

#define ENABLED                    true
#define DISABLED                   false

#define RUNNING                    true
#define notRUNNING                 false

#define LEDon                      HIGH
#define LEDoff                     LOW


//********************************************^************************************************
//                                                 Resistor     LED
const byte heartbeatLED          = 13;         //Pin13---[220R]---[A->|-K]---GND
const byte menuSwitch            = 8;          //+5V---[50k Internal Pullup]---[Input Pin]---[Switch]---GND
const byte incrementSwitch       = 9;          //+5V---[50k Internal Pullup]---[Input Pin]---[Switch]---GND
const byte decrementSwitch       = 10;         //+5V---[50k Internal Pullup]---[Input Pin]---[Switch]---GND

bool variableFlag                = HUMIDITY;

byte lastMenuSwitchState         = OPENED;
byte lastIncrementSwitchState    = OPENED;
byte lastDecrementSwitchState    = OPENED;

int counter;

float humidity                   = 15.0;         //powerup default
float maxHumidity                = 70.0;
float minHumidity                = 10.0;

float temperature                = 20.0;         //powerup default
float maxTemperature             = 40.0;
float minTemperature             = 15.0;


//timing stuff
unsigned long currentTime;
unsigned long heartbeatTime;
unsigned long switchTime;
unsigned long commonTime;
unsigned long finalizeTime;
unsigned long menuSwitchTime;

unsigned long toggleInterval     = 500ul;       //1/2 second
unsigned long longPressInterval  = 2000ul;      //2 seconds
unsigned long shortPressInterval = 500ul;       //1/2 second
unsigned long timeOutInterval    = 5000ul;      //5 seconds
unsigned long finalizeInterval   = 5000ul;      //5 seconds


//in your version pick names that mean something to you
enum  StateMachine {Startup, Waiting1, State1, Waiting2, State2, State3, State4};

StateMachine mState = Startup;


//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);

  pinMode(menuSwitch, INPUT_PULLUP);
  pinMode(incrementSwitch, INPUT_PULLUP);
  pinMode(decrementSwitch, INPUT_PULLUP);

} //END of   setup()


//********************************************^************************************************
void loop()
{
  //capture the current time
  currentTime = millis();

  //*************************************                          h e a r t b e a t   T I M E R
  //to see if the sketch is blocking,
  //toggle the heartbeat LED every 500ms
  if (currentTime - heartbeatTime >= toggleInterval)
  {
    //restart the TIMER
    heartbeatTime = resetTime;

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                          s w i t c h   T I M E R
  //is it time to check the switches ? every 50ms
  if (currentTime - switchTime >= 50)
  {
    //restart the TIMER
    switchTime = resetTime;

    //go and check the switches
    checkSwitches();
  }

  //*************************************
  //service the State Machine
  checkStateMachine();


  //*************************************
  // Other None Blocking Code Goes Here
  //*************************************

} //END of   loop()


//********************************************^************************************************
void checkSwitches()
{
  //*********************************************                    m e n u S w i t c h
  //menuSwitch code
  byte currentState = digitalRead(menuSwitch);

  //**********************
  //was there a change in state ?
  if (lastMenuSwitchState != currentState)
  {
    //update to the new state
    lastMenuSwitchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      //start Timing how long the switch is held
      menuSwitchTime = resetTime;
    }

    //**********************
    //switch was released
    else
    {
      //was this a long press ?
      if (currentTime - menuSwitchTime >= longPressInterval)
      {
        //reset this TIMER
        commonTime = resetTime;

        //next State in the machine
        mState = State1;
      }

      else if (currentTime - menuSwitchTime <= shortPressInterval)
      {
        counter = counter + 1;
      }

    }

  } //END of   menuSwitch code

  //*********************************************                    i n c r e m e n t S w i t c h
  //incrementSwitch code
  currentState = digitalRead(incrementSwitch);

  //**********************
  //was there a change in state ?
  if (lastIncrementSwitchState != currentState)
  {
    //update to the new state
    lastIncrementSwitchState = currentState;

    //**********************
    //if we are adjusting a value, is the switch closed ?
    if (mState == State4 && currentState == CLOSED)
    {
      //restart this TIMER
      finalizeTime = resetTime;

      if (variableFlag == HUMIDITY)
      {
        humidity = humidity + 1;

        //do not go over maximum humidity
        if (humidity > maxHumidity)
        {
          humidity = maxHumidity;
        }

        Serial.println(humidity);
      }

      else if (variableFlag == TEMPERATURE)
      {
        temperature = temperature + 1;

        //do not go over maximum temperature
        if (temperature > maxTemperature)
        {
          temperature = maxTemperature;
        }

        Serial.println(temperature);
      }
    }

  } //END of   incrementSwitch code

  //*********************************************                    d e c r e m e n t S w i t c h
  //decrementSwitch code
  currentState = digitalRead(decrementSwitch);

  //**********************
  //was there a change in state ?
  if (lastDecrementSwitchState != currentState)
  {
    //update to the new state
    lastDecrementSwitchState = currentState;

    //**********************
    //if we are adjusting a value, is the switch closed ?
    if (mState == State4 && currentState == CLOSED)
    {
      //restart this TIMER
      finalizeTime = resetTime;

      if (variableFlag == HUMIDITY)
      {
        humidity = humidity - 1;

        //do not go under minimum humidity
        if (humidity < minHumidity)
        {
          humidity = minHumidity;
        }

        Serial.println(humidity);
      }

      else if (variableFlag == TEMPERATURE)
      {
        temperature = temperature - 1;

        //do not go under minimum temperature
        if (temperature < minTemperature)
        {
          temperature = minTemperature;
        }

        Serial.println(temperature);
      }
    }

  } //END of   decrementSwitch code


} //END of   checkSwitches()


//********************************************^************************************************
void checkStateMachine()
{
  switch (mState)
  {
    //***********************************
    //power up state
    case Startup:
      {
        Serial.println("");
        Serial.print("Humidity = ");
        Serial.print(humidity);
        Serial.print("\t Temperature = ");
        Serial.println(temperature);

        Serial.println(F("To adjust variables, press the 'Menu Switch' for longer than 2 seconds"));

        //next State
        mState = Waiting1;
      }
      break;

    //***********************************
    //a place to wait
    case Waiting1:
      {
        //do nothing
      }
      break;

    //***********************************
    //user wants to make some changes
    case State1:
      {
        Serial.println("");
        Serial.println(F("To set HUMIDITY, Tap the 'Menu Switch', ONCE"));
        Serial.println(F("To set Temperature, Tap the 'Menu Switch', TWICE"));

        counter = 0;

        //next State
        mState = Waiting2;

        //restart this Timer
        commonTime = resetTime;
      }
      break;

    //***********************************
    //waiting for 1 or 2 taps on the 'Menu Switch'
    case Waiting2:
      {
        //did the user take too long to respond ?
        if (currentTime - commonTime >= timeOutInterval)
        {
          //did the user tap the menu switch ?
          if (counter == 1)
          {
            //next State
            mState = State2;
            break;
          }

          Serial.println("");
          Serial.println(F("You took too long to respond"));

          //back to Startup
          mState = Startup;

          break;
        }

        if (counter == 2)
        {
          //next State
          mState = State3;
        }
      }
      break;

    //***********************************
    //we are adjusting the value of 'humidity'
    case State2:
      {
        //restart this TIMER
        finalizeTime = resetTime;

        Serial.println("");
        Serial.println("");
        Serial.print("Humidity = ");
        Serial.print(humidity);
        Serial.print("\t Temperature = ");
        Serial.println(temperature);

        Serial.println(F("Setting Humidity. Tap the INC or DEC switches"));
        Serial.println(F("When finished, wait 5 seconds to finalize changes"));

        variableFlag = HUMIDITY;

        //next State
        mState = State4;
      }
      break;

    //***********************************
    //we are adjusting the value of 'temperature'
    case State3:
      {
        //restart this TIMER
        finalizeTime = resetTime;

        Serial.println("");
        Serial.println("");
        Serial.print("Humidity = ");
        Serial.print(humidity);
        Serial.print("\t Temperature = ");
        Serial.println(temperature);

        Serial.println(F("Setting Temperature. Tap the INC or DEC switches"));
        Serial.println(F("When finished, wait 5 seconds to finalize changes"));

        variableFlag = TEMPERATURE;

        //next State
        mState = State4;
      }
      break;

    //***********************************
    //waiting for 5 seconds to expire after no activity on the INC or DEC switches
    case State4:
      {
        if (currentTime - finalizeTime > finalizeInterval)
        {
          Serial.println("");
          Serial.println(F("You are now finished with the changes "));

          //back to Startup
          mState = Startup;
        }
      }
      break;

  } //END of switch/case

} //END of   checkStateMachine()


//********************************************^************************************************


Oh, thanks. I like it. Would you help me just with one more thing please.

I have this code:

// LCD
#include <LiquidCrystal.h>
  LiquidCrystal lcd(14,15,16,17,18,19);

// CLOCK
signed short min = 59, sec = 40;
char timeline[16];

// MOTOR
  #define A 8
  #define B 9
  #define C 10
  #define D 11
  #define NUMBER_OF_STEPS_PER_REV 896

  int i = 0;
// SERVO
#include <Servo.h>
Servo servo1;
int servoPin=9;
int d=0;

// RELAY
  int relay = 2;

// DHT 22
  #include <DHT.h>;
  DHT dht(12, DHT22); // DHT 22  (AM2302)
  int chk;
  float hum;  //Stores humidity value
  float temp; //Stores temperature value
 

// SIMBOLS
byte Temperature[8] =            
{
    B00100,
    B01010,
    B01010,
    B01110,
    B01110,
    B11111,
    B11111,
    B01110
};

byte Droplet[8] =            //droplet
{
    B00100,
    B00100,
    B01010,
    B01010,
    B10001,
    B10001,
    B10001,
    B01110,
};

byte Light_bulb[8] =          //light bulb
{
    B01110,
    B10001,
    B10001,
    B10001,
    B01110,
    B01110,
    B01110,
    B00000
};

byte Degree[8] =            //degree
{
    B01100,
    B10010,
    B10010,
    B01100,
    B00000,
    B00000,
    B00000,
    B00000
};
 
byte Motor[8] =             //motor
{
    B00010,
    B11111,
    B00010,
    B00000,
    B10001,
    B11011,
    B10101,
    B10001
};


void setup() {
  Serial.begin(9600);
  Serial.println("Start");
 
  // LCD
  lcd.begin(16, 2);
   
    lcd.setCursor(0,0);
      lcd.write(1);
    lcd.setCursor(0,1);
      lcd.write(2);

  // CREATE SIMBOL
  lcd.createChar(1,Temperature);      
  lcd.createChar(2,Droplet);      
  lcd.createChar(3,Light_bulb);
  lcd.createChar(4,Degree);
  lcd.createChar(5,Motor);

  // MOTOR
  pinMode(A,OUTPUT);
  pinMode(B,OUTPUT);
  pinMode(C,OUTPUT);
  pinMode(D,OUTPUT);

// SERVO
servo1.attach (servoPin);

  // RELAY
  pinMode(relay,OUTPUT);

  //DHT 22
  dht.begin();

 delay(500);
  }
 
    void write(int a,int b,int c,int d){
      digitalWrite(A,a);
      digitalWrite(B,b);
      digitalWrite(C,c);
      digitalWrite(D,d);
      }

    void onestep(){
     write(1,0,0,0);
      delay(5);
     write(1,1,0,0);
      delay(5);
     write(0,1,0,0);
      delay(5);
     write(0,1,1,0);
      delay(5);
     write(0,0,1,0);
      delay(5);
     write(0,0,1,1);
       delay(5);
     write(0,0,0,1);
       delay(5);
     write(1,0,0,1);
       delay(5);
    }

 void stopstep(){
    write(0,0,0,0);
 }

void loop() {
 
  // CLOCK
  lcd.setCursor(11, 1);
    sprintf(timeline,"%0.2d:%0.2d ", min, sec);
      lcd.print(timeline);
 
   delay(1000);
     sec++;
     
    if (sec == 60){
      sec = 0;
      min ++;
      }  

   //DHT 22
   hum = dht.readHumidity();
   temp= dht.readTemperature();

   if (isnan(hum) || isnan(temp)) {
    lcd.setCursor(11,0);    
    lcd.print("F");
   }
   
   else{
    lcd.setCursor(11,0);    
    lcd.print(" ");
   }

   //LCD-DHT
   lcd.setCursor(2,0);  
    lcd.print(temp);
     lcd.write(4);
     lcd.print("C");
   
   lcd.setCursor(2,1);  
    lcd.print(hum);
     lcd.print("%");

   //RELAY-DHT
   if(temp<37.5){
   digitalWrite(relay,HIGH);
     lcd.setCursor(15,0);
      lcd.write(3);}

   else if(temp>38.0){
    digitalWrite(relay,LOW);
      lcd.setCursor(15,0);
       lcd.print(" ");
}

//DHT-SERVO
if(hum<60){
     for(d=0; d<=180, d=d+1){
     servo1.write(d);
     delay(50);
     }
}

     else if (hum>70){
            for(d=180; d>=180, d=d-1){
            servo1.write(d);
            delay(50);
}
}

// MOTOR, CLOCK      
  if(min>59){
   
    min=0;
   
    lcd.setCursor(11,1);
    lcd.print("00:00");
   
    lcd.setCursor(13,0);
    lcd.write(5);
   
  digitalWrite(relay,LOW);
    lcd.setCursor(15,0);
      lcd.print(" ");
 
  delay(100);
 
while(i<NUMBER_OF_STEPS_PER_REV){
  onestep();
    i++;
}

 if(i==NUMBER_OF_STEPS_PER_REV){
   stopstep();
   i=0;    
}
 
  lcd.setCursor(13,0);
       lcd.print(" ");
       
}
}

And I want to combine it with your code.
"temp" is reading from sensor. I want to change this 37,5 and 38 numbers +/- 0.1 ( 37.5 is minimum value and 38 is maximum value for relay to open or close so I would need both numbers to be settable)

if(temp<37.5){
   digitalWrite(relay,HIGH);
     lcd.setCursor(15,0);
      lcd.write(3);}

   else if(temp>38.0){
    digitalWrite(relay,LOW);
      lcd.setCursor(15,0);
       lcd.print(" ");

And same for humidity:

if(hum<60){
     for(d=0; d<=180, d=d+1){
     servo1.write(d);
     delay(50);
     }
}

     else if (hum>70){
            for(d=180; d>=180, d=d-1){
            servo1.write(d);
            delay(50);
}
}

Only problem is that my code is counting hours for "timer" and is has delay 1 second:

// CLOCK
  lcd.setCursor(11, 1);
    sprintf(timeline,"%0.2d:%0.2d ", min, sec);
      lcd.print(timeline);
 
   delay(1000);
     sec++;
     
    if (sec == 60){
      sec = 0;
      min ++;
      }  

And I would need this "my" code run all the time except when menu is opened.
And thank you, you helped me a lot :slight_smile: .

Combining the two sketches is something we will leave up to you to do.

The example offered in post #18 shows techniques you can use to accomplish what you originally ask for.


What is important in all of this is how to make non delay( ) TIMERs using the millis( ) function, and how to use a State Machine to advance thru project states.

The Heartbeat TIMER is useful to show if code is blocking, remove it if need be.