Using a Push Button to aid in exploring a question tree

I am currently trying to create a question tree via the crystal ball library (part of the restrictions of the assignment).
What I want to do is have users click yes/no buttons to answer the questions which leads them to the next series of questions. (I have google-fu this already, but I still can't get it to work right). I had it working to level B yesterday then I tried to reconfigure the push buttons and ... well ... Here I am.

ex: Basic Greeting --> yes/no prompt --->Yes go to A
A) yes/no prompt ---> if yes go to B if no go to C
B) Yes/ no prompt --> If yes go to D if no return to start
C Yes/no prompt --> if yes go to E if no return to start
D) Yes/ no prompt --> if yes (FINAL MESSAGE 1) if no return to start
E) Yes/ no prompt --> If NO (final message 2) if yes return to start

Here is the basic code I have so far
Attempt 1:

#include <LiquidCrystal.h>  //liquid library code
 
// Required hardware I/O connections
const byte LCD_D7     = 2;  // connect D7 of the LCD to 2
const byte LCD_D6     = 3;  // connect D6 of the LCD to ~3
const byte LCD_D5     = 4;  // connect D5 of the LCD to 4
const byte LCD_D4     = 5;  // connect D4 of the LCD to ~5
const byte LCD_E      = 11; // connect E of the LCD to ~11
const byte LCD_RS     = 12; // connect RS of the LCD to 12
const byte yesPin            =  13;
const byte noPin              = 8;
// LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal Lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
 
// Global constants
const byte LCD_WIDTH  = 16;
const byte LCD_HEIGHT = 2;
 
// Global variables
byte YesPin           = 1;
byte prev_pin_val     = 0;
byte NoPin            = 1;
byte reply            = 0;// varies from 0 to 7
byte prev_nopin_val   = 0;

void setup() { 
  // put your setup code here, to run once:
   Lcd.begin(LCD_WIDTH, LCD_HEIGHT);
    pinMode(yesPin, INPUT);
    pinMode(noPin, INPUT);
    // intro message
    Lcd.setCursor(0, 0);
    Lcd.print("Welcome to");
    Lcd.setCursor(0, 1);
    Lcd.print("Fish Bank");
    delay(1000);
    Lcd.clear();
    Lcd.setCursor(0, 0);
    Lcd.print("Do you want");
    Lcd.setCursor(0, 1);
    Lcd.print("YOUR fish?");
    delay(2000);
    Lcd.clear();
    Lcd.print(" Click Yes or No");
}


