Pages: [1]   Go Down
Author Topic: Help with basic LCD menu  (Read 2047 times)
0 Members and 1 Guest are viewing this topic.
Leicester, MA USA
Offline Offline
Jr. Member
**
Karma: 1
Posts: 88
Arduino newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've searched and searched and can't seem to find exactly what I'm looking for. I want to create a basic menu (if you can even call it that) for my LCD display with just a single button to change the menus, and up/down buttons for fan speeds (that'll be controlled only when that fan's menu is displayed). Here's how I want it to go:

Welcome screen
(on power-up)
     |
     |
Display 1
(coolant temp/flow rate)
     |
     |
Display 2
(Intake fan speed/voltage)
     |
     |
Display 3
(Exhaust fan 1 speed/voltage)
     |
     |
Display 5
(Exhaust fan 2 speed/voltage)
     |
     |
Back to display 1 and so on

There will also be a button-controlled servo to open and close a door but that will be independent of the menu system and not displayed.

Obviously I need 5 interrupts (flow meter, fan 1, fan 2, fan 3, servo button) and only have 2, which is why I'm going to use a ChipKIT MAX32 which has 5 interrupts and plenty of I/O for controlling fan speeds, etc. so that problem it solved.

I've got each system (except fan speed control) working independently with separate coding and each works fine (temp/flow works fine, fan speed display works fine). I just can't figure out how to merge them all together into a single working unit. I've seen several different menu libraries but they seem way more complex than what I need. I was thinking button state change or something but can't figure out how to get it all working properly.

What's the best way to go about that?
Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You just need a user interface to adjust parameters. For simplicity, such as maybe 3 lines per parameter adjustment, you can get the phi-panel:

http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/serial-lcd-back-pack---phi-panel/

Then the menu will be like

case 'U':
if (speed<max_speed) speed+=speed_increment;
//update serial lcd
break;

case 'D':
if (speed>minspeed) speed-=speed_increment;
//update serial lcd
break;
Logged


Pakistan
Offline Offline
Sr. Member
****
Karma: 6
Posts: 357
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Look this thread and especially the end of pages  and you will find no menu easier than it.This is called MENWIZ by brunialti... Its brilliant, easy and cover almost all the things in a very easy way. Dont forget to read the pdf guide.smiley
http://arduino.cc/forum/index.php/topic,99693.0.html
« Last Edit: December 10, 2012, 09:58:12 am by Khalid » Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Look this thread and especially the end of pages  and you will find no menu easier than it.This is called MENWIZ by brunialti... Its brilliant, easy and cover almost all the things in a very easy way. Dont forget to read the pdf guide.smiley
http://arduino.cc/forum/index.php/topic,99693.0.html

Yes it is good but what you view as easy maybe hard to those beginners. If you have found my phi-panels, you will take back the "find no menu easier than it" statement.
Logged


Pakistan
Offline Offline
Sr. Member
****
Karma: 6
Posts: 357
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

liudr,
I downloaded your phi library but it was difficult to understand, its not your fault, but i have less brain power.. I really like the videos you posted about your library but its difficult to find simple examples using Analoge button and 3wire lcds...
Is their any, pls point out.
Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

liudr,
I downloaded your phi library but it was difficult to understand, its not your fault, but i have less brain power.. I really like the videos you posted about your library but its difficult to find simple examples using Analoge button and 3wire lcds...
Is their any, pls point out.

Khalid, there are two things I provide that does menus:
1) phi_prompt library and its support library. They run with most types of inputs and HD44780 LCD. The setup part is a bit hard but my new version will provide simple setup functions.
2) phi-panel serial lcd panels or backpacks. These are hardware I designed and are already set up to run some of the phi_prompt menu functions. You simply send out a plain text to these panels through serial port with a command. The panels render the menu and interacts with users then return to you what the user selects.

I was referring to solution 2 for the OP.
Logged


Pakistan
Offline Offline
Sr. Member
****
Karma: 6
Posts: 357
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

both the options require custom hardware which i have to purchase with the high shipment. smiley-kitty
Logged


Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What's the best way to go about that?

It is fairly simple:

