Go Down

Topic: Simple universal LCD menu code (Read 46457 times) previous topic - next topic

polepole

Feb 23, 2011, 02:40 pm Last Edit: Feb 26, 2011, 03:17 pm by polepole Reason: 1
First post here. I was struggling to find an easy to implement menu system that works on a variety of LCDs. I am brand new to the arduino, and so I didn't really understand how to use the class-based menuBackend that has been floating around here. So instead, I wrote my own. This should work with 1x16, 2x16, 4x20 or any other dimension LCD.  This function creates a "Do" loop and keeps looping while waiting for user input. There is a comment near the top that indicates where you can put code that will be called in the background while looping.

If anyone has any tips or tweaks, I would like to hear it.

A few implementation notes:

  • set totalRows & totalCols to the dimensions of your LCD.

  • set menuTimeout to however long you want to wait with no user feedback before bailing out of menu (in millis). If you don't want menu to timeout, just comment out the "if (timeoutTime<millis())" statement.


  • This was set up to use a rotary encoder, but the code should be commented enough so you can figure out what code should go where using buttons. (see post a few down for a suggested implementation using buttons).


Code: [Select]


/*
REQUIRED GLOBAL VARIABLES & DEFINITIONS
*/
#define MOVECURSOR 1  // constants for indicating whether cursor should be redrawn
#define MOVELIST 2  // constants for indicating whether cursor should be redrawn
byte totalRows = 4;  // total rows of LCD
byte totalCols = 20;  // total columns of LCD
unsigned long timeoutTime = 0;  // this is set and compared to millis to see when the user last did something.
const int menuTimeout = 10000; // time to timeout in a menu when user doesn't do anything.




polepole

#1
Feb 23, 2011, 02:41 pm Last Edit: Feb 26, 2011, 03:15 pm by polepole Reason: 1
Here is the rest of the code.
Updated to 1.1 on 2/26/11.

Code: [Select]

