What is the best way to change variables while using only an LCD?

Just wondering what would be the best way to handle this..

I have a frequency counter routine running and displaying results to my LCD. At 2 different (n1)(n2) variable, I have 2 outputs go hi or low with separate matching (h1)(h2) Hysteresis variable. There's also another (out) output variable that I have with its own (h3) hysteresis level. easy enough.. I have the code for this running and it works like a champ.

My problem is I want to be able to program the variables while the unit is running through 3 buttons (Left, Select, Right) probably configured through A0 (which I can figure out the buttons). what would be the best way to program the variables through the LCD?

My original idea was to use the "Select" button to increment a variable named "screen" and it call a subroutine that I could use "Left" or "Right" buttons to increment or decrement the variable that sub was designed to change. Select would then leave the current sub but enter the next sub. Problem is in every routine you have to re-establish all the button functions again since you're not running the loop that monitors those functions, don't you?

The other option I was thinking about was programming it through looping SELECT / CASE statments. Where "Select" button would increment "screen" and the case would be called by the variable "screen".? This hopefully would solve the button problem since it runs in void loop(), but I'm wondering if this would be the correct way to do what I need, or if I need to attack this from a whole different angle..?

Is there a somewhat easy cut & dry way of doing this that is easily expandable for future upgrades?

-Coding Newb :slight_smile:

It seems to be my turn to ask you to post all of your code so that we can help.

Problem is in every routine you have to re-establish all the button functions again since you're not running the loop that monitors those functions, don't you?

yes but that is not the biggest problem I think.
If I understand your problem correctly it can be solved somehow like this

void loop()
{
  int key = checkKey();

  switch (key)
  {
    case 1: // select
      func1();
      break;
    case 2: // left
      func2();
      break;
    case 3: // right
      func3();
      break;
    default: // do nothing
      break;
  }
  ...
}


void func1()
{
  bool ready = false;

  while (!ready) 
  {
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        ready = true;
        break;
      case 2: // left
        n1++;
        break;
      case 3: // right
        n1--;
        break;
  }
}

void func2()
{
  bool ready = false;
  while (!ready) 
  {
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        ready = true;
        break;
      case 2: // left
        n1++;
        break;
      case 3: // right
        n1--;
        break;
    }
  }
}

void func2()
{
  bool ready = false;
  while (!ready) 
  {
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        ready = true;
        break;
      case 2: // left
        n2++;
        break;
      case 3: // right
        n2--;
        break;
    }
  }
}

int checkKey()
{
  int x = analogRead(A0);
  if (x > 750) return 3;
  if (x > 500) return 2;
  if (x > 250) return 1;
  return 0;
}

That is exactly what I was thinking! However, I was worried that the Function loops don't know what the buttons are since they aren't defined in that loop..? It appears that you assign "checkKey" an interger value of 1-3 outside of the Function loops. The buttons will still work inside the function loops while they're running?? If so, that's AWESOME.. Also.. Lets say in the function loops, if I want to make more than just one increment or decrement; Couldn't I call that loop again until "Select" or "ready=true"? Or am I misreading that and "While" command will loop until it sees "ready"?

Thank you soo much for your help BTW!!
I can't wait to get home and try this!! XD

Ok, Here's what I tried.. I What you originally setup was cool, but I don't think it is going to work for what I'm trying to do.. I believe maybe an array style would be better? Perhaps you can read this and see what I'm trying to accomplish..

just to start, I would like to display Frequency result from a code I already know works.. There are at least 4 variables that need configuring however I hope to add more. I was hoping to accomplish this by stepping through each screen with the select button and using the left/right buttons to increase/decrease.. when done, I can configure either left + right to break or just tab all the way to the end with the select button to get back to the main screen.
ok, I tried your format, and I REALLY do appreciate the help.. THANK YOU!!! However, I don't think I can use that to do what I thought originally.

Here's a modded version of it (which I was hoping would work.) that's closer to what I was trying to accomplish. With this code, the buttons working were very temperamental if at all, and the LCD would display odd characters. I couldn't get "println" to work for the life of me (It acted like it wasn't printing a return character and the next line just wouldn't show on the LCD without forcefully designating where it goes.), and without some sort of delay, the entire top row of the LCD remained black after attempting to press a button. I got one of the buttons to respond to my If statements (I could see it through serial debugging), but like I said it was hit or miss if I could get it to work..

The program structure I'm looking for is kinda like this.. Only this didn't work. But I think it's probably a valid attempt for a newbie.. Hopefully I didn't kill the coding too badly. LOL

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(4,5,7,8,12,13);

// initialize variables
int n1=0;
int n2=0;
int h1=0;
int h2=0;
byte xLast;
byte yLast;
byte zLast;

void setup() {

//Setup button inputs
pinMode(A5, INPUT_PULLUP); 
pinMode(A4, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);

//Setup outputs
lcd.begin(16,2); //for display

//startup message to look all cool and stuff.
lcd.setCursor(0,0);
lcd.print(" Add lame start ");
lcd.setCursor(0,1);
lcd.print("   msg here..   ");
delay(1500);
lcd.clear();
delay(750);

}

void loop()
{
  lcd.setCursor(0,0);  //Display Main Program in loop
  lcd.println("Freq counter.   ");
  lcd.setCursor(0,1);
  lcd.print("(prog result)");
  lcd.print(" Hz"); 
  int key = checkKey();
  
//Main screen. Select setup left or right does nothing

  switch (key){
    case 1: // select
      config0();  //Goto first config screen
      break;
    case 2: // left
      break;
    case 3: // right
      break;
     default:   // do nothing
      break;
  }
 }


void config0() //Start config0 (Cut1)
{  
  bool ready = false;
  while (!ready) 
  {
    lcd.setCursor(0,0);  //Display Variable current setting
    lcd.println("set CUT 1 ");
    lcd.setCursor(0,1);
    lcd.println(n1);
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        config1();
        break;
      case 2: // left
        n1--;
        break;
      case 3: // right
        n1++;
        break;
    }
  }  
}

void config1() //Start config1 (Cut1 Hyst)
{  
  bool ready = false;
  while (!ready) 
  {
    lcd.setCursor(0,0);  //Display Variable current setting
    lcd.println("set CUT 1 Gain");
    lcd.setCursor(0,1);
    lcd.println(h1);
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        config2();
        break;
      case 2: // left
        h1--;
        break;
      case 3: // right
        h1++;
        break;
    }
  }
}
    
void config2() //Start config2 (Cut2)
{  
  bool ready = false;
  while (!ready) 
  {
    lcd.setCursor(0,0);    //Display Variable current setting
    lcd.println("set CUT 2 ");
    lcd.setCursor(0,1);
    lcd.println(n2);
    
    int key = checkKey();
    switch (key)
    {
      case 1: // select
        config3();
        break;
      case 2: // left
        n2--;
        break;
      case 3: // right
        n2++;
        break;
    }
  }
}
    
void config3() //Start config3 (Cut2 Hyst)
{  
  bool ready = false;
  while (!ready) 
  {
    lcd.setCursor(0,0);  //Display Variable current setting
    lcd.println("set CUT 2 Gain");
    lcd.setCursor(0,1);
    lcd.println(h2);
    
    int key = checkKey();
    
    switch (key)
    {
      case 1: // select
      ready=true;
        break;
      case 2: // left
        h2--;
        break;
      case 3: // right
        h2++;
        break;
    }
  }
}
    
int checkKey(){
  int xState = digitalRead(A4);
  int yState = digitalRead(A5);
  int zState = digitalRead(A3);
 
  if (xLast != xState){
   if (xState == LOW){
     return 1; //Select
   }
  }
  if (yLast != yState){
   if(yState == LOW){
      return 2; //LEFT
   }
  }
  if (zLast != zState){
   if (zState == LOW){
     return 3; //RIGHT
   }
  }
  
 
 xLast=xState;
 yLast=xState;
 zLast=zState;
  return 0;
}