void loop() {
      YesPin = digitalRead(yesPin);
  // put your main code here, to run repeatedly:
  
    if ((yesPin != prev_pin_val) && (YesPin == HIGH)) {
        reply = random (0); // goes to case 0
        Lcd.clear();
        Lcd.setCursor(0, 0);
        Lcd.print("Begin");
        Lcd.setCursor(0, 1);
         Lcd.print ("verification");
         Lcd.clear();
        delay(500);
        Lcd.setCursor (0,1);
 
        switch (reply) {
            case 0:
             if ((YesPin != reply) && (YesPin == HIGH)){
            Lcd.setCursor(0, 0);
            Lcd.print("Begin");
            Lcd.setCursor(0, 1);
            Lcd.print ("verification");
             Lcd.clear();
               delay(500);
            Lcd.setCursor(0,0);
                Lcd.print("Are you Human?");
                Lcd.setCursor (0, 1);
                Lcd.print ("Yes ..... No");
                 void loop();
                if ((YesPin != reply) && (YesPin == HIGH)) {
                  reply = random (1);
                  Lcd.clear ();
                  Lcd.print ("verifying");
                  delay (2000);
                  Lcd.setCursor (0, 0);
                  Lcd.print ("01101000");
                  Lcd.setCursor (0, 1);
                  Lcd.print ("01100001");
                  Lcd.clear();
                  Lcd.print ("verified");
                  delay(1100);
                  Lcd.setCursor(0, 0);
                  Lcd.print ("Do you wish");
                  Lcd.setCursor (0, 1);
                  Lcd.print ("to continue?");
                   void loop();

         switch (reply) {
              case 1:
              Lcd. setCursor(0, 0);
                Lcd.print("Are you a penguin?");
              Lcd.setCursor(0, 1);
                Lcd.print ("Yes... No");
         }
                  
                }
                break;
            
         
        }
    }
  

// No value **************************** to be worked on next

    }

second revised attempt on my break (this one does not get past the "welcome" portion in the void setup:

#include <LiquidCrystal.h>  //liquid library code
 
// Required hardware I/O connections
const byte LCD_D7     = 2;  // connect D7 of the LCD to 2
const byte LCD_D6     = 3;  // connect D6 of the LCD to ~3
const byte LCD_D5     = 4;  // connect D5 of the LCD to 4
const byte LCD_D4     = 5;  // connect D4 of the LCD to ~5
const byte LCD_E      = 11; // connect E of the LCD to ~11
const byte LCD_RS     = 12; // connect RS of the LCD to 12
const int  yesPin    =  13; //13 as the yes pin
// LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal Lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
 
// Global constants
const byte LCD_WIDTH  = 16;
const byte LCD_HEIGHT = 2;
 
// Global variables
int buttonState  = 0;
int staticButton = 0;


void setup() { 
  Lcd.begin(LCD_WIDTH, LCD_HEIGHT);    //start lcd dimensions
      pinMode(yesPin, INPUT);    //pin for yes input
           
           //begin intro message
           Lcd.setCursor(0, 0);
    Lcd.print("Welcome to your");
    Lcd.setCursor(0, 1);
    Lcd.print("fish Bank");
    delay(1000);
         Lcd.clear();
           Lcd.setCursor(0, 0);
           Lcd.print("Do you want");
           Lcd.setCursor(0, 1);
           Lcd.print("YOUR fish?");
              delay(2000);
                  Lcd.clear();
                  Lcd.print(" Click Yes or No");
}

void loop() {
     buttonState == digitalRead(yesPin); //will read off of yesPin
         
          if ((buttonState != staticButton) && (buttonState == HIGH)) {   //should read as a button push
                Lcd.clear();
                Lcd.setCursor(0, 0);
                   Lcd.print("verification?");
                Lcd.setCursor (0, 1);
                Lcd.print ("needed");
        delay(1000);
        Lcd.setCursor(0, 1);
 Lcd.print ("Are you Human?");
                delay (2000);
                Lcd.print ("yes or no?");
                 Lcd.clear();
              
                   if ((buttonState != staticButton) && (buttonState == LOW)) {
                  
                     Lcd.clear();
                     Lcd.setCursor (0, 0);
                       Lcd.print ("verifying");
                       delay(2000);
                       Lcd.print ("verified");
                       
                           Lcd.setCursor (0, 0);
                           Lcd.print ("Do you use");
                           Lcd.setCursor (0, 1);
                           Lcd.print ("fish dip?");
                           delay (2000);
                           Lcd.print ("Yes or no?");
                           Lcd.clear();

attached is the hardware set up (i took out the no button for the time being):

I"ll be trying again after work So I will let you know if I have any breakthroughs myself. Sorry for the novice level questioning!

First of all i would use INPUT_PULLUP as a pinmode for your buttons, and take a "LOW" state for them being pressed

pinMode(yesPin, INPUT);
    pinMode(noPin, INPUT);

I am seeing 1 resistor to a single button but i can't quite tell if it is actually related to it.
Sticking those ends of solid wire into the UNO is not a 100% reliable, it will work, but may also fail, just so you know.
Your first code has a 'stray' void loop() in there

   Lcd.print ("Yes ..... No");
                 void loop();
                if ((YesPin != reply) && (YesPin == HIGH)) {
                  reply = random (1);
                  Lcd.clear ();
                  Lcd.print ("verifying");

and you second code is missing a closing brace (at least one) Use ctrl-T to auto-format and indent your code and make sure the opening an closing braces match. Code that does not compile can not be tested for functionality.

void loop() {
     buttonState == digitalRead(yesPin); //will read off of yesPin
         
          if ((buttonState != staticButton) && (buttonState == HIGH)) {   //should read as a button push
                Lcd.clear();

If you only plan to read the button state once during loop, you should keep track of what menu you are in, (and the 'no-button' should also be read.

beside the problem Deva mention there are problems

the code is confusing

    YesPin = digitalRead(yesPin);

it would be better to do

    yes = digitalRead(YesPin);

good programming practice Capitalizes constants, such as a pin value that will never change and never capitalizes a variable. you use the same string for both the value of the pin, yesPin, and the value of the pin, YesPin, except one is Capitalized.

  if ((yesPin != prev_pin_val) && (YesPin == HIGH)) {

yesPin is the pin value, not the state of the pin

you do compare it to the previous pin value, but you never capture the previous pin value when it changes.

the condition only handles the HIGH case

and if you configure the pin as INPUT_PULLUP and connect the switch between the pin and ground, the state of the pin will be LOW when pressed.

  if (yes != prev_pin_val) {
        prev_pin_val = yes;

        if (LOW == yes)  {

having a separate routine to display both strings on an LCD makes the code easier to read

void
lcdDisplay (
    const char *s0,
    const char *s1 )
{
    Lcd.clear ();
    Lcd.setCursor (0, 0);
    Lcd.print (s0);
    Lcd.setCursor (0, 1);
    Lcd.print (s1);
}

with less lcd code, it's easy to see that loop() is called from within loop(). recursion isn't appropriate in this case. And the pin state is being retested without be re-read

YesPin = digitalRead (yesPin);
    // put your main code here, to run repeatedly:
    if ( (yesPin != prev_pin_val) && (YesPin == HIGH)) {
        reply = random (0); // goes to case 0

        lcdDisplay ("Begin", "verification");

        switch (reply) {
        case 0:
            if ( (YesPin != reply) && (YesPin == HIGH)){
                lcdDisplay ("Are you Human?", "Yes ..... No");

                void loop ();

                if ( (YesPin != reply) && (YesPin == HIGH)) {
                    lcdDisplay ("Do you wish", "to continue?");

                    void loop ();

                    switch (reply) {
                    case 1:
                        lcdDisplay ("Are you a penguin?", "Yes... No");
                    }
                }
                break;
            }
        }
    }

loop() is called repeatedly. it should read the button pins and check if either has been pressed. but that code also needs to keep track of which menu item it is on and display the appropriate menu strings.

you can use a switch statement to determine which menu strings to display after each button press. but you also need a way to which is the next menu item depending on which button is pressed.

Algorithms + Data Structures = Programs. figuring out how to keep track of things is the next challenge

there may be other problems

I recommend you use a variable to keep track of which question you are on and check the buttons at the top of loop. If neither button was just pressed there is no need to do anything. To tell if a button has just been pressed you would use “State Change Detection”. You may want to also debounce the switches.

Something like this:

#include <LiquidCrystal.h>  //liquid library code


// Required hardware I/O connections
const byte LCD_D7     = 2;  // connect D7 of the LCD to 2
const byte LCD_D6     = 3;  // connect D6 of the LCD to ~3
const byte LCD_D5     = 4;  // connect D5 of the LCD to 4
const byte LCD_D4     = 5;  // connect D4 of the LCD to ~5
const byte LCD_E      = 11; // connect E of the LCD to ~11
const byte LCD_RS     = 12; // connect RS of the LCD to 12
const int YesButtonPin = 13; //13 as the yes pin
const int NoButtonPin = 6;


// LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal Lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);


// Global constants
const byte LCD_WIDTH  = 16;
const byte LCD_HEIGHT = 2;


// Global variables
int CurrentQuestion = 0; // Basic Greeting


void setup()
{
  Lcd.begin(LCD_WIDTH, LCD_HEIGHT);    //start lcd dimensions
  pinMode(YesButtonPin, INPUT_PULLUP);    //pin for yes input
  pinMode(NoButtonPin, INPUT_PULLUP);    //pin for no input


  //begin intro message
  Lcd.setCursor(0, 0);
  Lcd.print("Welcome to your");
  Lcd.setCursor(0, 1);
  Lcd.print("fish Bank");
  delay(1000);
  Lcd.clear();
  Lcd.setCursor(0, 0);
  Lcd.print("Do you want");
  Lcd.setCursor(0, 1);
  Lcd.print("YOUR fish?");
  delay(2000);
  Lcd.clear();
  Lcd.print(" Click Yes or No");


  CurrentQuestion = 0; // Basic greeting
}


void loop()
{
  static int oldYesButtonState = HIGH;
  int yesButtonState = digitalRead(YesButtonPin);
  if (yesButtonState != oldYesButtonState)
  {
    oldYesButtonState = yesButtonState;
    if (yesButtonState == LOW)
    {
      // Button was just pressed
      YesButtonPressed();  // Mover to the next state...
    }
  }


  static int oldNoButtonState = HIGH;
  int noButtonState = digitalRead(NoButtonPin);
  if (noButtonState != oldNoButtonState)
  {
    oldNoButtonState = noButtonState;
    if (noButtonState == LOW)
    {
      // Button was just pressed
      NoButtonPressed();  // Mover to the next state...
    }
  }
}


void AskQuestion(const char * question)
{
  Lcd.clear();
  Lcd.setCursor(0, 0);
  Lcd.print(question);
  Lcd.setCursor (0, 1);
  Lcd.print ("Press Yes or No");
}


void YesButtonPressed()
{
  switch (CurrentQuestion)
  {
    case 0: // Basic greeting
      AskQuestion("Question A?");
      CurrentQuestion = 'A';
      break;


    case 'A':
      AskQuestion("Question B?");
      CurrentQuestion = 'B';
      break;


    case 'B':
      AskQuestion("Question D?");
      CurrentQuestion = 'D';
      break;


  }
}


void NoButtonPressed()
{
  switch (CurrentQuestion)
  {
    case 0: // Basic greeting
      AskQuestion("Question A?");
      CurrentQuestion = 'A';
      break;


    case 'A':
      AskQuestion("Question C?");
      CurrentQuestion = 'C';
      break;


    case 'C':
      AskQuestion("Question E?");
      CurrentQuestion = 'E';
      break;


  }
}

Thank you all so much! Your posts made it easy to trace my super novice errors and get it working. If I were a beautiful woman I would caress you down, if I were of a persuasion for man-to-man action I would make you my work of art. Instead, I will climb the heights of mount Olympus, chisel in hand, and carve your angelic faces for the gods to gaze in wide wonder at. You are all truly digital magicians doing the work of humanity.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.