TransWikia.com

128x64 and pushButtons

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;   
}
}

One Answer

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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP