Arduino Asked by Iulian Chirvasa on February 12, 2021
Could someone give me some advice related to building a menu for a 128×64 LCD using 5 pushButtons?
i have 5 screens.
btn1 is for display MainMenu and Selection.
btn2 and btn3 is for up and down scrolling
btn 4 and btn4 is for switching on/off and increase decrease values.
the problem which i encounter is related to btn2 and btn3.
i don;t know how to use them for scrolling in in another screen except screen1 (MainMenu).
#include "U8glib.h"
U8GLIB_ST7920_128X64_1X u8g(13,12,11); //Enable, RW, RS, RESET
int selectionButton = A1, selectionButtonState, selectionButtonLastState = 0, cntSelectionButtonPressed = 0, cntSelectionButtonPressed2ForMenu2 = 0;
int menuButton = A0, menuButtonState, menuButtonLastState = 0;
int scrollDownButton = A3, scrollDownButtonState, scrollDownButtonLastState = 0;
boolean mainMenu = false;
void setup()
{
Serial.begin(9600);
if ( u8g.getMode() == U8G_MODE_R3G3B2 )
u8g.setColorIndex(255); // white
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
u8g.setColorIndex(3); // max intensity
else if ( u8g.getMode() == U8G_MODE_BW )
pinMode(selectionButton,INPUT);
pinMode(menuButton,INPUT);
pinMode(scrollDownButton,INPUT);
}
void loop()
{
scrollDownButtonState = digitalRead(A3);
selectionButton = digitalRead(A1);
menuButton = digitalRead(A0);
//pin A1 = RiGHT
if(selectionButton != selectionButtonLastState)
{
if(digitalRead(A1) == HIGH)
{
cntSelectionButtonPressed += 1;
if(cntSelectionButtonPressed == 4)
{
cntSelectionButtonPressed = 0;
}
}
selectionButtonLastState = selectionButton;
}
////////////////////////
if(menuButton != menuButtonLastState)
{
if(cntSelectionButtonPressed == 1 && digitalRead(A0) == HIGH)
{
cntSelectionButtonPressed2ForMenu2 += 1;
}
if(cntSelectionButtonPressed2ForMenu2 == 4)
{
cntSelectionButtonPressed2ForMenu2 = 0;
}
u8g.firstPage();
do{
Menu2();
}while(u8g.nextPage());
menuButtonLastState = menuButton;
}
else
{
u8g.firstPage();
do{
MainMenu();
}while(u8g.nextPage());
}
}
void MainMenu(){
switch(cntSelectionButtonPressed)
{
case 1:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print("> Ceas");
u8g.setPrintPos(15,25);
u8g.print(" Interior casa");
u8g.setPrintPos(15,35);
u8g.print(" Exterior casa");
break;
case 2:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print(" Ceas");
u8g.setPrintPos(15,25);
u8g.print("> Interior casa");
u8g.setPrintPos(15,35);
u8g.print(" Exterior casa");
break;
break;
case 3:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print(" Ceas");
u8g.setPrintPos(15,25);
u8g.print(" Interior casa");
u8g.setPrintPos(15,35);
u8g.print("> Exterior casa");
break;
}
}
void Menu2()
{
switch(cntSelectionButtonPressed2ForMenu2)
{
case 1:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print("> Stil1");
u8g.setPrintPos(15,25);
u8g.print(" Stil2");
u8g.setPrintPos(15,35);
u8g.print(" Stil3");
break;
case 2:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print(" Stil1");
u8g.setPrintPos(15,25);
u8g.print("> Stil2");
u8g.setPrintPos(15,35);
u8g.print(" Stil3");
break;
break;
case 3:
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(15,15);
u8g.print(" Stil1");
u8g.setPrintPos(15,25);
u8g.print(" Stil2");
u8g.setPrintPos(15,35);
u8g.print("> Stil3");
break;
}
}
First, I'm a bit surprised you use analog pins for button checks, instead of digital pins.
About the code, without analyzing it completely, the easiest way is to make a state diagram in pseudo code first.
E.g.suppose you want to have the following screens(a screen 'title/content' is shown in[], a button transition with ---(key)-->
InitScreen--- (right)--> MenuOption1Highlight---(right)-->MenuOption1Items
| ^ ---(left)----+
(down) (up)
v |
MenuOption2Highlight---(right)-->MenuOption2Items
---(left)----+
To program this (roughly), create an enumeration for each menu page :
enum EMenuPage
{
None,
InitScreen,
MenuOption1Highlight,
MenuOption1Items,
MenuOption2Highlight,
MenuOption2Items
};
Than create a current state for it as global variable:
EMenuPage _eMenuPage;
And initialize it in Setup:
_eMenuPage = None;
Create an enum for the keys :
enum EKey
{
None,
Up,
Down,
Right,
Left
};
It is easier to create a function that reads keys, and returns one key, maybe one key has priority over another, or you can combine keys (in that case add in EKey e.g. UpAndDown). If no key has been pressed, None is selected.
In the loop, use a state transition diagram to program out the options :
EKey pressedKey = GetPressedKey(); // This is for yourself to implement, it updates _pressedKey;
switch (_eMenuPage)
{
case None:
InitScreen();
break;
case InitScreen:
ProcessInitScreenKeys();
break;
case MenuOptions1HighLighted:
ProcessMenuOptions1HighLightedKeys();
break;
...
default:
// Illegal key
break;
}
For each page you make a function (e.g. InitScreen) which updates the state and shows the content on the display:
void InitScreen()
{
_eMenuPage = InitScreen;
// Show content on display.
}
Also, you create a Process...Keys function to handle the keys. Like:
void InitScreen()
{
EKey pressedKey = GetPressedKey();
switch (pressedKey)
{
case Right:
MenuOptions1HighLighted();
break;
default:
// Ignore other keys
break;
}
}
For another function it would look like:
void ProcessMenuOptions1HighLightedKeys()
{
EKey pressedKey = GetPressedKey();
switch (pressedKey)
{
case Down:
MenuOptions1HighLighted();
break;
case Right:
MenuOption1Items();
break;
default:
// Ignore other keys
break;
}
}
(Btw I did not check neither compiled the code).
Probably there is a nicer more object oriented way to do this, but it costs more memory and is more advanced. This is to create an abstract Page class, which has two virtual methods (one to show and one to handle keys), and create a derived class for each page implementing the two functions from the base class.
Answered by Michel Keijzers on February 12, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP