I need help in menus and keyboard (case structure)

Hi this must be something really easy to fix, but i cant.
My project is about a servo that has a gopro in the top.
the first thing that apears in the LCD is the first selection menu
i have 3 options.

void MenuInicio()
{
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print("--Selecciona--");
lcd.selectLine(2);
lcd.print("* - Manual ");
lcd.selectLine(3);
lcd.print("# - Circuito ");
lcd.selectLine(4);
lcd.print("T - Timelapse");

}

then you can go to any of them without trouble.
The only one that is complete in code is the "Manual"
In the following screen

void menuManual()
{
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print(" Modo MANUAL ");
lcd.selectLine(2);
lcd.print("A - Angulo Mobil");
lcd.selectLine(3);
lcd.print("B - PreDefinidos");
lcd.selectLine(4);
lcd.print("0 - Salir ");
}
But here i dont know how to read the keyboard again to re direct the user to another screen that can display the angles of the servo, or direct back the user to the first menu if they want to exit.
The keyboard is not doing anything by now and i need your help.
How do i make the keyboard can be read again in the case structure or away in another function, i have tried that also.
thanks.

void loop()
{
char tecla = keypad.getKey(); //Lo primero que hace el programa es esperar tecla

switch (tecla)
{
case '*':

menuManual();
char tecla = keypad.getKey();
switch (tecla)
{
case '0':
MenuInicio();
break;
case 'A':
desplieguePotenciometro();
break;
case 'B':
preDefinidos();
break;
}
break;
/*
case '#':
Circuito();
break;

case 'D':
Timelapse();
break;
*/
}
}

Could you please post your complete code (use the code tags for that in your replay) ?
Without this its not possible to really help you.

I would make a

 void keyboard_request() {   // and again...and again
char tecla = keypad.getKey();                                     //Lo primero que hace el programa es esperar tecla
  
   switch (tecla) 
   {
     case '*':
     
       menuManual();
        char tecla = keypad.getKey(); 
        switch (tecla)
        {
          case '0':
            MenuInicio();
            break;
          case 'A':
            desplieguePotenciometro();
            break;
          case 'B':
            preDefinidos();
            break;
          }
       break;
     /*
     case '#':
       Circuito();
       break;
    
      case 'D':
        Timelapse();
        break;
        */
   }  
}

and call that in every sub loop (menu)

May be like this:

void menuManual()
{
   lcd.setBrightness(25);
   lcd.selectLine(1);
   lcd.print("   Modo MANUAL  ");
   lcd.selectLine(2);
   lcd.print("A - Angulo Mobil");
   lcd.selectLine(3);
   lcd.print("B - PreDefinidos");
   lcd.selectLine(4);
   lcd.print("0 - Salir       ");    
   keyboard_request();
}

Simply put all your keyboad request code in keyboard_request(); and here we go 8)
This way you have only one routine to modify for each belongings. :smiley:

Also you may have a look on the depending ARDUINO help:
http://playground.arduino.cc//Main/InterfacingWithHardware#ui

Crossposting won't get you more answers.

:~

Im sorry for not posting the whole code, i thought it wouldn't be needed, also let me explain something.
I tried several options but all recalls the keyboard and does not separates instances or sequence of events,
i mean that if first menu is on the screen, it works just fine, but if i enter to the second menu to have
some other options, the options in the first menu are still available, its like an open window that
allows in every moment have all the options, and separating in functions is all i could think of
here is the complete code as it is, and also i tried to make a separated keyboard for separated instances

//Proyecto camara GoPro controlada desde una Moto
//Este programa pretende que comodamente desde un teclado
//se pueda tener acceso a mover un servo motor con una
//camara GoPro para tener varias tomas durante un viaje,
//el hacerlo asi permite que se puedan ver varios angulos
//sin tener la necesidad de parar a ajustar un nuevo angulo
//sino desde el manubrio poder presionar botones con posiciones
//prestablecidas para no preocuparse por eso.
//En otra parte se podra con un potenciometro generar una
//manipulacion del servo motor con solo girar la manecilla
//para que el servo llegue a esa posicion.
//Otra de las funciones mas importantes es el uso de un TimeLapse
//el cual se podra programar desde una posicion inicial
//hasta una final estableciendo el tiempo que debera el
//servo cumplir con la tarea.

// Librerias
#include <Servo.h>
#include <Keypad.h>
#include <SoftwareSerial.h>
#include <serLCD.h>

//Declaraciones pantalla LCD

int lcdp = 2;
serLCD lcd(lcdp);

//Declaraciones para el teclado

const byte fil = 4;
const byte col = 4;
char teclas[fil][col] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte filas[fil] = {11,10,9,8};
byte columnas[col] = {7,6,5,4};
Keypad TecladoM = Keypad (makeKeymap(teclas),filas,columnas,fil,col);

//Declaraciones para el Servo Motor y potenciometro
const int servo = 3 ; //Espero que este sea un PWM
const int pot = 0; //Entrada analoga 0
int val = 0; //Para guardar la lectura del Potencionmetro
Servo myServo; //llama a un objeto de Servo llamado myServo
//cada vez que quiera que el servo haga algo
//me refiero a myServo
void setup()
{
Serial.begin(9600); //esto es por si queiro ver que esta pasando
myServo.attach(servo);
MenuInicio();
}

//Esta funcion escribe en la pantalla el menu de Inicio

void MenuInicio()
{
lcd.clear();
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print("--Selecciona--");
lcd.selectLine(2);
lcd.print("* - Manual ");
lcd.selectLine(3);
lcd.print("# - Circuito ");
lcd.selectLine(4);
lcd.print("T - Timelapse");

}

//Esta Funcion es la que recibe comandos con los botones listos con los grados

void preDefinidos()
{/*
// char teclaV = Teclado.getKey();
//Lo primero que hace el programa es esperar tecla

if (int (teclaV) == '4')
{
myServo.write (0); //pone el servo en la posicion
Serial.println(0);
delay(15);
}
if (int (teclaV) == '7')
{
myServo.write (45); //pone el servo en la posicion
Serial.println(45);
delay(15);
}
if (int (teclaV) == '8')
{
myServo.write (90); //pone el servo en la posicion
Serial.println(90);
delay(15);
}
if (int (teclaV) == '9')
{
myServo.write (135); //pone el servo en la posicion
Serial.println(135);
delay(15);
}
if (int (teclaV) == '6')
{
myServo.write (180); //pone el servo en la posicion
Serial.println(180);
delay(15);
} */
}

//Esto es lo que se despliega durante el uso de la funcion Potenciometro

void desplieguePotenciometro()
{
lcd.clear();
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print(" Angulo Mobil ");
lcd.selectLine(2);
lcd.print("Angulo Actual");
lcd.setCursor(3,8);
lcd.print("Grados");
lcd.setCursor(4,5);
lcd.print("0 - Salir");
}

//Esta funcion mueve el potenciometro desplegando el angulo de giro

void potenciometro()
{/*
desplieguePotenciometro();
char teclaP = Teclado.getKey();
val = analogRead(pot); //leo la posicion del potenciometro
val = map(val,0,1023,0,180); //escala para el rango del servo, con grados
myServo.write (val); //pone el servo en la posicion
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print(val);
delay(15);
potenciometro();
if ((teclaP) == '0')
{
}*/
}

//Esta funcion es el menu manual

void menuManual()
{

//cada vez que quiera que el teclado manual haga algo
//me refiero a TecladoM
char b = TecladoM.getKey();

lcd.clear();
lcd.setBrightness(25);
lcd.selectLine(1);
lcd.print(" Modo MANUAL ");
lcd.selectLine(2);
lcd.print("A - Angulo Mobil");
lcd.selectLine(3);
lcd.print("B - PreDefinidos");
lcd.selectLine(4);
lcd.print("0 - Salir ");

switch (b)
{
case '0':
MenuInicio();
break;
case 'A':
desplieguePotenciometro();
break;
case 'B':
preDefinidos();
break;
}
}