Code:
  button=read_button(button_pin); //read button on button_pin
  switch (button) {
  case 'U': //up button is pressed
     app_index = (app_index)?(app_index-1):MAX_APP; //update app_index
     break;
  case 'D': //down button is pressed
     app_index = (app_index==MAX_APP)?0:(app_index+1_; //update app_index
     break;
  default: do_something(); //illegal key press. do something / nothing
  }

  switch (app_index) {
  case 0: app0(); //run 1st application
             break;
  case 1: app1(); //run 2nd application
             break;
  ...
  }

You can start to fill the various boxes / functions. For example, if you use analog buttons, you just need to implement it in read_button(); and you can put your coolant / flowrate display in app0(); your fan speed/voltage in app1(); ...

It cannot be simpler than that, once you cut it down to logical blocks and implement those blocks one at a time.
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

both the options require custom hardware which i have to purchase with the high shipment. smiley-kitty
Option one is free. just get an hd44780 display and a few buttons. If you think $6 is expensive for international shipping, FYI shipping to Australia or Europe is almost $6 plus bubble wrap and time.
Logged


Leicester, MA USA
Offline Offline
Jr. Member
**
Karma: 1
Posts: 88
Arduino newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What's the best way to go about that?

It is fairly simple:

Code:
  button=read_button(button_pin); //read button on button_pin
  switch (button) {
  case 'U': //up button is pressed
     app_index = (app_index)?(app_index-1):MAX_APP; //update app_index
     break;
  case 'D': //down button is pressed
     app_index = (app_index==MAX_APP)?0:(app_index+1_; //update app_index
     break;
  default: do_something(); //illegal key press. do something / nothing
  }

  switch (app_index) {
  case 0: app0(); //run 1st application
             break;
  case 1: app1(); //run 2nd application
             break;
  ...
  }

You can start to fill the various boxes / functions. For example, if you use analog buttons, you just need to implement it in read_button(); and you can put your coolant / flowrate display in app0(); your fan speed/voltage in app1(); ...

It cannot be simpler than that, once you cut it down to logical blocks and implement those blocks one at a time.


ok so where exactly do I put my functions? do I put it in app0(xxxx);?
Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That code is a snippet, i.e. not complete. You complete it. Yes that was what dhenry meant.
Logged


Leicester, MA USA
Offline Offline
Jr. Member
**
Karma: 1
Posts: 88
Arduino newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That code is a snippet, i.e. not complete. You complete it. Yes that was what dhenry meant.

I know it's just a snippet I'm just lost as to where to put my actual analogRead etc etc in the snippet
Logged


Leicester, MA USA
Offline Offline
Jr. Member
**
Karma: 1
Posts: 88
Arduino newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's what I've got so far. It works as is with the commented-out lines (kinda - I can't get the % to display if it's showing 100). Am I on the right track?

Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

const int buttonPin = 11;
const int potPin = A0;
const int tempPin = A1;
const int fan = 10;
const int buttonMin = 0;
const int buttonMax = 1;
int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;

void setup(){
  pinMode(buttonPin, INPUT);
  pinMode(potPin, INPUT);
  pinMode(tempPin, INPUT);
  pinMode(fan, OUTPUT);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print(" Project:    ");
  lcd.setCursor(0, 1);
  lcd.print("    Circuit Box ");
  delay(5000);
  lcd.clear();
}

void loop(){
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    buttonState = reading;
  }
  //int range = map(reading, buttonMin, buttonMax, 0, 1); //Map the range to 2 options
//  switch (range) {
  //  case '0': // Manual Mode
      lcd.setCursor(0, 0);
      lcd.print("  Manual Mode   ");
      int fanSpeed = analogRead(potPin);
      fanSpeed = map(fanSpeed, 0, 1023, 120, 255);
      int  fanpct = map(fanSpeed, 120, 254, 40, 100);
      lcd.setCursor(0, 1);
      lcd.print("Fan Speed:");
      lcd.setCursor(11, 1);
      lcd.print(fanpct);
      if (fanpct < 100) lcd.print ('%');
  //    lcd.setCursor(14, 1);
//      lcd.print("%");
      analogWrite(fan, fanSpeed);
/*      break;
    case '1': // Automatic Mode
      lcd.setCursor(0, 0);
      lcd.print(" Automatic Mode ");
      int
      break;
    }
    delay(1);
}

  lcd.setCursor(0, 0);
  lcd.print("  Manual Mode   ");
  int fanSpeed = analogRead(potPin);
  fanSpeed = map(fanSpeed, 0, 1023, 120, 255);
  int  fanpct = map(fanSpeed, 120, 255, 40, 100);
  lcd.setCursor(0, 1);
  lcd.print("Fan Speed:");
  lcd.setCursor(14, 1);
  lcd.print("%");
  analogWrite(fan, fanSpeed); */
}
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm confused by dhenry's answer.

Your original question was how to show 5 screens by pushing one button?

This shows the general idea. It outputs to serial so you can test by just grounding pin 8 (to act as your switch).

Code:
const byte mySwitch = 8; 

// these "states" are what screen is currently being displayed.
typedef enum
  {
  POWER_ON, COOLANT, INTAKE_SPEED, EXHAUST_FAN1, EXHAUST_FAN2,
  // add more here ...
 
  LAST_STATE  // have this last
  } states;

byte state = POWER_ON;

byte oldSwitch = HIGH;

void powerOn ()
  {
  Serial.println ("Welcome!");
  }
 
void showCoolant ()
  {
  Serial.println ("Coolant level = x");
  }
 
void showIntakeSpeed ()
  {
  Serial.println ("Intake speed = x");
  }
 
void showExhaustFan1 ()
  {
  Serial.println ("Exhaust Fan 1 = x");
  }
 
void showExhaustFan2 ()
  {
  Serial.println ("Exhaust Fan 2 = x");
  }
 
void setup ()
  {
  pinMode (mySwitch, INPUT_PULLUP);
  Serial.begin (115200);
  powerOn ();
  }  // end of setup
 
void loop ()
  {
  byte switchValue = digitalRead (mySwitch);
 
  // detect switch presses
  if (switchValue != oldSwitch)
    {
    delay (100);   // debounce

    // was it pressed?
    if (switchValue == LOW)
      {
      state++;      // next state
      if (state >= LAST_STATE)
        state = COOLANT; 
     
      switch (state)
        {
        case POWER_ON:     powerOn ();         break;
        case COOLANT:      showCoolant ();     break;
        case INTAKE_SPEED: showIntakeSpeed (); break;
        case EXHAUST_FAN1: showExhaustFan1 (); break;
        case EXHAUST_FAN2: showExhaustFan2 (); break;
        }  // end of switch
      }  // end of switch being pressed
     
    oldSwitch = switchValue; 
    } // end of switch changing state
   
  }  // end of loop
Logged

Leicester, MA USA
Offline Offline
Jr. Member
**
Karma: 1
Posts: 88
Arduino newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm confused by dhenry's answer.

Your original question was how to show 5 screens by pushing one button?

This shows the general idea. It outputs to serial so you can test by just grounding pin 8 (to act as your switch).

Code:
const byte mySwitch = 8; 

// these "states" are what screen is currently being displayed.
typedef enum
  {
  POWER_ON, COOLANT, INTAKE_SPEED, EXHAUST_FAN1, EXHAUST_FAN2,
  // add more here ...
 
  LAST_STATE  // have this last
  } states;

byte state = POWER_ON;

byte oldSwitch = HIGH;

void powerOn ()
  {
  Serial.println ("Welcome!");
  }
 
void showCoolant ()
  {
  Serial.println ("Coolant level = x");
  }
 
void showIntakeSpeed ()
  {
  Serial.println ("Intake speed = x");
  }
 
void showExhaustFan1 ()
  {
  Serial.println ("Exhaust Fan 1 = x");
  }
 
void showExhaustFan2 ()
  {
  Serial.println ("Exhaust Fan 2 = x");
  }
 
void setup ()
  {
  pinMode (mySwitch, INPUT_PULLUP);
  Serial.begin (115200);
  powerOn ();
  }  // end of setup
 
void loop ()
  {
  byte switchValue = digitalRead (mySwitch);
 
  // detect switch presses
  if (switchValue != oldSwitch)
    {
    delay (100);   // debounce

    // was it pressed?
    if (switchValue == LOW)
      {
      state++;      // next state
      if (state >= LAST_STATE)
        state = COOLANT; 
     
      switch (state)
        {
        case POWER_ON:     powerOn ();         break;
        case COOLANT:      showCoolant ();     break;
        case INTAKE_SPEED: showIntakeSpeed (); break;
        case EXHAUST_FAN1: showExhaustFan1 (); break;
        case EXHAUST_FAN2: showExhaustFan2 (); break;
        }  // end of switch
      }  // end of switch being pressed
     
    oldSwitch = switchValue; 
    } // end of switch changing state
   
  }  // end of loop

OK that makes much more sense now that I see it laid out. I'm going much simpler than originally planned with only 2 options instead of 5 - automatic mode (temp-sensor controlled PWM fan speed) and manual mode (potentiometer-controlled PWM fan speed). I'll also be upgrading to a 20x4 LCD (when it arrives). The top 2 lines will display coolant temp and flow rate all the time with the bottom 2 lines switching between manual and auto modes with fan speed shown (which is what I'm trying to get working right now on the 16x2 I'm currently using)
Logged


Pages: [1]   Go Up
Jump to: