need help to modify this push button code

hi. hello everyone. i want to ask your help how i'm gonna modify this code so that the same push button can be use twice. the current code only allow me to use the same push button once. i want to modify it to so that it fulfill the condition as in the picture attached here.

#include <LiquidCrystal.h>

/*
  The circuit:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 9
 * LCD D4 pin to digital pin 4
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 6
 * LCD D7 pin to digital pin 7
 * LCD R/W pin to ground
*/

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int analogPin = A0;
int adc_key_old;
int adc_key_in;
int NUM_KEYS = 5;
int key=-1;
int adc_key_val[5] ={30, 150, 360, 535, 760};        


/*******************************************************************************
* PRIVATE FUNCTION: setup()
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Define of I/O pin as Input or Output 
*
*******************************************************************************/
// The setup() method runs once, when the sketch starts
void setup ()
{
  // initialize serial:
  Serial.begin(57600);

  
  lcd.begin(16, 2);                         // set the lcd dimension
  lcd.print("  CYTRON TECH.");              // display the text
  lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
  lcd.print(" Eg. LCD Shield");    
  delay(1500);                              // delay for 3000ms
  lcd.clear();
  adc_key_old = analogRead(analogPin);      // store the unpress key value 
}


/*******************************************************************************
* PRIVATE FUNCTION: loop()
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Non-Stop looping 
*
*******************************************************************************/
void loop()
{
  adc_key_in = analogRead(analogPin);     // read ADC value
  adc_key_in = get_key(adc_key_in);
  
  if (adc_key_in==0)        // Right button menu
  {
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Menu 1");    
  }
  
  else if (adc_key_in==1)   // Up button menu
  {
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Menu 2");    
  }
  
  else if (adc_key_in==2)  // Down button menu
  {
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Menu 3");    
  }

  else if (adc_key_in==3)  // Left button menu
  {
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Menu 4");    
  }

  else if (adc_key_in==4)  // Select button menu
  {
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Menu 5");    
  }
}
  

/*******************************************************************************
* PRIVATE FUNCTION: get_key
*
* PARAMETERS:
* ~ integer
*
* RETURN:
* ~ unsigned int input
*
* DESCRIPTIONS:
* convert the ADC value to number between 0 to 4
*
*******************************************************************************/
int get_key(unsigned int input)
{
  int k;

    for (k = 0; k < NUM_KEYS; k++)
    {
      if (input < adc_key_val[k])
      {

      return k;
      }
    }
    
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed

    return k;
}

Your sample uses 5 push button using on analog input and 5 different resistor values. What help do you exactly need with this?
Excuse me if I'm wrong, but this sounds a bit like "let the forum do my school work for me". We help you do it but we don't do it for you.

i know. it maybe sound like that. but, this is not a homework actually. i'm juz graduated. i'm juz want to see the pattern. how the programming. perhaps, later maybe with the example, i can modify it to change the program from dual menu to triple menu. that's the way i learn the program. i only learned one semester subject programming. only the basic. and it is not enough. i'm not hoping u guys to do it. perhaps juz give a few hints how to modify the coding. that's all.

At the moment the code simply reads the buttons and prints a message to indicate which one has been pressed. The program has no way of knowing what level of the menu is currently on the screen and what action to take when a button is pressed. What you need to do is implement a state machine with a variable, lets call it state, whose value is changed when a button is pressed so that next time a button is pressed the appropriate action for the current state is taken.

So, in your example you could start with state set to 1 and display the top level menu. If button 1 is pressed you update state to 2 and display the Add Fingerprint menu and wait for a button press. When a button is pressed you check the current state and respond appropriately for that button in that state. For instance, suppose button 5 is designated to exit from the Add Fingerprint menu and it is pressed. You would update state to 1 and display the top level menu ready for another menu item to be selected.

understood. now i have a clear image on that. buttonState. so, the buttonState will be a variable how many time it been push. Thank you very much. i'll give a try on that. thank you for the hint.

No !
The number of times the button has been pressed is not relevant. buttonState simply tells the program whether a button is currently pressed or not. The state that I am talking about indicates which level of the menu you are in so that button presses can be interpreted and acted on appropriately . Button 1 will mean different things depending on the current state. To expand on my example, if you are at the top level of the menu and press button 2 this might take you to a menu allowing you to delete fingerprints. That might be state 3. You decide on the state numbers.

May be something like this may help to see things clearer :

//definition of Variables
 
int State = 0


if (ButtonState==1)
    {State = 1}

Then in your code you define at State = 1, what happen depending on your requirements.

taz . .