/*
MENU ROUTINE
*/
void basicMenu(){

  byte topItemDisplayed = 0;  // stores menu item displayed at top of LCD screen
  byte cursorPosition = 0;  // where cursor is on screen, from 0 --> totalRows.

  // redraw = 0  - don't redraw
  // redraw = 1 - redraw cursor
  // redraw = 2 - redraw list
  byte redraw = MOVELIST;  // triggers whether menu is redrawn after cursor move.
  byte i=0; // temp variable for loops.
  byte totalMenuItems = 0;  //a while loop below will set this to the # of menu items.

// Put the menu items here. Remember, the first item will have a 'position' of 0.
  char* menuItems[]={
    "Set Timer 1",
    "Set Timer 2",
    "Set Probe 1 Temp",
    "Set Probe 2 Temp",
    "Probe 1 Controller",
    "Probe 2 Controller",
    "Advanced Settings",
    "",
  };

  while (menuItems[totalMenuItems] != ""){
    totalMenuItems++;  // count how many items are in list.
  }
  totalMenuItems--;  //subtract 1 so we know total items in array.

  lcd.clear();  // clear the screen so we can paint the menu.

  boolean stillSelecting = true;  // set because user is still selecting.

  timeoutTime = millis() + menuTimeout; // set initial timeout limit.

  do   // loop while waiting for user to select.
  {

    /*
    IF YOU WANT OTHER CODE GOING ON IN THE BACKGROUND
    WHILE WAITING FOR THE USER TO DO SOMETHING, PUT IT HERE
    */
   
    /*
    my code uses a rotary encoder for input.
    You should obviously change the code to meet your needs.
    For a button, you could do something like this, but note that
    it does not have ANY debouncing and will scroll for as long as
    the button is being pushed. This is not a button tutorial,
    so you should look elsewhere on how to implement that. Just
    remember that ALL of the code between the corresponding 'case'
    and 'break' should be moved to each button push routine.
   
   
    buttonState = digitalRead(buttonPin);
    if (buttonState == HIGH) {     
      AND THEN PUT THE CORRESPONDING CODE
      FROM BELOW HERE
  }
  */
    switch(read_encoder())
    {  // analyze encoder response. Default is 0.


    case 1:  // ENCODER ROTATED UP. EQUIVALENT OF 'UP' BUTTON PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      //  if cursor is at top and menu is NOT at top
      //  move menu up one.
      if(cursorPosition == 0 && topItemDisplayed > 0)  //  Cursor is at top of LCD, and there are higher menu items still to be displayed.
      {
        topItemDisplayed--;  // move top menu item displayed up one.
        redraw = MOVELIST;  // redraw the entire menu
      }

      // if cursor not at top, move it up one.
      if(cursorPosition>0)
      {
        cursorPosition--;  // move cursor up one.
        redraw = MOVECURSOR;  // redraw just cursor.
      }
      break;

    case 2:    // ENCODER ROTATED UP. EQUIVALENT OF 'DOWN' BUTTON PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      // this sees if there are menu items below the bottom of the LCD screen & sees if cursor is at bottom of LCD
      if((topItemDisplayed + (totalRows-1)) < totalMenuItems && cursorPosition == (totalRows-1))
      {
        topItemDisplayed++;  // move menu down one
        redraw = MOVELIST;  // redraw entire menu
      }
      if(cursorPosition<(totalRows-1))  // cursor is not at bottom of LCD, so move it down one.
      {
        cursorPosition++;  // move cursor down one
        redraw = MOVECURSOR;  // redraw just cursor.
      }
      break;

    case 4:  // ENCODER BUTTON PUSHED FOR SHORT PERIOD & RELEASED.
             // EQUIVALENT TO 'SELECT' OR 'OKAY' BEING PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      switch(topItemDisplayed + cursorPosition) // adding these values together = where on menuItems cursor is.
      {
      //  put code to be run when specific item is selected in place of the Serial.print filler.
      // the Serial.print code can be removed, but DO NOT change the case & break structure.
      // (Obviously, you should have as many case instances as you do menu items.)
      case 0:  // menu item 1 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        // there is no menuSubMenu1() function. BUT, to have nested menus,
        // copy this function(i.e. all of basicMenu) into a new function named
        // whatever you want for your sub menu items and repeat.
//        menuSubMenu1();
        break;

      case 1:  // menu item 2 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 2:  // menu item 3 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 3:  // menu item 4 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 4:  // menu item 5 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 5:  // menu item 6 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;


      case 6:  // menu item 7 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;
       
        // add as many "case #:" as items you have. You could put
        //  line separators in menuList and leave out the
        //  corresponding case, which would mean that nothing
        // would be triggered when user selected the line separator. 
      }
      break;
     
    case 8:  // encoder button was pushed for long time. This corresponds to "Back" or "Cancel" being pushed.
      stillSelecting = false;
      Serial.println("Button held for a long time");
      break;

    }

    switch(redraw){  //  checks if menu should be redrawn at all.
    case MOVECURSOR:  // Only the cursor needs to be moved.
      redraw = false;  // reset flag.
      if (cursorPosition > totalMenuItems) // keeps cursor from moving beyond menu items.
        cursorPosition = totalMenuItems;
      for(i = 0; i < (totalRows); i++){  // loop through all of the lines on the LCD
        lcd.setCursor(0,i);
        lcd.print(" ");                      // and erase the previously displayed cursor
        lcd.setCursor((totalCols-1), i);
        lcd.print(" ");
      }
      lcd.setCursor(0,cursorPosition);      // go to LCD line where new cursor should be & display it.
      lcd.print(">");
      lcd.setCursor((totalCols-1), cursorPosition);
      lcd.print("<");
      break;  // MOVECURSOR break.

    case MOVELIST:  // the entire menu needs to be redrawn
      redraw=MOVECURSOR;  // redraw cursor after clearing LCD and printing menu.
      lcd.clear(); // clear screen so it can be repainted.
      if(totalMenuItems>((totalRows-1))){  // if there are more menu items than LCD rows, then cycle through menu items.
        for (i = 0; i < (totalRows); i++){
          lcd.setCursor(1,i);
          lcd.print(menuItems[topItemDisplayed + i]);
        }
      }
      else{  // if menu has less items than LCD rows, display all available menu items.
        for (i = 0; i < totalMenuItems+1; i++){
          lcd.setCursor(1,i);
          lcd.print(menuItems[topItemDisplayed + i]);
        }
      }
      break;  // MOVELIST break
    }

    if (timeoutTime<millis()){  // user hasn't done anything in awhile
      stillSelecting = false;  // tell loop to bail out.
      /*
      in my main code, I had a function that
       displayed a default screen on the LCD, so
       I would put that function here, and it would
       bail out to the default screen.
       defaultScreen();
       */
    }
  }


  while (stillSelecting == true);  //
}


liuzengqiang

Good work. How many buttons do you need to operate your menu? I have something I could share but will need to smooth my code before I can post. You got me started thinking about doing it.
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

polepole

Thanks.

With my rotary encoder, I technically only have 1 button. If you were to break out the encoder functions into buttons, it would need a minimum of 3 - up, down, button 3 pressed a short time (<500ms) to select the menu item and button 3 held a longer time (>500ms) to cancel/go back. You could make the "hold button 3" into it's own 4th button - "cancel."

In the code, the cases after switch(read_encoder) correspond to the following button presses:
case 1 - up button
case 2 - down button
case 4 - select button
case 8 - cancel button

(Side note: I use powers of 2 (instead of 1,2,3,4) for the case switch because with the rotary encoder code I use, rotary states can be added up. For instance, if the button is being held down (case 16) while the rotary is being rotated (case 1), you get: 1 + 16 = 17).

nitro_boy

Hi!

is that how you implent buttons in to your code:
Code: [Select]
case 1: 
    buttonState = digitalRead(buttonUp);
    if (buttonState == HIGH) {
break;



Thanks

floresta

Quote
This should work with 1x16, 2x16, 4x20
I doubt that it will work properly for the right hand half of most 16x1 displays or for lines 3 and 4 of a 16x4 display.  This is due to limitations of the current LiquidCrystal library.  It will probably work better with LiquidCrystal440.

Quote
If anyone has any tips or tweaks, I would like to hear it.
...
... set totalRows & totalCols to the dimensions of your LCD, minus 1 (e.g. for 2x16, totalRows = 1, totalCols = 15).
I would let the user specify the actual dimensions and do the subtracting within the program.

Don

polepole


Quote
This should work with 1x16, 2x16, 4x20
I doubt that it will work properly for the right hand half of most 16x1 displays or for lines 3 and 4 of a 16x4 display.  This is due to limitations of the current LiquidCrystal library.  It will probably work better with LiquidCrystal440.


Interesting. I didn't know about that limit. While I only have a 4x20 LCD, I declared lcd.begin(16,1), and (16,4) and it seemed to work fine.

Quote
I would let the user specify the actual dimensions and do the subtracting within the program.


Thanks for the suggestion. I made the changes in the original code above.

polepole


Hi!

is that how you implent buttons in to your code:
Code: [Select]
case 1: 
    buttonState = digitalRead(buttonUp);
    if (buttonState == HIGH) {
break;



Thanks



This is a rough sketch for you, but this might work. Instead of the line
Code: [Select]
switch(read_encoder())
You'll have:
Code: [Select]

switch(read_buttons())


Then, create a new function, such as the one below (I have not compiled this, so it may not work at first).

Code: [Select]


unsigned long lastButtonPressed; // this is when the last button was pressed. It's used to debounce.
const int debounceTime = 50; //this is the debounce and hold delay. Otherwise, you will FLY
                                         //through the menu by touching the button.

void read_buttons(){  // you may need to swap "void" with "int" or "byte"
  byte returndata = 0;
  int buttonState; // this might not be the correct declaration.
  // remember to declare what buttonUp, buttonDown, buttonSelect, buttonCancel are
if ((lastButtonPressed + debounceTime) < millis(){  // see if it's time to check the buttons again
  buttonState = digitalRead(buttonUp);
  if (buttonState == HIGH){
    returndata = returndata + 1;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonDown);
  if (buttonState == HIGH){
    returndata = returndata + 2;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonSelect);
  if (buttonState == HIGH){
    returndata = returndata + 4;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonCancel);
  if (buttonState == HIGH){
    returndata = returndata + 8;
    lastButtonPressed = millis();
}
}
 return returndata; // this spits back to the function that calls it the variable returndata.
}



This was all off the cuff, but it should give you a start. Good luck.

floresta

Quote
Interesting. I didn't know about that limit. While I only have a 4x20 LCD, I declared lcd.begin(16,1), and (16,4) and it seemed to work fine.
As it stands right now the LiquidCrystal library does not do much with the information it gets from the lcd.begin function.  It does not use the column information at all and it only checks to see if the row information is '1' or something other than '1'. The default (if lcd.begin is not present) is, unfortunately, '1'.

The problem with the 16x1 devices is that most of them are actually 8x2 internally.  So if your 16x1 doesn't display anything on the right side (with any LCD library) then try treating it as an 8x2.  The problem with the 16x4 devices is that the initial addresses for lines 3 and 4 are different than the initial addresses for the same lines on 20x4 devices.  Check out the LCD Addressing link at http://web.alfredstate.edu/weimandn for more information.

I doubt that your 20x4 device worked at all on lines 2, 3 or 4 when using lcd.begin(16,1).  You should also have noticed a difference in contrast on line 1.


Don


nitro_boy

Thank you for the reply but this is my first LCD project and im not quite sure about where to insert this.

Here is my threat about my problem:
http://arduino.cc/forum/index.php/topic,53260.0.html

I would be very grateful if you could help me.

Thanks

polepole


Thank you for the reply but this is my first LCD project and im not quite sure about where to insert this.



In the Arduino sketch app, search for "switch(read_encoder())" and when you find it, replace it with, "switch(read_buttons())" (omitting the "" of course).

Then, go to the top of your sketch, before "void setup()" and paste this in:
Code: [Select]

unsigned long lastButtonPressed; // this is when the last button was pressed. It's used to debounce.
const int debounceTime = 50; //this is the debounce and hold delay. Otherwise, you will FLY
                                          //through the menu by touching the button.




Then, scroll to the bottom of your sketch, after all your other functions, and paste this code in:

Code: [Select]

void read_buttons(){  // you may need to swap "void" with "int" or "byte"
  byte returndata = 0;
  int buttonState;
  // *** REMEMBER to declare buttonUp, buttonDown, buttonSelect, & buttonCancel pins

  if ((lastButtonPressed + debounceTime) < millis()){  // see if it's time to check the buttons again
   
    // read Up button
    buttonState = digitalRead(buttonUp);
    if (buttonState == HIGH){
      returndata = returndata + 1;
      lastButtonPressed = millis();
    }

    // read Down button
    buttonState = digitalRead(buttonDown);
    if (buttonState == HIGH){
      returndata = returndata + 2;
      lastButtonPressed = millis();
    }

    // read Select button
    buttonState = digitalRead(buttonSelect);
    if (buttonState == HIGH){
      returndata = returndata + 4;
      lastButtonPressed = millis();
    }

    // read Cancel button
    buttonState = digitalRead(buttonCancel);
    if (buttonState == HIGH){
      returndata = returndata + 8;
      lastButtonPressed = millis();
    }
  }
  return returndata; // this spits back to the function that calls it the variable returndata.
}


nitro_boy

Thanks but now it says for switch(read_buttons()):

switch quantity not an integer

and somthing else do I have to include LiquidCrystal.h library  ?

polepole


Thanks but now it says for switch(read_buttons()):

switch quantity not an integer



I think this should work...
In "void read_buttons()" replace
Code: [Select]
byte returndata = 0; with   
Code: [Select]
int returndata = 0;

Quote

and somthing else do I have to include LiquidCrystal.h library  ?


Yep.

nitro_boy

#13
Mar 01, 2011, 05:17 pm Last Edit: Mar 01, 2011, 05:19 pm by Nitro_boy Reason: 1
This is the code:
Code: [Select]
/*REQUIRED GLOBAL VARIABLES & DEFINITIONS
*/
#include <LiquidCrystal.h>
#define MOVECURSOR 1  /
#define MOVELIST 2  
byte totalRows = 4;  
byte totalCols = 20;  
unsigned long timeoutTime = 0;  
const int menuTimeout = 10000;

unsigned long lastButtonPressed;
const int debounceTime = 50;
                                         
                                         
LiquidCrystal lcd(10, 11, 12, 13, 14, 15, 16);


   buttonState = digitalRead(buttonPin);
   if (buttonState == HIGH) {    
     AND THEN PUT THE CORRESPONDING CODE
     FROM BELOW HERE
 }
 */
  switch(read_buttons())
   {  // analyze encoder response. Default is 0.


   case 1:  

     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     //  if cursor is at top and menu is NOT at top
     //  move menu up one.
     if(cursorPosition == 0 && topItemDisplayed > 0)  //  Cursor is at top of LCD, and there are higher menu items still to be displayed.
     {
       topItemDisplayed--;  // move top menu item displayed up one.
       redraw = MOVELIST;  // redraw the entire menu
     }

     // if cursor not at top, move it up one.
     if(cursorPosition>0)
     {
       cursorPosition--;  // move cursor up one.
       redraw = MOVECURSOR;  // redraw just cursor.
     }
     break;

   case 2:    

     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     // this sees if there are menu items below the bottom of the LCD screen & sees if cursor is at bottom of LCD
     if((topItemDisplayed + (totalRows-1)) < totalMenuItems && cursorPosition == (totalRows-1))
     {
       topItemDisplayed++;  // move menu down one
       redraw = MOVELIST;  // redraw entire menu
     }
     if(cursorPosition<(totalRows-1))  // cursor is not at bottom of LCD, so move it down one.
     {
       cursorPosition++;  // move cursor down one
       redraw = MOVECURSOR;  // redraw just cursor.
     }
     break;

   case 4:  

     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     switch(topItemDisplayed + cursorPosition) // adding these values together = where on menuItems cursor is.
     {
     //  put code to be run when specific item is selected in place of the Serial.print filler.
     // the Serial.print code can be removed, but DO NOT change the case & break structure.
     // (Obviously, you should have as many case instances as you do menu items.)
     case 0:  // menu item 1 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       // there is no menuSubMenu1() function. BUT, to have nested menus,
       // copy this function(i.e. all of basicMenu) into a new function named
       // whatever you want for your sub menu items and repeat.
//        menuSubMenu1();
       break;

     case 1:  // menu item 2 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;

     case 2:  // menu item 3 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;

     case 3:  // menu item 4 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;

     case 4:  // menu item 5 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;

     case 5:  // menu item 6 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;


     case 6:  // menu item 7 selected
       Serial.print("Menu item ");
       Serial.print(topItemDisplayed + cursorPosition);
       Serial.print(" selected - ");
       Serial.println(menuItems[topItemDisplayed + cursorPosition]);
       break;
       
       // add as many "case #:" as items you have. You could put
       //  line separators in menuList and leave out the
       //  corresponding case, which would mean that nothing
       // would be triggered when user selected the line separator.  
     }
     break;
     
   case 8:  // encoder button was pushed for long time. This corresponds to "Back" or "Cancel" being pushed.
     stillSelecting = false;
     Serial.println("Button held for a long time");
     break;

   }

   switch(redraw){  //  checks if menu should be redrawn at all.
   case MOVECURSOR:  // Only the cursor needs to be moved.
     redraw = false;  // reset flag.
     if (cursorPosition > totalMenuItems) // keeps cursor from moving beyond menu items.
       cursorPosition = totalMenuItems;
     for(i = 0; i < (totalRows); i++){  // loop through all of the lines on the LCD
       lcd.setCursor(0,i);
       lcd.print(" ");                      // and erase the previously displayed cursor
       lcd.setCursor((totalCols-1), i);
       lcd.print(" ");
     }
     lcd.setCursor(0,cursorPosition);      // go to LCD line where new cursor should be & display it.
     lcd.print(">");
     lcd.setCursor((totalCols-1), cursorPosition);
     lcd.print("<");
     break;  // MOVECURSOR break.

   case MOVELIST:  // the entire menu needs to be redrawn
     redraw=MOVECURSOR;  // redraw cursor after clearing LCD and printing menu.
     lcd.clear(); // clear screen so it can be repainted.
     if(totalMenuItems>((totalRows-1))){  // if there are more menu items than LCD rows, then cycle through menu items.
       for (i = 0; i < (totalRows); i++){
         lcd.setCursor(1,i);
         lcd.print(menuItems[topItemDisplayed + i]);
       }
     }
     else{  // if menu has less items than LCD rows, display all available menu items.
       for (i = 0; i < totalMenuItems+1; i++){
         lcd.setCursor(1,i);
         lcd.print(menuItems[topItemDisplayed + i]);
       }
     }
     break;  // MOVELIST break
   }

   if (timeoutTime<millis()){  // user hasn't done anything in awhile
     stillSelecting = false;  // tell loop to bail out.
     /*
     in my main code, I had a function that
      displayed a default screen on the LCD, so
      I would put that function here, and it would
      bail out to the default screen.
      defaultScreen();
      */
   }
 }


 while (stillSelecting == true);  //
}

void read_buttons(){  // you may need to swap "void" with "int" or "byte"
  int returndata = 0;
  int buttonState; // this might not be the correct declaration.
  // remember to declare what buttonUp, buttonDown, buttonSelect, buttonCancel are
if ((lastButtonPressed + debounceTime) < millis(){  // see if it's time to check the buttons again
  buttonState = digitalRead(buttonUp);
  if (buttonState == HIGH){
    returndata = returndata + 1;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonDown);
  if (buttonState == HIGH){
    returndata = returndata + 2;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonSelect);
  if (buttonState == HIGH){
    returndata = returndata + 4;
    lastButtonPressed = millis();
}

  buttonState = digitalRead(buttonCancel);
  if (buttonState == HIGH){
    returndata = returndata + 8;
    lastButtonPressed = millis();
}
}
 return returndata; // this spits back to the function that calls it the variable returndata.
}


And it stil says that I have to switch quantity not an integer. I have cut out some code to fit it in the 9500 limit.

polepole

Quote

And it stil says that I have to switch quantity not an integer. I have cut out some code to fit it in the 9500 limit.


Maybe try changing "void read_buttons()" to "int read_buttons()"

Learning how to debug errors like this is important. I would recommend breaking down your sketch into pieces. Put the "read_buttons" function into a new sketch w/ basic code that serial.prints the output of read_buttons and see if you are getting the responses you want, and then go from there.

sample sketch for testing read_buttons()
Code: [Select]


int returnedData = 0;

void setup(){
}

void loop(){
returnedData = 0;
returnedData = read_buttons();
if (returnedData != 0)
  Serial.println(returnedData);
}




Go Up