Arduino Forum

Forum 2005-2010 (read only) => Software => Interfacing => Topic started by: jman31 on Jan 19, 2010, 02:53 pm

Title: LCD menu options (best route)
Post by: jman31 on Jan 19, 2010, 02:53 pm
Hi,

I have been searching the internet for two solid days now to get an idea of how to do menu options with an LCD. I have included a flow chart of basically what I am trying to accomplish. I am very new to programming, so I am learning as I go. I have also included the code that I have written so far and tried to make notations of what it does and what I am trying to do. So far I have one button doing sort of what I am after. Still a long way off though I am afraid.

The program eventually will basically choose an LED and some options for the LED that will light up a drum when struck through a midi input. Most of the midi stuff has been programmed by someone else and I a trying to interact a 16x2 LCD (4 bit) with it.

It will have five buttons. up, down, right, left and center (store). I don't think that I am on the right path for the buttons and accessing menu options, so if any of you has some advice I could sure use some help.

Thanks
Jeremy

HERE (http://www.italentshare.com/storage/Midi%20Lights/Midi%20Lights%20Schematic%202.jpg) is a mostly completed schematic. Still have some tweaking to do on it.

(http://www.italentshare.com/storage/Midi%20Lights/button%20scheme.jpg)

Code: [Select]
/*
  LCD portion of the code. Sets up the pins
  and intro screen.
 
 The circuit:
 * LCD RS pin to digital pin 2
 * LCD Enable pin to digital pin 3
 * 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
 * 10K resistor:
   * ends to +5V and ground
   * wiper to LCD VO pin (pin 3)
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 
 */

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

// initialize the 4 bit LCD library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

// constants won't change. They're used here to
// set pin numbers:

const int ledPin =  13;      // the number of the LED pin

int switchPin1 =12;              // switch1 is connected to pin 12
int switchPin2 =11;              // switch2 is connected to pin 11
int switchPin3 =10;              // switch3 is connected to pin 10
int switchPin4 =9;              // switch4 is connected to pin 9
int switchPin5 =8;              // switch5 is connected to pin 8

int led1Pin = 13;
int led2Pin = 8;
int led3Pin = 9;
int led4Pin = 10;
int led5Pin = 12;

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int lightMode = 0;              // What mode is the light in?



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void setup() {
 
  //LCD SETUP
 
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
 
  // Print a message to the LCD.
  lcd.print("**MIDI NIGHTS**");
  delay (1000);
  lcd.setCursor(0, 4);
  lcd.print("LED Menu Options");
  delay (1000);
  lcd.clear();
   
    // resets cursor position
  lcd.setCursor(0, 4);
  lcd.print("    Use right/left buttons to select LED    ");
  delay (20);
 
    // scroll 150 positions (string length) to the left
    // to move it offscreen left:
 for (int positionCounter = 0; positionCounter < 27; positionCounter++) {
    // scroll one position left:
   lcd.scrollDisplayLeft();
    // wait a bit:
   delay(50);
 }
 lcd.clear();    //clear screen and reset cursor
 lcd.setCursor(1, 9);
 lcd.print("Select LED < >");  //Select desired LED
 delay (4000);    // delays on this screen then goes to led choices
 
 //BUTTON SETUP
 
 pinMode(switchPin1, INPUT);    // Set the switch pin as input for menu right
 pinMode(switchPin2, INPUT);    // Set the switch pin as input for menu left
 pinMode(switchPin3, INPUT);    // Set the switch pin as input for menu up
 pinMode(switchPin4, INPUT);    // Set the switch pin as input for menu down
 pinMode(switchPin5, INPUT);    // Set the switch pin as input for menu store

 pinMode(led1Pin, OUTPUT);     // leds outputs that will eventually become the LEDs 1-33 (11 LED selections with three colors each)
 pinMode(led2Pin, OUTPUT);     // right now they each button press lights up the same light
 pinMode(led3Pin, OUTPUT);     // ultimate goal is to charlieplex with decoder and latches
 pinMode(led4Pin, OUTPUT);
 pinMode(led5Pin, OUTPUT);
 
 Serial.begin(9600);           // Set up serial communication at 9600bps
 buttonState = digitalRead(switchPin1);   // read the initial state
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void loop() {
 val = digitalRead(switchPin1);      // read input value and store it in val
 delay(10);                         // 10 milliseconds is a good amount of time
 val2 = digitalRead(switchPin1);     // read the input again to check for bounces
 if (val == val2) {                 // make sure we got 2 consistant readings!
   if (val != buttonState) {          // the button state has changed!
     if (val == LOW) {                // check if the button is pressed
       if (lightMode == 0) {          // if its off
         lightMode = 1;               // turn light on!
       } else {
         if (lightMode == 1) {        //
           lightMode = 2;             //
         } else {
           if (lightMode == 2) {      //
             lightMode = 3;           //
             } else {
               if (lightMode == 3) {      //
                 lightMode = 4;           //
                 } else {
                   if (lightMode == 4) {      //
                     lightMode = 5;           //
                        } else {
                   if (lightMode == 5) { //  
                       lightMode = 0;           //
                 }
               }
             }
         }
         }
       }
     }
   }
   buttonState = val;                 // save the new state in our variable
 }

 // Now do whatever the lightMode indicates
 if (lightMode == 0) { // LED on
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 1");
   delay (100);
   
 }

 if (lightMode == 1) {             // LED on
   digitalWrite(led1Pin, HIGH);    //turns on LED
   lcd.clear();                    // clears screen
   lcd.print("LED 2");             // name of led
   delay (100);                    // delay to keep the lCD from flashing so much while looping, not exactly what I am after
 }

 if (lightMode == 2) { // LED on
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 3");
   delay (100);
 }
 if (lightMode == 3)  { // LED on
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 4");
   delay (100);
 }
if (lightMode == 4)  { // LED on
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 5");
   delay (100);
 }  
if (lightMode == 5)  { // LED on
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 6");
   delay (100);
 }
}


Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 19, 2010, 04:10 pm
Code: [Select]
if (lightMode == 0) {          // if its off
         lightMode = 1;               // turn light on!
       } else {
         if (lightMode == 1) {        //
           lightMode = 2;             //
         } else {
           if (lightMode == 2) {      //
             lightMode = 3;           //
             } else {
               if (lightMode == 3) {      //
                 lightMode = 4;           //
                 } else {
                   if (lightMode == 4) {      //
                     lightMode = 5;           //
                        } else {
                   if (lightMode == 5) { //  
                       lightMode = 0;           //
                 }


Can I introduce you to Mr Switch statement?
http://arduino.cc/en/Reference/SwitchCase

or even Ms Modulo?
http://arduino.cc/en/Reference/Modulo

One other minor thing:
Code: [Select]
// constants won't change. They're used here to
// set pin numbers:

const int ledPin =  13;      // the number of the LED pin

int switchPin1 =12;              // switch1 is connected to pin 12
int switchPin2 =11;              // switch2 is connected to pin 11
int switchPin3 =10;              // switch3 is connected to pin 10
int switchPin4 =9;              // switch4 is connected to pin 9
int switchPin5 =8;              // switch5 is connected to pin 8

int led1Pin = 13;
int led2Pin = 8;
int led3Pin = 9;
int led4Pin = 10;
int led5Pin = 12;


As per the comment, does this mean you plan on dynamically moving these led and switch pins?
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 19, 2010, 07:22 pm
Hi Groove,

I have looked over the switch/case tutorial and googled everything I can find on it and I am just not sure how to implement it. I am confused as to what all needs to be included. Everything I tried kicked back errors.

I am not sure what you mean by dynamically moving the led's and switch pins, but I don't think so. I guess they could all be constants. I think I just had some remnants left over from something else I tried which may lead to confusion with the variables. I will have three led's in each drum. Each a different color. I want to be able to select one of these three colors. I should have probably labeled it "Snare", "Tom" or "Cymbal" instead of LED1, LED2 and LED3 and so forth. The buttons will be there to access each drum light and pick one of three colors mounted in that drum.

Thanks for taking the time to look this over!
Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 19, 2010, 07:33 pm
Code: [Select]
switch (lightMode) {
   case 0: lightMode = 1; break;
   case 1: lightMode = 2; break;
   case 2: lightMode = 3; break;
   case 3: lightMode = 4; break;
   case 4: lightMode = 5; break;
   case 5: lightMode = 0; break;
}


or even more succinct:
Code: [Select]
lightMode = (lightMode + 1) % 6;
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 19, 2010, 08:58 pm
OK, I got it to actually do something. However, I am not sure how to implement the button, so it is not waiting for a button push. It is simply looping through the LED menu. I am assuming an "if" statement of some sort within each case?

Here is the revised code.

Thanks for your helpfulness. It means a lot!!


Code: [Select]
/*
  LCD portion of the code. Sets up the pins
  and intro screen.
 
 The circuit:
 * LCD RS pin to digital pin 2
 * LCD Enable pin to digital pin 3
 * 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
 * 10K resistor:
   * ends to +5V and ground
   * wiper to LCD VO pin (pin 3)
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 
 */

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

// initialize the 4 bit LCD library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);


// set pin numbers:


int switchPin1 =12;              // switch1 is connected to pin 12
int switchPin2 =11;              // switch2 is connected to pin 11
int switchPin3 =10;              // switch3 is connected to pin 10
int switchPin4 =9;              // switch4 is connected to pin 9
int switchPin5 =8;              // switch5 is connected to pin 8

int led1Pin = 13;
int led2Pin = 8;
int led3Pin = 9;
int led4Pin = 10;
int led5Pin = 1;

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int lightMode;                 // What mode is the light in?



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void setup() {
 
  //LCD SETUP
 
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
 
  // Print a message to the LCD.
  lcd.print("**MIDI NIGHTS**");
  delay (1000);
  lcd.setCursor(0, 4);
  lcd.print("LED Menu Options");
  delay (1000);
  lcd.clear();
   
    // resets cursor position
  lcd.setCursor(0, 4);
  lcd.print("    Use right/left buttons to select LED    ");
  delay (20);
 
    // scroll 150 positions (string length) to the left
    // to move it offscreen left:
 for (int positionCounter = 0; positionCounter < 27; positionCounter++) {
    // scroll one position left:
   lcd.scrollDisplayLeft();
    // wait a bit:
   delay(50);
 }
 lcd.clear();    //clear screen and reset cursor
 lcd.setCursor(1, 9);
 lcd.print("Select LED < >");  //Select desired LED
 delay (4000);    // delays on this screen then goes to led choices
 
 //BUTTON SETUP
 
 pinMode(switchPin1, INPUT);    // Set the switch pin as input for menu right
 pinMode(switchPin2, INPUT);    // Set the switch pin as input for menu left
 pinMode(switchPin3, INPUT);    // Set the switch pin as input for menu up
 pinMode(switchPin4, INPUT);    // Set the switch pin as input for menu down
 pinMode(switchPin5, INPUT);    // Set the switch pin as input for menu store

 pinMode(led1Pin, OUTPUT);     // leds outputs that will eventually become the LEDs 1-33 (11 LED selections with three colors each)
 pinMode(led2Pin, OUTPUT);     // right now they each button press lights up the same light
 pinMode(led3Pin, OUTPUT);     // ultimate goal is to charlieplex with decoder and latches
 pinMode(led4Pin, OUTPUT);
 pinMode(led5Pin, OUTPUT);
 
 Serial.begin(9600);           // Set up serial communication at 9600bps
 buttonState = digitalRead(switchPin1);   // read the initial state
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void loop() {

switch (lightMode){
                                   // Now do whatever the lightMode indicates
 case 0: lightMode = 1;  
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 1");
   delay (100);
   break;


 case 1: lightMode = 2;            
   digitalWrite(led1Pin, HIGH);    //turns on LED
   lcd.clear();                    // clears screen
   lcd.print("LED 2");             // name of led
   delay (100);                    // delay to keep the lCD from flashing so much while looping, not exactly what I am after
   break;
 

 case 2: lightMode = 3;  
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 3");
   delay (100);
   break;
 
 case 3: lightMode = 4;  
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 4");
   delay (100);
   break;
 
 case 4: lightMode = 5;  
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 5");
   delay (100);
   break;
 
 case 5: lightMode = 6;  
   digitalWrite(led1Pin, HIGH);
   lcd.clear();
   lcd.print("LED 6");
   delay (100);

 case 6: lightMode = 0;
 break;
 }
}
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 02:31 pm
Wow, that was brutal, but I finally got a switch case situation to work. I believe I can start actually coding something now! ::)

Here is the very basic code:

Code: [Select]
// include the library code:
#include <LiquidCrystal.h>

// initialize the 4 bit LCD library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//first define states with obvious names and different values
#define START 0
#define RED 1
#define BLUE 2
//next define which pin is which
#define RED_PIN 9
#define BLUE_PIN 10


int buttonState = 0;
int switchPin = 11;              // switch is connected to pin 2
int val;                        // variable for reading the pin status
int val2;
int lightMode = 0;              // What mode is the light in?
int state = START; //create state variable and initialize it to START state

 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
void setup() {
 
  //LCD SETUP
 
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
 
  // Print a message to the LCD.
 
  lcd.print("**MIDI NIGHTS**");
  delay (1000);
  lcd.setCursor(0, 4);
  lcd.print("LED Menu Options");
  delay (1000);
  lcd.clear();
   
    // resets cursor position
  lcd.setCursor(0, 4);
  lcd.print("    Use right/left buttons to select LED    ");
  delay (20);
 
    // scroll 150 positions (string length) to the left
    // to move it offscreen left:
   for (int positionCounter = 0; positionCounter < 27; positionCounter++) {
    // scroll one position left:
   lcd.scrollDisplayLeft();
    // wait a bit:
   delay(50);
   }
{
 delay (300);
 lcd.clear();    //clear screen and reset cursor
 lcd.setCursor(1, 9);
 lcd.print("Select LED < >");  //Select desired LED
 delay(2000);
}
pinMode(RED_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
digitalWrite(BLUE_PIN,LOW); //turn blue led off
digitalWrite(RED_PIN,LOW); //turn red led off
pinMode(switchPin, INPUT);    // Set the switch pin as input


Serial.begin(9600);           // Set up serial communication at 9600bps

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void loop(){
buttonState = digitalRead(switchPin);
 
 if (buttonState == LOW){
   }
else {
 //FSM time
switch(state){
case START:
   lcd.clear();
   lcd.print("Snare");
   digitalWrite(BLUE_PIN,LOW); //turn blue led off
   digitalWrite(RED_PIN,LOW); //turn red led off
   delay(100); //wait 100ms
   state = RED; //transition to red state
   break; //end of START case
 case RED:
   lcd.clear();
   lcd.print("TOM1");
   digitalWrite(BLUE_PIN,LOW); //turn blue led off
   digitalWrite(RED_PIN,HIGH); //turn red led on
   delay(200); //wait 200ms
   state = BLUE; //transition to blue state
   break; //end of RED case
 case BLUE:
   lcd.clear();
   lcd.print("TOM2");
   digitalWrite(RED_PIN,LOW); //turn red led off
   digitalWrite(BLUE_PIN,HIGH); //turn blue led on
   delay(200); //wait 200ms
   state = START; //transition to start state
   break; //end of BLUE case
 }
}
}
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 03:00 pm
You have this:

Code: [Select]
 if (buttonState == LOW){
   }
else {


Why not simply:

Code: [Select]
if(buttonState == HIGH){
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 03:18 pm
Ha Ha, yep that works too. Thanks! 8-)

I am now trying to nest a second switch/case into the first case "Start" and I a can't get any reaction from it. I think I have some of the {} in the wrong places. Any thoughts?

Code: [Select]
#include <Button.h>

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

// initialize the 4 bit LCD library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//first define states with obvious names and different values
#define START 0
#define RED 1
#define BLUE 2
#define START2 0
#define RED2 1
#define BLUE2 2
//next define which pin is which
#define RED_PIN 9
#define BLUE_PIN 10


int buttonState = 0;
int buttonState2 = 0;
int switchPin = 11;              // switch is connected to pin 11
int switchPin2 = 12;            // switch is connected to pin 12

int state = START; //create state variable and initialize it to START state
int state2 = START2; //create state variable and initialize it to START state

 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
void setup() {
 
  //LCD SETUP
 
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
 
  // Print a message to the LCD.
 
  lcd.print("**MIDI NIGHTS**");
  delay (1000);
  lcd.setCursor(0, 4);
  lcd.print("LED Menu Options");
  delay (1000);
  lcd.clear();
   
    // resets cursor position
  lcd.setCursor(0, 4);
  lcd.print("    Use right/left buttons to select LED    ");
  delay (20);
 
    // scroll 150 positions (string length) to the left
    // to move it offscreen left:
   for (int positionCounter = 0; positionCounter < 27; positionCounter++) {
    // scroll one position left:
   lcd.scrollDisplayLeft();
    // wait a bit:
   delay(50);
   }
{
 delay (300);
 lcd.clear();    //clear screen and reset cursor
 lcd.setCursor(1, 9);
 lcd.print("Select LED < >");  //Select desired LED
 delay(2000);
}
pinMode(RED_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
digitalWrite(BLUE_PIN,LOW); //turn blue led off
digitalWrite(RED_PIN,LOW); //turn red led off
pinMode(switchPin, INPUT);    // Set the switch pin as input
pinMode(switchPin2, INPUT);    // Set the switch pin as input

Serial.begin(9600);           // Set up serial communication at 9600bps

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void loop(){
buttonState = digitalRead(switchPin);
buttonState2 = digitalRead(switchPin2);

 if (buttonState == HIGH){
 //FSM time
switch(state){
case START:
   lcd.clear();
   lcd.print("Snare");
   digitalWrite(BLUE_PIN,LOW); //turn blue led off
   digitalWrite(RED_PIN,LOW); //turn red led off
   delay(100); //wait 100ms

                   
         if (buttonState2 == HIGH)
       switch(state2){
           case START2:
               lcd.clear();
               lcd.print("Color 1");
               state2 = RED2; //transition to red state
               break; //end of START case
           case RED2:
               lcd.clear();
               lcd.print("Color 2");
               state2 = BLUE2; //transition to blue state
               break; //end of RED case
           case BLUE2:
               lcd.clear();
               lcd.print("Color 3");
               state2 = START2; //transition to start state
               break; //end of BLUE case
       }
   state = RED; //transition to red state    
   break; //end of START case              
 

   
 case RED:
   lcd.clear();
   lcd.print("TOM1");
   digitalWrite(BLUE_PIN,LOW); //turn blue led off
   digitalWrite(RED_PIN,HIGH); //turn red led on
   delay(200); //wait 200ms
   state = BLUE; //transition to blue state
   break; //end of RED case
 case BLUE:
   lcd.clear();
   lcd.print("TOM2");
   digitalWrite(RED_PIN,LOW); //turn red led off
   digitalWrite(BLUE_PIN,HIGH); //turn blue led on
   delay(200); //wait 200ms
   state = START; //transition to start state
   break; //end of BLUE case
 }
}
}
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 03:22 pm
Code: [Select]
if (buttonState2 == HIGH)
[glow]{
[/glow]        switch(state2){
           case START2:
               lcd.clear();
               lcd.print("Color 1");
               state2 = RED2; //transition to red state
               break; //end of START case
           case RED2:
               lcd.clear();
               lcd.print("Color 2");
               state2 = BLUE2; //transition to blue state
               break; //end of RED case
           case BLUE2:
               lcd.clear();
               lcd.print("Color 3");
               state2 = START2; //transition to start state
               break; //end of BLUE case
       }
[glow]}[/glow]
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 03:33 pm
I tried that, but nothing changed. Any other ideas or possible errors in my code?

Thank you for looking at this for my PaulS!
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 04:14 pm
The code, as you have it written, requires that you have both buttons pressed. Do you?
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 04:35 pm
No, I wasn't. I guess I need to change "buttonState" back to low before I can use "buttonState2" by itself?
Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 20, 2010, 04:35 pm
Quote
I tried that, but nothing changed

That's because they're not required.
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 04:46 pm
Is there another way I can write "buttonState" at the beginning of the loop so that I can bring it back to LOW during the second switch/case?
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 05:05 pm
What you could do is move the button 2 code after the end of the button 1 switch statement, and execute the code if state == RED.
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 05:35 pm
Hope you guys aren't getting sick of me yet. I really appreciate your time and input. I am learning as I go and wearing my google button out! ::)

Here is how I tried to implement your idea PaulS. I still get no entry into the second switch/case. I changed up some of the variable names to make more sense with the project. I hope that doesn't throw too much confusion into the mix.

If I can get this last issue, then maybe I can leave you guys alone for awhile! :D

Code: [Select]
void loop(){
 buttonState = digitalRead(switchPin);
 buttonState2 = digitalRead(switchPin2);

 if (buttonState == HIGH){
   switch(ledstate){
   case LED1:
     lcd.clear();
     lcd.print("Snare");
     digitalWrite(BLUE_PIN,HIGH); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led off
     delay(100); //wait 100ms
     ledstate = LED2; //transition to red state    
     break; //end of START case              

   case LED2:
     lcd.clear();
     lcd.print("TOM 1");
     digitalWrite(BLUE_PIN,LOW); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led on
     delay(200); //wait 200ms
     ledstate = LED3; //transition to blue state
     break; //end of RED case

   case LED3:
     lcd.clear();
     lcd.print("TOM 2");
     digitalWrite(RED_PIN,LOW); //turn red led off
     digitalWrite(BLUE_PIN,HIGH); //turn blue led on
     delay(200); //wait 200ms
     ledstate = LED1; //transition to start state
     break; //end of BLUE case
   }

   {
     if (ledstate == LED2)
       if (buttonState2 == HIGH)
         if (buttonState == LOW){
           switch(colorState){
           case COLOR1:
             lcd.clear();
             lcd.print("Color 1");
             colorState = COLOR2; //transition to red state
             break; //end of START case
           case COLOR2:
             lcd.clear();
             lcd.print("Color 2");
             colorState = COLOR3; //transition to blue state
             break; //end of RED case
           case COLOR3:
             lcd.clear();
             lcd.print("Color 3");
             colorState = COLOR1; //transition to start state
             break; //end of BLUE case
           }
         }

   }
 }
}
Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 20, 2010, 07:05 pm
This:
Code: [Select]
     if (ledstate == LED2)
       if (buttonState2 == HIGH)
         if (buttonState == LOW){


is the same as writing:
Code: [Select]
     if  ( (ledstate == LED2) &&
           (buttonState2 == HIGH) &&
           (buttonState == LOW)) {
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 07:16 pm
OK, but will that change anything to make it work?
Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 20, 2010, 07:19 pm
No, but it may make it easier to read.
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 07:23 pm
OK    :)
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 08:50 pm
Is it safe to assume that you pushed button 1, and then pushed button 2?
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 09:12 pm
Yes and although you were correct in that, It is definitely not what I am after. I tried moving it outside of the case, but think it is still expecting a "high" on button one to make it function when ledstate == led2

I made some changes to the variable names as I mentioned.
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 09:38 pm
You aren't debouncing the buttons, or toggling behavior only when the button state changes.

Your behavior is based on the button state being HIGH.

This is fine if you want something to happen while a button is pressed, like a doorbell ringing. It's not fine, if you want to implement a state machine, as you are (trying to).

You need to keep track of the previous state of the buttons, and only act when the state changes:

Code: [Select]
int previousButtonOneState = LOW;
int previousButtonTwoState = LOW;

void loop()
{
  int buttonOneState = digitalRead(buttonOnePin);
  int buttonTwoState = digitalRead(buttonTwoPin);

  if(buttonOneState == HIGH && previousButtonOneState == LOW)
  {
      // Button One was just pushed. Make the state changes...
  }
  previousButtonOneState = buttonOneState;

  if(buttonTwoState == HIGH && previousButtonTwoState == LOW)
  {
      // Button Two was just pushed. Now, we can rely on the state
  }
  previousButtonTwoState = buttonTwoState;
}
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 10:07 pm
Thanks for that. I think maybe I am biting off more than I can chew with my limited knowledge. I added the code you gave me before the switch statements, but I obviously didn't do it correctly.

Here is what I did. I deleted some of the code that didn't pertain to what we are talking about.

Code: [Select]

int previousButtonOneState;
int previousButtonTwoState;
int buttonOneState;
int buttonTwoState;


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
void setup() {



 pinMode(RED_PIN, OUTPUT);      // Set the pin as output
 pinMode(BLUE_PIN, OUTPUT);    // Set the pin as output
 pinMode(switchPin, INPUT);    // Set the switch pin as input
 pinMode(switchPin2, INPUT);    // Set the switch pin as input

 digitalWrite(BLUE_PIN,LOW);   //turn blue led off
 digitalWrite(RED_PIN,LOW);     //turn red led off

 Serial.begin(9600);           // Set up serial communication at 9600bps

 previousButtonOneState = LOW;
 previousButtonTwoState = LOW;

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void loop(){
 {
   if(buttonOneState == HIGH && previousButtonOneState == LOW){
     // Button One was just pushed. Make the state changes...
   }
   previousButtonOneState = buttonOneState;

   if(buttonTwoState == HIGH && previousButtonTwoState == LOW){
     // Button Two was just pushed. Now, we can rely on the state
   }
   previousButtonTwoState = buttonTwoState;
 }

   switch(ledstate){
   case LED1:
     lcd.clear();
     lcd.print("Snare");
     digitalWrite(BLUE_PIN,HIGH); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led off
     delay(100); //wait 100ms
     switch(colorState){
     case COLOR1:
       lcd.clear();
       lcd.print("Color 1");
       colorState = COLOR2; //transition to color2 state
       break; //end of color1 case
     case COLOR2:
       lcd.clear();
       lcd.print("Color 2");
       colorState = COLOR3; //transition to color3 state
       break; //end of color2 case
     case COLOR3:
       lcd.clear();
       lcd.print("Color 3");
       colorState = COLOR1; //transition back to color1 state
       break; //end of color3 case
     }
     ledstate = LED2; //transition to led2 state    
     break; //end of START case              

   case LED2:
     lcd.clear();
     lcd.print("TOM 1");
     digitalWrite(BLUE_PIN,LOW); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led on
     delay(200); //wait 200ms
     ledstate = LED3; //transition to led3 state
     break; //end of RED case

   case LED3:
     lcd.clear();
     lcd.print("TOM 2");
     digitalWrite(RED_PIN,LOW); //turn red led off
     digitalWrite(BLUE_PIN,HIGH); //turn blue led on
     delay(200); //wait 200ms
     ledstate = LED1; //transition to led1 state
     break; //end of BLUE case
   }
 }
}
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 20, 2010, 10:12 pm
At least, you're trying. Boy, are you trying. ;)

The whole switch statement, where you change the state goes inside the {} where the comment says

// Button One was just pushed. Make the state changes...
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 10:23 pm
Man, I sure appreciate you hanging in there with me. I figure the only way for me to learn it since I live in a small town (no resources available) is to jump in and try to code something.  :-?

Ok, does the nested code go in the second {} or does it remain in line like this? I'm still missing something. :-/

Code: [Select]

void loop(){


  if(buttonOneState == HIGH && previousButtonOneState == LOW)
  {
   switch(ledstate){
   case LED1:
     lcd.clear();
     lcd.print("Snare");
     digitalWrite(BLUE_PIN,HIGH); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led off
     delay(100); //wait 100ms
     switch(colorState){
     case COLOR1:
       lcd.clear();
       lcd.print("Color 1");
       colorState = COLOR2; //transition to color2 state
       break; //end of color1 case
     case COLOR2:
       lcd.clear();
       lcd.print("Color 2");
       colorState = COLOR3; //transition to color3 state
       break; //end of color2 case
     case COLOR3:
       lcd.clear();
       lcd.print("Color 3");
       colorState = COLOR1; //transition back to color1 state
       break; //end of color3 case
     }
     ledstate = LED2; //transition to led2 state    
     break; //end of START case              

   case LED2:
     lcd.clear();
     lcd.print("TOM 1");
     digitalWrite(BLUE_PIN,LOW); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led on
     delay(200); //wait 200ms
     ledstate = LED3; //transition to led3 state
     break; //end of RED case

   case LED3:
     lcd.clear();
     lcd.print("TOM 2");
     digitalWrite(RED_PIN,LOW); //turn red led off
     digitalWrite(BLUE_PIN,HIGH); //turn blue led on
     delay(200); //wait 200ms
     ledstate = LED1; //transition to led1 state
     break; //end of BLUE case
   }


  previousButtonOneState = buttonOneState;

  if(buttonTwoState == HIGH && previousButtonTwoState == LOW)
  {
      // Button Two was just pushed. Now, we can rely on the state
  }
  previousButtonTwoState = buttonTwoState;
}


Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 20, 2010, 11:24 pm
I think I got it. I am sure I will be back, but that will get me started for now. Thanks to everyone that lent me a helping hand!!!!!  8-)
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 21, 2010, 02:42 am
Man I am so close! But yet so far away. Here is what I have. By changing the {} around I can get it to enter the second Switch/Case, but I never have any control with the second button. It cycles through the color cases every time I get back around to the LED1 case.

Code: [Select]
void loop(){

 buttonOneState = digitalRead(switchPin);
 buttonTwoState = digitalRead(switchPin2);

 if(buttonOneState == HIGH && previousButtonOneState == LOW){
   switch(ledstate){
   case LED1:
     lcd.clear();
     lcd.print("Snare");
     if(buttonTwoState == HIGH && previousButtonTwoState == LOW){        
       switch(colorState){
       case COLOR1:
         lcd.clear();
         lcd.print("Color 1");
         colorState = COLOR2; //transition to color2 state
         break; //end of color1 case
       case COLOR2:
         lcd.clear();
         lcd.print("Color 2");
         colorState = COLOR3; //transition to color3 state
         break; //end of color2 case
       case COLOR3:
         lcd.clear();
         lcd.print("Color 3");
         colorState = COLOR1; //transition back to color1 state
         break; //end of color3 case
         previousButtonTwoState = buttonTwoState;
       }  
     }
     digitalWrite(BLUE_PIN,HIGH); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led off
     delay(100); //wait 100ms
     ledstate = LED2; //transition to led2 state    
     break; //end of led1 case

   case LED2:
     lcd.clear();
     lcd.print("TOM 1");
     digitalWrite(BLUE_PIN,LOW); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led on
     delay(200); //wait 200ms
     ledstate = LED3; //transition to led3 state
     break; //end of led2 case

   case LED3:
     lcd.clear();
     lcd.print("TOM 2");
     digitalWrite(RED_PIN,LOW); //turn red led off
     digitalWrite(BLUE_PIN,HIGH); //turn blue led on
     delay(200); //wait 200ms
     ledstate = LED1; //transition to led1 state
     break; //end of led3 case

   }
 }
 previousButtonOneState = buttonOneState;
 previousButtonTwoState = buttonTwoState;
}
Title: Re: LCD menu options (best route)
Post by: PaulS on Jan 21, 2010, 11:33 am
On any given pass through loop, which probably happens far oftener than you think, only one button is pressed. Only one button can have changed state.

Therefore, you need to treat the buttons, and their states, as completely independent.

In the loop function, see if button 1 is being presses, but was not before. If that is the case, set ledState.

Then, see if button 2 is being pressed, but was not before. If that is the case, set colorState.

The value of colorState has nothing to do with whether button 1 is being pressed, or not. It depends on (or changes as a result of) ledState, not whether button 1 is being pressed.
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 21, 2010, 01:21 pm
OK, this time I got it. I moved the entire colorstate switch out of the first loop and then added "ledstate == LED2" to the first line as was mentioned before. Thanks for the help again PaulS! 8-)

Here is the code as it works for me.

Code: [Select]


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

// initialize the 4 bit LCD library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//first define states with obvious names and different values
#define LED1 0
#define LED2 1
#define LED3 2
#define COLOR1 3
#define COLOR2 4
#define COLOR3 5

//next define which pin is which
#define RED_PIN 9
#define BLUE_PIN 10


int buttonState = 0;
int buttonState2 = 0;
int switchPin = 11;              // switch is connected to pin 11
int switchPin2 = 12;            // switch is connected to pin 12

int ledstate = LED1; //create state variable and initialize it to START state
int colorState = COLOR1; //create state variable and initialize it to START state

int previousButtonOneState;
int previousButtonTwoState;
int buttonOneState;
int buttonTwoState;


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
void setup() {

 //LCD SETUP

 // set up the LCD's number of rows and columns:
 lcd.begin(16, 2);

 // Print a message to the LCD.

 lcd.print("**MIDI NIGHTS**");
 delay (1000);
 lcd.setCursor(0, 4);
 lcd.print("LED Menu Options");
 delay (1000);
 lcd.clear();

 // resets cursor position
 lcd.setCursor(0, 4);
 lcd.print("    Use right/left buttons to select LED    ");
 delay (20);

 // scroll 27 positions (string length) to the left
 // to move it offscreen left:
 for (int positionCounter = 0; positionCounter < 27; positionCounter++) {
   // scroll one position left:
   lcd.scrollDisplayLeft();
   // wait a bit:
   delay(50);
 }
 {
   delay (300);

   lcd.clear();    //clear LCD and reset cursor
   lcd.setCursor(1, 9);
   lcd.print("Select LED < >");  //Select desired LED from menu
   delay(2000);
 }

 pinMode(RED_PIN, OUTPUT);      // Set the pin as output
 pinMode(BLUE_PIN, OUTPUT);    // Set the pin as output
 pinMode(switchPin, INPUT);    // Set the switch pin as input
 pinMode(switchPin2, INPUT);    // Set the switch pin as input

 digitalWrite(BLUE_PIN,LOW);   //turn blue led off
 digitalWrite(RED_PIN,LOW);     //turn red led off

 Serial.begin(9600);           // Set up serial communication at 9600bps

 previousButtonOneState = LOW;
 previousButtonTwoState = LOW;
 buttonOneState = LOW;
 buttonTwoState = LOW;

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void loop(){

 buttonOneState = digitalRead(switchPin);
 buttonTwoState = digitalRead(switchPin2);

 if(buttonOneState == HIGH && previousButtonOneState == LOW){
   switch(ledstate){
   case LED1:
     lcd.clear();
     lcd.print("Snare");
     digitalWrite(BLUE_PIN,HIGH); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led off
     delay(100); //wait 100ms
     ledstate = LED2; //transition to led2 state    
     break; //end of led1 case

   case LED2:
     lcd.clear();
     lcd.print("TOM 1");
     digitalWrite(BLUE_PIN,LOW); //turn blue led off
     digitalWrite(RED_PIN,HIGH); //turn red led on
     delay(200); //wait 200ms
     ledstate = LED3; //transition to led3 state
     break; //end of led2 case

   case LED3:
     lcd.clear();
     lcd.print("TOM 2");
     digitalWrite(RED_PIN,LOW); //turn red led off
     digitalWrite(BLUE_PIN,HIGH); //turn blue led on
     delay(200); //wait 200ms
     ledstate = LED1; //transition to led1 state
     break; //end of led3 case

   }
 }
       if(buttonTwoState == HIGH && previousButtonTwoState == LOW && ledstate == LED2){      
         
         switch(colorState){
       case COLOR1:
         lcd.clear();
         lcd.print("Color 1");
         colorState = COLOR2; //transition to color2 state
         break; //end of color1 case
       case COLOR2:
         lcd.clear();
         lcd.print("Color 2");
         colorState = COLOR3; //transition to color3 state
         break; //end of color2 case
       case COLOR3:
         lcd.clear();
         lcd.print("Color 3");
         colorState = COLOR1; //transition back to color1 state
         break; //end of color3 case
         previousButtonTwoState = buttonTwoState;
       }  
     }

 previousButtonOneState = buttonOneState;
 previousButtonTwoState = buttonTwoState;
}
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 21, 2010, 03:44 pm
Next questions for anyone NOT sick of me yet! ::) ;D

I managed to get two menu tiers working with two separate buttons. I tried to make a third tier menu and going back to the first button again. Here is the code I used. I redefined switchpin as buttonStateThree hoping that that would separate it from buttonStateOne, and added this code. I am seeing "Time" cases, but once again they refuse to behave properly.

Secondly, with the direction I have gone is there any way to have another button that would go "back" through the menu options of all of these tiers?

Code: [Select]
 //Time duration Choosing
if(buttonThreeState == HIGH && previousButtonThreeState == LOW && ledState == LED2 && colorState == COLOR1){   //sets button one to the TIME2 loop    
   
   switch(durationState){
   case TIME1:
     lcd.clear();
     lcd.print("Time 1");
     durationState = TIME2; //transition to color2 state
     break; //end of color1 case
   case TIME2:
     lcd.clear();
     lcd.print("Time 2");
     durationState = TIME3; //transition to color3 state
     break; //end of color2 case
   case TIME3:
     lcd.clear();
     lcd.print("Time 3");
     durationState = TIME4; //transition back to color1 state
     break; //end of color3 case
   case TIME4:
     lcd.clear();
     lcd.print("Time 4");
     durationState = TIME1; //transition back to color1 state
     break; //end of color3 case      
     previousButtonThreeState = buttonThreeState;
   }  
 }
 previousButtonOneState = buttonOneState;
 previousButtonTwoState = buttonTwoState;
 previousButtonThreeState = buttonThreeState;
}
Title: Re: LCD menu options (best route)
Post by: GrooveFlotilla on Jan 21, 2010, 04:01 pm
My suggestion would be to separate "what the menu item does"  from "what I did to get to the menu item" (i.e the navigation controls).
A menu hierarchy can be simply written as a series of functions with infinite loops containing switch statements containing menu functions.
Menu functions can be simple actions, or function calls to sub-menus.

Once you break out of the loop at any given level, the function returns, taking you to the menu above.
Title: Re: LCD menu options (best route)
Post by: AlphaBeta on Jan 21, 2010, 09:09 pm
I completly understand if you want to do it yourself, but as per Grooves suggestion:
http://www.arduino.cc/playground/Code/Menu this is a framework that I wrote to separate the navigation and the action.

Have a play with the example, and do not hesitate to ask any questions.  :)
(about either the library or other things:)

Good luck
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 21, 2010, 09:58 pm
Trust me I have been eyeing that for two days now, but I am so new to this programming stuff that I have no idea where to start in implementing it. I actually would rather use a tried-and-true method than stumble through it myself. I will see if I can make it work for me. I installed the menu this morning and gave it a look, but a lot of it confuses me.
Title: Re: LCD menu options (best route)
Post by: jman31 on Jan 21, 2010, 10:44 pm
I may not even understand what I am asking here so please bear with me. How do I know what a library is intended to do. AlphaBeta, I see where you included your menu libraries in the sample code you included, but how does the end user know what you coded into these libraries, and then be able to use them?  :-?