Your code-style has too much comments imho (not to bash you, just want to learn you how to type less and more tot the point :slight_smile:

Code can explain itself if you choose good names for variables, functions and constants.
Comment should tell primarly the WHY, not the HOW (that should the code do) and sometimes explain the WHAT

Some examples

delay(1500); // delay for 3000ms

This kind above is obfuscating at best, code will always win when there is a difference between code and comment.
A better comment could be // milliseconds as that explains the unit of delay (WHAT)

if (adc_key_in==0) // Right button menu

is much better, but can be improved by using consts or #defines, creating self explaining code

something like this

// at the top of sketch you define 
#define RIGHT_BUTTON_MENU 0
#define UP_BUTTON_MENU 1
#define DOWN_BUTTON_MENU 2
#define LEFT_BUTTON_MENU 3
#define SELECT_BUTTON_MENU 4
etc

if (adc_key_in == RIGHT_BUTTON_MENU) 
....

if (adc_key_in == LEFT_BUTTON_MENU) 
....

From the big block above loop() only this line explains something, the rest can be seen in the code, no need to comment

* Non-Stop looping

Give it a try!

thank you. thank you very much. wow. i'm very grateful to all of u. much much clear. thank you for the explanation & example provided.

by the way, is this code correct in your opinion. i manage to scroll down to every operation. add fingerprint, delete fingerprint and so on. by when i want to go to second menu, it won't go to the second menu. need advice on that. perhaps maybe something wrong with my coding.

#include <LiquidCrystal.h>
#define RIGHT_BUTTON_MENU 0
#define UP_BUTTON_MENU 1
#define DOWN_BUTTON_MENU 2
#define LEFT_BUTTON_MENU 3
#define SELECT_BUTTON_MENU 4

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int analogPin = A0;
int adc_key_old;
int NUM_KEYS = 5;
int key=-1;
int adc_key_val[5] ={30, 150, 360, 535, 760};

// Variables will change:
int adc_key_in=0;
int adc_key_in_last = 0;     // previous state of the button
int adc_key_in_PushCounter = 0;   // counter for the number of button presses

int State1 = 0;
int State2 = 0;
int State3 = 0;
int State4 = 0;
int State5 = 0;
int State6 = 0;
int State7 = 0;

void setup ()
{
  // initialize serial:
  Serial.begin(57600);
  
  lcd.begin(16, 2);                         // set the lcd dimension
  lcd.setCursor(0,0);  
  lcd.print("  CYTRON TECH.");              // display the text
  lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
  lcd.print(" Eg. LCD Shield");
  delay(1500);  // delay for 1500ms
  
  lcd.clear();
  adc_key_old = analogRead(analogPin);      // store the unpress key value 
}

void loop()
{

  adc_key_in = analogRead(analogPin);     // read ADC value
  adc_key_in = get_key(adc_key_in);
  
  // compare the buttonState to its previous state
  if (adc_key_in != adc_key_in_last) {
    
    // if the state has changed, increment the counter
    if (adc_key_in == DOWN_BUTTON_MENU) {

      // if the current state is HIGH then the button
      // wend from off to on:
      adc_key_in_PushCounter++;
      delay (300);
      
      if (adc_key_in_PushCounter==1) {
        //{State1 = 1}
        lcd.clear();
        lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
        lcd.print("Add Fingerprint");
        
        if (adc_key_in == SELECT_BUTTON_MENU) {
          addFinger0;
        }
      }
      
      else if (adc_key_in_PushCounter==2){
        lcd.clear();
        lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
        lcd.print("Delete");
        lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
        lcd.print("Fingerprint");
      }
      
      else if (adc_key_in_PushCounter==3){
        lcd.clear();
        lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
        lcd.print("Search");
        lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
        lcd.print("Fingerprint");
      }

      else if (adc_key_in_PushCounter==4){
        lcd.clear();
        lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
        lcd.print("Empty Database");
      }

      else if (adc_key_in_PushCounter==5){
        lcd.clear();
        lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
        lcd.print("Search Database");
      }
    }
        
    else {
      // if the current state is LOW then the button
      // wend from on to off:
      //lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
      //lcd.print("off");
    }
  }
  // save the current state as the last state, 
  //for next time through the loop
  adc_key_in_last = adc_key_in;
}

int get_key(unsigned int input)
{
  int k;

    for (k = 0; k < NUM_KEYS; k++)
    {
      if (input < adc_key_val[k])
      {

      return k;
      }
    }
    
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed

    return k;
}

void addFinger0(){
  // set the cursor to column 0, line 1
  lcd.setCursor(0, 1);
  // Print a message to the LCD.
  lcd.print("Add Fingerprint1");
  delay(1500);
}

You are still not setting a variable to a value that would indicate which menu is on display so the program does not know what to do when a button is pressed. I see that you have experimented with variable called stateX where X is a number but what you need to do is to have a single variable, maybe call it currentState, whose value indicates which menu is on display.

As a start, list all of the screens to be displayed and allocate each of them a number. This number will be the value to be given to currentState. Now list each of the buttons that might be pressed when each screen is on display and the actions to be taken should the button be pressed.

Screen 1 on display. currentState = 1
button 1 pressed. Set currentState to 2 and show screen 2
button 2 pressed. Set currentState to 3 and show screen 3
button 3 pressed. Set currentState to 4 and show screen 4

Screen 2 on display. currentState = 2
Call addFingerprint function
Button 2 pressed. Set currentState to 1 and show screen 1

Screen 3 on display. currentState = 3
Call deleteFingerprint function
Button 2 pressed. Set currentState to 1 and show screen 1

Can you see how you can then use statements like

if (currentState == 1 && buttonPressed == 2)
{
//show screen 3
//do actions for screen 3
}

and how that differs from

if (currentState == 2 && buttonPressed == 2)
{
//set currentState to 1
//show screen 1
}

even though the same button was pressed each time.

let me give a try first. Thank you by the way, correcting me. by the way, how to increase the currentstate so that it won't interpret it as button pressed? i almost got it. with the implementation of &&. thank you for that.

i believe more visible like this. i understand what u meant. almost got it. but how to link the state while i pressed the down button.

if (currentState == 1 && buttonPressed == DOWN_BUTTON_MENU)
{
  lcd.clear();
  lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
  lcd.print("Add Fingerprint");
}

else if (currentState == 2 && buttonPressed == DOWN_BUTTON_MENU)
{
  lcd.clear();
  lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
  lcd.print("Delete");
  lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
  lcd.print("Fingerprint");
}

else if (currentState == 3 && buttonPressed == DOWN_BUTTON_MENU)
{
  lcd.clear();
  lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
  lcd.print("Search");
  lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
  lcd.print("Fingerprint");
}

else if (currentState == 4 && buttonPressed == DOWN_BUTTON_MENU)
{
  lcd.clear();
  lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
  lcd.print("Empty Database");
}

else if (currentState == 5 && buttonPressed == DOWN_BUTTON_MENU)
{
  lcd.clear();
  lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
  lcd.print("Search Database");
}

Your code is not updating the value of currentState when you change screens so it will always be the same value.

Look at this again

Screen 1 on display. currentState = 1
button 1 pressed. Set currentState to 2 and show screen 2
button 2 pressed. Set currentState to 3 and show screen 3
button 3 pressed. Set currentState to 4 and show screen 4

NOTE - I deliberately referred to screens rather than menus because when updating a fingerprint, for example, there will not be a menu on the screen, rather a prompt asking for the user to put their finger on the device or press a button to exit. Equally, when a fingerprint has been read you probably need a screen asking for confirmation, but that is up to you.

UKHeliBob:
Look at this again

Screen 1 on display. currentState = 1
button 1 pressed. Set currentState to 2 and show screen 2
button 2 pressed. Set currentState to 3 and show screen 3
button 3 pressed. Set currentState to 4 and show screen 4

understood! just like stepping a stairs.

am i correct like this? but why it not goes to state 1. remain at state zero after i push down button.

/////////////////////////////////////////////////////////////  
  if (currentState == 0 && buttonPressed == DOWN_BUTTON_MENU)
  {
    (currentState == 1);
    lcd.clear();
    lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
    lcd.print("Add Fingerprint");
  }
  
  else if (currentState == 1 && buttonPressed == DOWN_BUTTON_MENU)
  {
    (currentState == 2);
    lcd.clear();
    lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
    lcd.print("Delete");
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Fingerprint");
  }
  
  else if (currentState == 2 && buttonPressed == DOWN_BUTTON_MENU)
  {
    (currentState == 3);
    lcd.clear();
    lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
    lcd.print("Search");
    lcd.setCursor(0,1);                       // set lcd.setCursor (column,row) 
    lcd.print("Fingerprint");
  }
  
  else if (currentState == 3 && buttonPressed == DOWN_BUTTON_MENU)
  {
    (currentState == 4);
    lcd.clear();
    lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
    lcd.print("Empty Database");
  }
  
  else if (currentState == 4 && buttonPressed == DOWN_BUTTON_MENU)
  {
    //(currentState == 0);
    lcd.clear();
    lcd.setCursor(0,0);                       // set lcd.setCursor (column,row) 
    lcd.print("Search Database");
  }
///////////////////////////////////////////////////////////////////////////////

Thanks,
Useful lessons for me too !

(currentState == 1); does nothing. Actually not quite true, but not what you want
currentState = 1; sets the currentState variable to 1

== compares 2 things
= sets the variable on the left to the value on the right.

UKHeliBob:
(currentState == 1); does nothing. Actually not quite true, but not what you want
currentState = 1; sets the currentState variable to 1

== compares 2 things
= sets the variable on the left to the value on the right.

actually not quite true? i think my coding is like this. my initial state is zero by the way. currentState = 0; sets the currentState variable to 1

In your code you have: (currentState == 1);

That won't do as you are intending. Assuming you want currentState to change to 1 you need to change it to: currentState = 1;