Menu e sottomenu con keypad e lcd a 2 righe

Ho scritto la base e scopiazzato qualcosa per creare un menu e sottomenu con <Keypad.h> e <LiquidCrystal.h> per intenderci quello a 2 righe.
La parte display non è inclusa. Uso la seriale per vedere i risultati.

Il listato lo ritenete corretto?

È semplificative in qualche modo secondo voi?

È solo una bozza, ma mi piacerebbe renderlo più semplificato, anche se questo è di facile lettura.
Soprattutto vorrei che non sia avido di memoria.

Il menu è la pressione del tasto 0 zero
I sottomenu vanno da 1 a 9

La parte che rimanda al sottomenu deve rimanere nel ciclo fino a che premo il tasto 0 zero.

Abbiate pietà sono alle primissime armi con il C++ e purtroppo non ho molto tempo per approfondire il linguaggio.
Per età e acciacchi vari.

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char Keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
/*  Tabella conversione Hex a Dec per i tasti premuti
0 48
1 49
2 50
3 51
4 52
5 53
6 54
7 55
8 56
9 57
A 65
B 66
C 67
D 68
# 35
* 42
*/
int MenuOption = 48;
byte rowPins[ROWS] = {36, 38, 40, 42};          //connect to the row pinouts of the keypad
byte colPins[COLS] = {44, 46, 48, 50};          //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(Keys), rowPins, colPins, ROWS, COLS); 

void setup()
{  
  Serial.begin(9600);
}
  
void loop()
{
  ImpostazioniMenu();   
}

void ImpostazioniMenu()
{

  char customKey = customKeypad.getKey(); 
   int numero =  customKey;
  if (customKey)
  {
    Serial.print(customKey);
    Serial.print (" ");
    Serial.println(numero);
    
     
    if ((customKey) == 49) // tasto 1
    { 
     Menu1();
    }      
    if ((customKey) == 50)
    {
     Menu2();
    }
    if ((customKey) == 51)
    {
     Menu3();
    }
    if ((customKey) == 52)
    {
     Menu4();
    }
    if ((customKey) == 53)
    {
     Menu5();
    }
    if ((customKey) == 54)
    {
     Menu6();
    }
    if ((customKey) == 55)
    {
     Menu7();
    }
    if ((customKey) == 56)
    {
     Menu8();
    }
    if ((customKey) == 57)
    {
     Menu9();
    }
    if ((customKey) == 48) // tasto 0
    {
     return;
    }
    
  } 
}



void Menu1()
{
Serial.println("Menu 1");

 for (int i = 0;i <= 99;i++){
 Serial.println(i);//il blocco di istruzioni verrà eseguito 100 volte

 
 char customKey = customKeypad.getKey();
 int numero =  customKey;
  if (customKey)
  {
    Serial.print(customKey);
    Serial.print (" ");
    Serial.println(numero);
  }
  if ((customKey) == 48)
    {
     i = 99;
     Serial.println ("Esco dal ciclo e vado a Menu 0"); 
     Serial.println(i);    
     return;
    }
   delay (250);}
}
void Menu2()
{
Serial.println("Menu 2"); 
 
}
void Menu3()
{
Serial.println("Menu 3"); 
 
}

void Menu4()
{
Serial.println("Menu 4"); 
 
}

void Menu5()
{
Serial.println("Menu 5"); 
 
}

void Menu6()
{
Serial.println("Menu 6"); 
 
}

void Menu7()
{
Serial.println("Menu 7"); 
 
}
void Menu8()
{
Serial.println("Menu 8"); 
 
}

void Menu9()
{
Serial.println("Menu 9"); 
 
}

Ciao! Nei vari controlli con if() dove valuti il carattere premuto nel keypad, puoi usare direttamente i caratteri invece del loro codice ascii, if(carattere==65) è uguale a if(carattere=='A').

Quando entri nei vari menu, menu1 ecc.., io creerei un ciclo infinito while(1), all'interno del ciclo leggo il carattere premuto per fare altre azioni o per uscire dal menu, quando sei in un ciclo devi considerare anche il NO_KEY quando il tasto non è premuto.

io creerei un ciclo infinito while(1)

dipende se bloccare il programma in quel punto può causare problemi...in ogni caso ci vuole una condizione di uscita tipo timeout...

farà anche altro il loop, a regime, quindi perchè bloccarlo con un while(true)?
io queste cose le eviterei sempre anche solo come forma mentale :wink:

Secondo voi è un sistema elegante per risolvere il problema oppure ne esiste uno più lineare e sintetico.
Grazie comunque per chi risponde.
Eventualmente mi potete indicare un codice o un link dove attingere uno schema già impostato?
Ho cercato in rete ma non ho trovato un caso simile.

Premetto che il concetto di "eleganza" è un concetto soggettivo, poi, per ottimizzare qualcosa bosognerebbe prima averlo!
Non penso che il "cosa deve fare questo menù" sia poi così secondario per poter decidere, viste le indicazioni ricevute, per quanto scarne.
Ad es. bloccare tutto al primo ingresso nel menù finchè non si sceglie la voce del sottomenù potrebbe essere non accettabile come funzionamento, se nel frattempo il software deve fare delle operazioni continue...

Qui, poi, ammetto la mia ignoranza (è così vasta che mi è difficile da nascondere :wink: ): non so se col "C" di Arduino è possibile definire puntatori a funzioni oppure richiamare funzioni dinamicamente in qualche modo.
In caso affermativo ci sarebbero alcune possibilità in più.

EDIT: si dovrebbe poter fare, in effetti ci sono funzioni di callback in giro quà e là.
Quindi si può creare un array di array, il primo rappresenta il primo livello del menù ogni elemento conterrà un array di puntatori a funzioni, cioè le funzioni da richiamare per le varie voci dei sottomenù.
E' alla moda? o sufficientemente elegante? :wink:

@maubarzi in arduino è possibile usare puntatori a funzione, io li ho usati senza problemi.

Io uso un ciclo while(1) perché invece di mettere una condizione con richiamo a funzioni, preferisco inserire la condizione di uscita all’interno del corpo del while, in questo caso leggo il carattere premuto se corrisponde, break, preferisco farlo nel corpo del while invece che nella condizione “quindi non è un ciclo infinito”. :slight_smile:

Non ho avuto esigenze di avere un programma che non si potesse fermare per qualche secondo, quindi in caso di menu, ho sempre creato un ciclo che mi facesse rimanere all’interno del menu fino alla condizione di uscita, e al suo interno leggere di continuo gli input da pulsanti.

maubarzi:
Qui, poi, ammetto la mia ignoranza (è così vasta che mi è difficile da nascondere :wink: ): non so se col "C" di Arduino è possibile definire puntatori a funzioni oppure richiamare funzioni dinamicamente in qualche modo.

È cosa normale in 'C', ampiamente descritta nel capitolo 5.11 del Kernighan & Ritchie che si chiama proprio "Pointers to Functions", quindi ...
... perché mai non dovrebbe essere supportata da gcc (compilatore usato dal IDE di Arduino)? ? ? :o :o :o

Guglielmo

@patdepri cosa deve fare il programma e i menu? Entrando nei menu il programma può sospendere quello che fa nel tempo che sei nei menu? Esempio entro nel menu per 20 secondi, in quel tempo sospendo e mi occupo solo del menu...

gpb01:
... perché mai non dovrebbe essere supportata da gcc (compilatore usato dal IDE di Arduino)? ? ? :o :o :o

La risposta è nella mia premessa: "Qui, poi, ammetto la mia ignoranza" :wink:
Io mi sto affacciando al C grazie ad Arduino, quindi sono solo un paio di mesi o poco più :-[ ci sta la mia ignoranza :stuck_out_tongue:

maubarzi:
Io mi sto affacciando al C grazie ad Arduino ....

... ma il Kernighan & Ritchie, ovvero la Bibbia del 'C', te lo sei preso (e studiato) ? ? ? :smiley:

Guglielmo

Assolutamente no :sunglasses: al momento sto facendo esplorazione mirata con il lanternino.
Per hobby al momento può bastare, e poi voglio testare una mia convinzione, se sai programmare, il linguaggio è secondario :wink: ovvio che devo studiarmi gli aspetti specifici quando mi servono ma so già dove andare a parare (fino a prova contraria sotto verifica)

maubarzi:
Assolutamente no :sunglasses: al momento sto facendo esplorazione mirata con il lanternino ...

... NON bene !

Guglielmo

Concordo in linea di principio, ma io sto facendo uno studio scientifico sulla mia convinzione :wink:
Al momento mi sta andando dritta e sto, quindi, confermando la mia idea :wink:
Comunque, tu intendi questo?

Me lo sono procurato, prima o poi lo leggerò :sleeping:

maubarzi:
Comunque, tu intendi questo?

Si, certo ... il Sacro Testo :smiley:

Come scriveva sempre Astrobeed ... "Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante." :slight_smile:

Guglielmo

Quella di Astro è una citazione da “Il vero programmatore”, famoso testo le cui origini sono perse nei meandri di Internet :).

Tornando in-topic, io ho usato un approccio diverso, in stile C++ (con classi astratte e ereditarietà). So che molti storceranno il naso, ma in verità mi ha permesso di scrivere codice semplice, leggibile e compatto, molto efficiente dal punto di vista dell’occupazione di flash.

SukkoPera:
Quella di Astro è una citazione da “Il vero programmatore”, famoso testo le cui origini sono perse nei meandri di Internet :).

Si, si, lo diceva sempre :smiley: :smiley: :smiley: Io avevo anche recuperato il testo … lo metto in allegato :grin:

SukkoPera:
Tornando in-topic, io ho usato un approccio diverso, in stile C++ (con classi astratte e ereditarietà). So che molti storceranno il naso

… esatto :smiley: :smiley: :smiley: … sai che sono un purista del ‘C’ :grin:

Guglielmo

Il vero programmatore.zip (8.92 KB)

Off topic

Penso che il K&R ha un grande valore perché scritto dagli autori del linguaggio, ma di fatto non è il libro di testo che usano in ambiente scolastico.
Imparare il C senza testo di riferimento? Secondo un mio parere “è solo un opinione :)” dipende di che livello di conoscenza e da che testo.
Se abbiamo un libro di introduzione al linguaggio “io ho imparato da libri del genere” se ne può fare a meno e basarsi su quello che si trova in internet.

Devi avere anche un certo background di conoscenze.
Io non ho mai lavorato in C ma lo conosco.
So come è strutturato e cosa può fare.
Quindi, ora che ho iniziato a sbatterci la testa, so già cosa posso ottenere e vado in cerca della sintassi giusta.
Ho una sufficiente infarinatura di base per potermici raccapezzolare anche se non ci ho mai veramente lavorato.
Poi, per diventarne un guru ne dovrò mangiare di pastasciutta, ma per il livello hobbistico...
Se mi servirà fare il grande passo mi leggerò il K&R che mi sono accaparrato.

Mi potrei definire l'anello mancante tra il "mangia-quiche" e il "Vero Programmatore" :wink: polarizzato verso il primo perchè il secondo è veramente inarrivabile, mi sa ormai quasi del tutto estinto.

SukkoPera:
io ho usato un approccio diverso[/iurl], in stile C++ (con classi astratte e ereditarietà).

anche io, per deformazione professionale, sono tentato da approcci di questo tipo, poi magari imbastardati da modi di fare le cose più C oriented.
La cosa che mi stuzzica di più del C e che lo distingue dal mondo cui sono più abituato, poi, sono i puntatori.
Quindi tenderei a vedere se possono dare una mano a risolvere i problemi.

torn24:
...e basarsi su quello che si trova in internet.

sempre che si sappia separare il grano dalla pula.
Ho trovato gente che sosteneva che uno script per linux non funzionava perchè era stata tolta una riga con scritto solo "ls"... e suggeriva di riprovare dopo avercela rimessa :sob:

Se ricordo bene il K&R è più una guida per creare il compilatore, che per programmare
Letta nell'introduzione di non ricordo se la prima
o seconda edizione, italiana o inglese
Tra l'altro non trovo più la mia copia della prima edizione italiana.... Troppi traslochi