code does not separate 1st selection

I am trying to promt the user to mak the first pick using the F1 and F2 buttons on this LCD shield. Then the user will be promt to make another choice based on the first selection using the 4 arrow keys. After the second choice is made, the LCD should display both choices together. Currently my code has two displays at the end, one for the F1 and one For the F2. What am I missing to make it only display the choice that was selected?
Also, is there away to make the second promt remain on screen until button is pressed. I use a delay to give time to read screen and press button?

// Define / Initiate Variables
char Key;  // define the variable that will hold the button press

// the setup routine runs once when you press reset:
void setup() 
{                
  // initialize Serial port and set baudrate at 4800 bps
  Serial.begin(4800);
}

// the loop routine runs over and over again forever:
void loop() 
{
  Serial.write(1);    // clear screen and home cursor
  Serial.print("Thin (F1)       Deep dish (F2)");  //prompt user
  Key = Serial.read();  // wait for button press
  delay (400);

if(Key=='5')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor - Deep Dish
    Serial.print("S(^) M(>) L(V)  XL(<)");  //prompt user
    delay(2000);
  }
  if(Key=='1')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Small Deep Dish");
    delay(2000);
  }
  if(Key=='2')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Medium Deep Dish");
    delay(2000);
  }
  if(Key=='3')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Large Deep Dish");
    delay(2000);
  }
  if(Key=='4')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Extra Large Deep Dish");
    delay(2000);
  }
  

  
if(Key=='6')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor - Think crust
    Serial.print("S(^) M(>) L(V)  XL(<)");
    delay(2000);
  }
  if(Key=='1')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Small Thin");
    delay(2000);
  }
 if(Key=='2')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Medium Thin");
    delay(2000);
  }
 if(Key=='3')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Large Thin");
    delay(2000);
  }
 if(Key=='4')        // button 1 was pressed
  {
    Serial.write(1);    // clear screen and home cursor
    Serial.print("Extra Large Thin");
    delay(2000);
  }
  }

Read Serial Input Basics and Planning and Implementing a Program

What kind of serial display do you have ? What’s the keyboard ?

It is an ATS-1 Terminal Shield, no additional keyboard.

Key = Serial.read();  // wait for button press

That doesn't wait for anything. Serial.read() takes the next character out of the buffer. If there's nothing there, too bad.

And this won't help:

Key = Serial.read();  // wait for button press
delay (400);

By the time it gets into the delay() the Serial.read() is over and done with.

CoryC: It is an ATS-1 Terminal Shield, no additional keyboard.

This guy here?

Never seen a shield connected to the serial pins 0 and 1 before....

The first example in the first link of J-M-L's #1 above shows how to read single characters elegantly. I like how it splits up the receipt of a character (recvOneChar()) and the use thereof (showNewData()).

If I read your opening post and the manual at the site I found correctly, you want to first enter F1 or F2 (returning a 5 or a 6 respectively) followed by an arrow (returning 1-4 respectively).

So you want (5 and (1, 2, 3, or 4)) or (6 and (1, 2, 3, or 4))

Looks to me that you need to implement a state machine, where you have a state variable indicating that you are waiting for the first input or the second input. Let's say that state variable is called ooooo I don't know, stateVariable ;) and initialise it as 0. If stateVariable = 0, read serial into a variable called say firstPart, and if firstPart is 5 or 6*, set stateVariable to 1, where we await secondPart, initialised as 0. Only read serial into secondPart if stateVariable is 1; by which time we already know firstPart is a 5 or 6. Then, if secondPart is 1, 2, 3 or 4**, you have the two things you need to know, each neatly kept in two separate variables.

it's easy then to ignore the user hitting the arrows when you're waiting for a F1 or F2, since at that stage we can reject illegal input, knowing that in state 0 we limit ourselves to accepting a 5 or 6. * similarly in state 1, we only accept 1, 2, 3 or 4.