//Esta funcion es para decidir a que parte del programa se dirige
// el usuario y en cada una de ellas definire una lectura de teclado
//independiente, es decir una variable local

void Principal()
{
Keypad TecladoP = Keypad (makeKeymap(teclas),filas,columnas,fil,col); //cada vez que quiera que el teclado principal haga algo
//me refiero a TecladoP
char a = TecladoP.getKey(); //Lo primero que hace el programa es esperar tecla

switch (a)
{
case '*':

menuManual();
break;

case '#':
desplieguePotenciometro();
break;

case 'D':
//Timelapse();
break;

}
}

//ESte es el ciclo infinito del Arduino

void loop()
{
Principal();
}


Also i dont really understand your code,

void keyboard_request() { // and again...and again
char tecla = keypad.getKey(); //Lo primero que hace el programa es esperar tecla

switch (tecla)
{
case '*':

what is this function??
How does it separates the instances?

void keyboard_request() { // and again...and again
char tecla = keypad.getKey(); //Lo primero que hace el programa es esperar tecla

thank you very much for the reply.

some other options, the options in the first menu are still available, its like an open window that
allows in every moment have all the options, and separating in functions is all i could think of

That's exactly what is happening, since each post-a-menu function is not a blocking function. You can either have a function like postMenuOneAndGetSelection() that blocks (does not return) until a valid key is pressed, or you can have a postMenuOne() function that simply puts some info on the LCD, sets a state, and returns. Then, the meaning of a keypress will depend on the state.

here is the complete code as it is

I'll read that after you read the sticky at the top of the forum and post your code correctly.

Fair enough, jajaja
With some time and experience i will get better, in the forum also, thanks for the corrections.
Im sorry for not posting the whole code, i thought it wouldn't be needed, also let me explain something.
I tried several options but all recalls the keyboard and does not separates instances or sequence of events,
i mean that if first menu is on the screen, it works just fine, but if i enter to the second menu to have
some other options, the options in the first menu are still available, its like an open window that
allows in every moment have all the options, and separating in functions is all i could think of
here is the complete code as it is, and also i tried to make a separated keyboard for separated instances

//Proyecto camara GoPro controlada desde una Moto
//Este programa pretende que comodamente desde un teclado
//se pueda tener acceso a mover un servo motor con una
//camara GoPro para tener varias tomas durante un viaje,
//el hacerlo asi permite que se puedan ver varios angulos
//sin tener la necesidad de parar a ajustar un nuevo angulo
//sino desde el manubrio poder presionar botones con posiciones
//prestablecidas para no preocuparse por eso.
//En otra parte se podra con un potenciometro generar una 
//manipulacion del servo motor con solo girar la manecilla
//para que el servo llegue a esa posicion.
//Otra de las funciones mas importantes es el uso de un TimeLapse 
//el cual se podra programar desde una posicion inicial
//hasta una final estableciendo el tiempo que debera el
//servo cumplir con la tarea.


// Librerias
#include <Servo.h>
#include <Keypad.h>
#include <SoftwareSerial.h>
#include <serLCD.h>

//Declaraciones pantalla LCD

int lcdp = 2;
serLCD lcd(lcdp);

//Declaraciones para el teclado

const byte fil = 4; 
const byte col = 4;
char teclas[fil][col] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte filas[fil] = {11,10,9,8};
byte columnas[col] = {7,6,5,4}; 
Keypad TecladoM = Keypad (makeKeymap(teclas),filas,columnas,fil,col);

//Declaraciones para el Servo Motor y potenciometro
const int servo = 3 ;                                                //Espero que este sea un PWM
const int pot = 0;                                                    //Entrada analoga 0
int val = 0;                                                         //Para guardar la lectura del Potencionmetro
Servo myServo;                                                        //llama a un objeto de Servo llamado myServo
                                                                      //cada vez que quiera que el servo haga algo
                                                                      //me refiero a myServo
void setup()
{
  Serial.begin(9600);                                                //esto es por si queiro ver que esta pasando
  myServo.attach(servo);
  MenuInicio();
}

//Esta funcion escribe en la pantalla el menu de Inicio

void MenuInicio()
{
   lcd.clear();
   lcd.setBrightness(25);
   lcd.selectLine(1);
   lcd.print("_--Selecciona--_");
   lcd.selectLine(2);
   lcd.print("* - Manual      ");
   lcd.selectLine(3);   
   lcd.print("# - Circuito    ");
   lcd.selectLine(4);
   lcd.print("T - Timelapse");
   
}

//Esta Funcion es la que recibe comandos con los botones listos con los grados

void preDefinidos()
{/*
   // char teclaV = Teclado.getKey(); 
    //Lo primero que hace el programa es esperar tecla
 
    if (int (teclaV) == '4')
    {
      myServo.write (0);            //pone el servo en la posicion
      Serial.println(0);
      delay(15);
    } 
    if (int (teclaV) == '7')
    {
      myServo.write (45);            //pone el servo en la posicion
      Serial.println(45);
      delay(15);
    } 
    if (int (teclaV) == '8')
    {
      myServo.write (90);            //pone el servo en la posicion
      Serial.println(90);
      delay(15);
    } 
    if (int (teclaV) == '9')
    {
      myServo.write (135);            //pone el servo en la posicion
      Serial.println(135);
      delay(15);
    } 
    if (int (teclaV) == '6')
    {
      myServo.write (180);            //pone el servo en la posicion
      Serial.println(180);
      delay(15);
    } */
}

//Esto es lo que se despliega durante el uso de la funcion Potenciometro

void desplieguePotenciometro()
{
   lcd.clear(); 
   lcd.setBrightness(25);
   lcd.selectLine(1);
   lcd.print("  Angulo Mobil  ");
   lcd.selectLine(2);
   lcd.print("Angulo Actual");
   lcd.setCursor(3,8);
   lcd.print("Grados"); 
   lcd.setCursor(4,5);
   lcd.print("0 - Salir"); 
}


//Esta funcion mueve el potenciometro desplegando el angulo de giro

void potenciometro()
{/*
  desplieguePotenciometro();
  char teclaP = Teclado.getKey();
  val = analogRead(pot);          //leo la posicion del potenciometro
  val = map(val,0,1023,0,180);    //escala para el rango del servo, con grados
  myServo.write (val);             //pone el servo en la posicion
  lcd.setBrightness(25);
  lcd.selectLine(1);
  lcd.print(val);
  delay(15);
  potenciometro();
   if ((teclaP) == '0')
  {
  }*/
}

//Esta funcion es el menu manual

void menuManual()
{

                                                                      
     //cada vez que quiera que el teclado manual haga algo
                                                                            //me refiero a TecladoM
   char b = TecladoM.getKey();
   
   lcd.clear();
   lcd.setBrightness(25);
   lcd.selectLine(1);
   lcd.print("   Modo MANUAL  ");
   lcd.selectLine(2);
   lcd.print("A - Angulo Mobil");
   lcd.selectLine(3);
   lcd.print("B - PreDefinidos");
   lcd.selectLine(4);
   lcd.print("0 - Salir       "); 
   
        switch (b)
        {
          case '0':
            MenuInicio();
            break;
          case 'A':
            desplieguePotenciometro();
            break;
          case 'B':
            preDefinidos();
            break;
          }
}

//Esta funcion es para decidir a que parte del programa se dirige
// el usuario y en cada una de ellas definire una lectura de teclado 
//independiente, es decir una variable local

void Principal()
{
  Keypad TecladoP = Keypad (makeKeymap(teclas),filas,columnas,fil,col);    //cada vez que quiera que el teclado principal haga algo
                                                            //me refiero a TecladoP
   char a = TecladoP.getKey();                                  //Lo primero que hace el programa es esperar tecla
 
   switch (a) 
   {
     case '*':
     
       menuManual();
       break;
       
     case '#':
       desplieguePotenciometro();
       break;
    
      case 'D':
        //Timelapse();
        break;
        
   }  
}

//ESte es el ciclo infinito del Arduino

void loop()
{
  Principal();
}

Also i dont really understand your code,

void keyboard_request() {   // and again...and again
char tecla = keypad.getKey();                                     //Lo primero que hace el programa es esperar tecla
  
   switch (tecla) 
   {
     case '*':

what is this function??
How does it separates the instances?

void keyboard_request() {   // and again...and again
char tecla = keypad.getKey();                                     //Lo primero que hace el programa es esperar tecla

thank you very much for the reply.

but if i enter to the second menu to have
some other options, the options in the first menu are still available

That is because you don't make the first ones unavailable. You need a state variable. The states might be as simple as 1 (menu 1 displayed), 2 (menu 2 displayed), 2.1 (menu 2, submenu 1 displayed), etc.

When a key is pressed, the meaning of 7, for instance, depends on the state variable's value.

I don't think that you get this point.

What? :astonished:
i did not understand that answer, please mr paul, i dont get it!

The states might be as simple as 1 (menu 1 displayed), 2 (menu 2 displayed), 2.1 (menu 2, submenu 1 displayed), etc.

1(menu1 displayed)
1() is the function
menu1 is the function that displays the second menu, or menu1 displayed is the whole state?

can you insert a function as a state for calling the other funcion?

1(menu1 displayed) is like inside the switch structure case?

for example
this will eliminate the following.

menu 1

a - say hi
b - say goodbye
c - do nothing and power off

menu 2

a - say, hi, how are you doing?
b - say, hi good morning.

by the moment
if i press "a" in menu1

i jump to menu 2

but if i press "a" in menu 2 i will jump to menu 2 again and the choices in menu 2 are not working
and i can press "c" and the system will power off.

I know that you understand this explanation.

i don´t understand where do i need to start and stop the separation of choices.
how?

the character reading with " char a = TecladoP.getKey(); "

is in any function and the window now is opened, how do i close it for this menu and open it for the next?

i dont get it!

int menuDisplayed = 0;

Use this to keep track of which menu is displayed.

void showMenuOne()
{
   // some stuff to write to the LCD

   menuDisplayed = 1;
}

Show a menu. Record which one is shown.

Now see if a key is pressed. If so, do what it means based on the menu being displayed:

char key = keypad.getKey();
if(key != NO_KEY)
{
   // a key was pressed
   switch(menuState)
   {
      case 1:
         switch(key)
         {
             case '1':
               // do whatever item 1 on menu 1 means
               break;
             case '2':
               // do whatever item 2 on menu 1 means
               break;
             case '3':
               // do whatever item 3 on menu 1 means
               break;
         }
         break;
      case 2:
         switch(key)
         {
             case '1':
               // do whatever item 1 on menu 2 means
               break;
             case '2':
               // do whatever item 2 on menu 2 means
               break;
             case '3':
               // do whatever item 3 on menu 2 means
               break;
         }
         break;
      case 3:
         switch(key)
         {
             case '1':
               // do whatever item 1 on menu 3 means
               break;
             case '2':
               // do whatever item 2 on menu 3 means
               break;
             case '3':
               // do whatever item 3 on menu 3 means
               break;
         }
         break;
   }
}

Oh, thank you!
I will make the corrections and implementations, i will let you know the result of this little project.
Regards.