Not sure how you would get back to state 0 for the next item. Maybe if secondPArt has taken the non- zero value (where we initialised it) of 1,2,3 4 you could then look for an F1 (=5) into another variable which this time means set stateVariable=0 and secondPArt back to 0 also for next time.

(The beauty of such a scheme is that eg F1's value of 5 can have different effects at different times.)

Does that make sense? It made perfect sense to me ;) but it might be total bollocks.

EDIT: in fact have 3 states, 0 waiting, 5 deep and 6 thin. You're not far off the mark actually, I think the flaw is that you only have 1 input variable, key, so when you go 5 then 1 it doesn't know that it's 1 within 5, so to speak.

HINT for above: use switch...case for the state variables and have your existing if blocks in the 5 or 6 cases, with case 0 just waiting for a 5 or 6.

I am having difficulty figuring out how to implement these suggestions of state or of the switch_case with “char Key;” already defining variables. I get further away each attempt. This is were I am at…

// Define / Initiate Variables
char Key;  // define the variable that will hold the button press


void setup() 
{                
  Serial.begin(4800);
}

void loop() 
{
  Serial.write(1);                                  // clear screen and home cursor
  Serial.print("Thin (F1)       Deep dish (F2)");   //prompt user
  Key = Serial.read();                              // wait for button press 
  delay (400);

  if(Key=='5')                                      // F2 was pressed - Deep Dish
  {
    Serial.write(1);                                // clear screen and home cursor 
    Serial.print("S(^) M(>) L(V)  XL(<)");
    delay(2000);
  }
  if(Key=='1' && '5')                                // up arrow was pressed
  {
    Serial.write(1);                                 // clear screen and home cursor
    Serial.print("Small Deep Dish");
    delay(2000);
  }
  if(Key=='2' && '5')                                // left arrow was pressed
  {
    Serial.write(1);                                 // clear screen and home cursor
    Serial.print("Medium Deep Dish");
    delay(2000);
  }
  if(Key=='3' && '5')                                 // down arrow was pressed
  {
    Serial.write(1);                                  // clear screen and home cursor
    Serial.print("Large Deep Dish");
    delay(2000);
  }
  if(Key=='4' && '5')                                 // right arrow was pressed
  {
    Serial.write(1);                                  // clear screen and home cursor
    Serial.print("Extra Large Deep Dish");
    delay(2000);
  }
  if(Key=='6')                                        // F1 was pressed - Think crust
  {
    Serial.write(1);                                   // clear screen and home cursor 
    Serial.print("S(^) M(>) L(V)  XL(<)");
    delay(2000);
  }
    if(Key=='1' && '6')                                // up arrow was pressed
  {
    Serial.write(1);                                   // clear screen and home cursor
    Serial.print("Small Thin Crust");
    delay(2000);
  }
  if(Key=='2' && '6')                                  // left arrow was pressed
  {
    Serial.write(1);                                   // clear screen and home cursor
    Serial.print("Medium Thin Crust");
    delay(2000);
  }
  if(Key=='3' && '6')                                  // down arrow was pressed
  {
    Serial.write(1);                                   // clear screen and home cursor
    Serial.print("Large Thin Crust");
    delay(2000);
  }
  if(Key=='4' && '6')                                  // right arrow was pressed
  {
    Serial.write(1);                                   // clear screen and home cursor
    Serial.print("Extra Large Thin Crust");
    delay(2000);
  }
}

Right now, when I push F1 or F2 the second prompt will display. When I press any arrow it with display the size selected with deep dish then it clears screen and displays that size again with Thin crust. How can I get it to hold just the selected F1 or F2.

Have a look at the code below.

I don't have your hardware (does anyone? ;) ) so I used input just typed from the monitor and my output is just back to the monitor. You should probably run this without your shield so you can test it same as I wrote it, to understamd the idea. It uses the idea from the link j-m-l gave.

It reads the input at the top of loop() every time. What it does with the input varies depending if it's in state 0 (waiting), 5 (thin) or 6 (thick). (I ended up calling the state variable thinthick.)

(The use of the variable newlyArrivedAtThisState is to prevent the monitor printing the text a gazillion times- limits it to once. That sort of check is probably not needed when printing to an lcd but I had to do it that way for the monitor.)

Oh and I just stuck a 2000ms delay in after you make the size choice in 5 an 6 so that it goes back to the first message in state 0 by itself.

// ref https://forum.arduino.cc/index.php?topic=644918
// 7 nov 2019

// choose a pizza: thick or thin, then size
// reads data from serial ala Robin2 Ex1 https://forum.arduino.cc/index.php?topic=396450.0

bool newlyArrivedInThisState = true; //so as not to keep on printing the messages
char thinThick = '0'; //start in the waiting state
char receivedChar;
boolean newData = false;

void setup()
{
  // initialize serial communication:
  Serial.begin(9600);
  Serial.println("setup() ... ");
  Serial.println(".... pizza menu ....");
  Serial.println("setup() done");
  Serial.println(" ");
}

void loop()
{
  recvOneChar();
  doStates();
} //loop

void recvOneChar() 
{
  if (Serial.available() > 0) {
    receivedChar = Serial.read(); //although there may be more behind it in the buffer
    newData = true;
    //Serial.println(receivedChar); //quick test
  }
}//recvOneChar

void doStates()
{
  switch (thinThick)
  {
    case '0': //waiting for thick or thin
      if (newlyArrivedInThisState)
      {
        Serial.println("Enter 5 or 6 for thin or thick");
        newlyArrivedInThisState = false;
      }

      if (newData)
      {
        if (receivedChar == '5') thinThick = '5';
        else if (receivedChar == '6') thinThick = '6';
        else Serial.println("Illegal choice");
        newlyArrivedInThisState = true; //so we get the welcome message again
        newData = false;
      }

      break;

    case '5': // thin, waiting for size
      if (newlyArrivedInThisState)
      {
        Serial.println("Enter 1,2,3,4 for s,m,l,xl thin");
        newlyArrivedInThisState = false;
      }

      if (newData)
      {
        thinThick = '0'; //will be going back to main screen after this
        if (receivedChar == '1') Serial.print("Small ");
        else if (receivedChar == '2') Serial.print("Medium ");
        else if (receivedChar == '3') Serial.print("Large ");
        else if (receivedChar == '4') Serial.print("Extra Large ");
        else
        {
          Serial.print("Illegal choice of ");
          thinThick = '5'; //stay in this state but start over
        }
        Serial.println("Thin");
        newlyArrivedInThisState = true;
        newData = false;
        delay(2000);
        newlyArrivedInThisState = true;
      }

      break;

    case '6': // thick, waiting for size
      if (newlyArrivedInThisState)
      {
        Serial.println("Enter 1,2,3,4 for s,m,l,xl thick");
        newlyArrivedInThisState = false;
      }

      if (newData)
      {
        thinThick = '0'; //will be going back to main screen after this
        if (receivedChar == '1') Serial.print("Small ");
        else if (receivedChar == '2') Serial.print("Medium ");
        else if (receivedChar == '3') Serial.print("Large ");
        else if (receivedChar == '4') Serial.print("Extra Large ");
        else
        {
          Serial.print("Illegal choice of ");
          thinThick = '6'; //stay in this state but start over
        }
        Serial.println("Thick");
        newlyArrivedInThisState = true;
        newData = false;
        delay(2000);
        newlyArrivedInThisState = true;
      }

      break;

  }//switch
}//doStates

PS…

Apart from the coding being incorrect, this is logically impossible because Key can’t have two values at the same time:

if(Key=='1' && '5')

That’s what my approach takes care of. The variable thickThin takes on the value of 5 or 6, and then “under that” so to speak we look for the next variable* to be 1, 2, 3 or 4.

  • which I just left as receivedChar, but which could then be saved into a different variable called say pizzaSize if required.

BTW the correct syntax for that, if it was logically possible for Key to be both 1 and 5 simultaneously, would be:

if(Key=='1' && Key== '5')