Tutorial: come gestire menu e display LCD con Arduino

Lavorando al mio MIDI ribbon controller ho avuto la necessità di utilizzare un menu per poter configurare agevolmente i vari parametri, ma in giro per la rete ho trovato solo indicazioni su come gestire un menu, come gestire un display lcd, ma poco materiale relativo a come mettere insieme le due cose. Comunque grazie alla libreria Menubackend di Alexander Brevig sono riuscito a creare il menu che desideravo.Prima di tutto ho scaricato la versione 1.4 della libreria di Alexander Brevig e l'ho modificata leggermente aggiungendo, alla riga 195 del file MenuBackend.h subito prima della riga con scritto "private:", questo metodo:
    void toRoot() {
        setCurrent( &getRoot() );
    }
Tale metodo mi serve per poter tornare agevolmente alla radice del menu.

Nel mio sketch ho quindi importato la libreria Menubackend così modificata e la libreria LiquidCrystal che è inclusa nell'IDE di Arduino.

La libreria MenuBackend permette di gestire un menu in maniera molto flessibile pensando ai collegamenti tra voci di menu come a degli incroci. Per creare la sruttura del menu si utilizzano dei metodi come addRight, addLeft, Add e AddBefore per aggiungere le varie voci a destra, sinistra, sotto o sopra le altre voci. Per navigare tra una voce e l'altra si utilizzano metodi intuitivi come moveLeft, moveRight, moveUp e moveDown. Nel mio esempio creo una struttura come la seguente.

Main
  |
 Item1-------------------------------Item2----------------------------------------------------Item3
  |                                   |
Item1SubItem1-----Item1SubItem2     Item2SubItem1------Item2SubItem2------Item2SubItem3

MenuBackend innesca un evento ogni volta che cambia la voce di menu corrente e quindi l'ho sfruttato per "stampare" sul display lcd la voce del menu corrente. Inoltre viene innescato un altro evento quando viene selezionata una voce tramite il metodo "use". Tale evento potrebbe essere sfruttato per esempio per modificare lo status dell'applicazione, ma in questo caso mi sono limitato a stampare sul display la frase "You used" seguita dal nome della voce di menu utilizzata.
Per navigare nel menu ho usato 4 pulsanti (Left, Right, Esc ed Enter). Se la voce corrente ha una sottovoce premendo il tasto Enter si "scende" su di essa, altrimenti viene innescato l'evento used. Con i tasti Left e Right si naviga tra le voci dello stesso "livello", mentre con il tasto Esc si ritorna alla voce principale.

Per realizzare il progetto avete bisogno dei seguenti componenti:

  • Scheda Arduino compatibile (dovrebbe andare bene anche la vecchia Arduino Diecimila)
  • un display LCD compatibile Hitachi HD44780
  • 4 pulsanti
  • 4 resistenze da 10k

Opzionalmente per facilitarvi le connessioni potete sfruttare una scheda per i prototipi (protoshield). Io ne ho usata una della Nuelectronics.

Lo schema elettrico è molto semplice. Ci sono 12 dei 16 pin del display lcd collegati alla scheda Arduino: 6 sono pin di input, 2 di alimentazione, 2 servono ad alimentare la luce interna, 1 per abilitare la scrittura (viene collegato al ground) e 1 per regolare il contrasto (anche questo a ground per avere sempre il massimo contrasto). I 4 pulsanti sono collegati a 4 pin di input di Arduino, a loro volta collegati a ground tramite resistenze da 10k. L'altro capo dei pulsanti è collegato ai 5v di Arduino.

Gli schemi sono realizzati con Fritzing

Per collegare il display lcd ad Arduino ho prima saldato due strip da 6 pin di tipo maschio sullo shield e poi, grazie a un'idea datami da Emanuel nei commenti di un altro post, ho sfruttato un vecchio cavo parallelo per hard disk IDE.

Aggionramento: Come mi ha fatto notare Liudr per ragioni di sicurezza è meglio usare un cavo ide molto vecchio da 40 cavi invece del cavo a 80 cavi che ho utilizzato in queste foto.

Credo che questo tipo di struttura anche se molto semplice, visto che sfrutta una sola riga del display, possa essere utile in molte situazioni di gestione di menu tramite display lcd con Arduino, e comunque può essere utilizzata come base per altre modifiche.

Puoi scaricare il codice sorgente qui.

/*
    Copyright Giuseppe Di Cillo (www.coagula.org)
    Contact: dicillo@coagula.org
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
    void toRoot() {
        setCurrent( &getRoot() );
    }
*/
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

const int buttonPinLeft = 8;      // pin for the Up button
const int buttonPinRight = 9;    // pin for the Down button
const int buttonPinEsc = 10;     // pin for the Esc button
const int buttonPinEnter = 11;   // pin for the Enter button

int lastButtonPushed = 0;

int lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int lastButtonRightState = LOW;   // the previous reading from the Right input pin


long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
long lastEscDebounceTime = 0;  // the last time the output pin was toggled
long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
long lastRightDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 500;    // the debounce time

// LiquidCrystal display with:
// rs on pin 2
// rw on PIN3
// enable on pin 6
// d4, d5, d6, d7 on pins 4, 5, 6, 7
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");


void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
 
  lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  lcd.setCursor(0,0); 
  lcd.print("www.coagula.org");

}  // setup()...


void loop()
{

  readButtons();  //I splitted button reading and navigation in two procedures because
  navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)
                 
} //loop()...


void menuChanged(MenuChangeEvent changed){
 
  MenuItem newMenuItem=changed.to; //get the destination menu
 
  lcd.setCursor(0,1); //set the start position for lcd printing to the second row
 
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("Main Menu       ");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("Item1           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("Item1SubItem1");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("Item1SubItem2   ");
  }else if(newMenuItem.getName()=="Item2"){
      lcd.print("Item2           ");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      lcd.print("Item2SubItem1   ");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
      lcd.print("Item2SubItem2   ");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      lcd.print("Item2SubItem3   ");
  }else if(newMenuItem.getName()=="Item3"){
      lcd.print("Item3           ");
  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0); 
  lcd.print("You used        ");
  lcd.setCursor(0,1);
  lcd.print(used.item.getName());
  delay(3000);  //delay to allow message reading
  lcd.setCursor(0,0); 
  lcd.print("www.coagula.org");
  menu.toRoot();  //back to Main
}


void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter input pin
  int buttonEscState=LOW;             // the current reading from the input pin
  int buttonLeftState=LOW;             // the current reading from the input pin
  int buttonRightState=LOW;             // the current reading from the input pin

  //Enter button
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEnter);

                  // check to see if you just pressed the enter button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise: 
               
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEnterState) {
                    // reset the debouncing timer
                    lastEnterDebounceTime = millis();
                  }
                 
                  if ((millis() - lastEnterDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEnterState=reading;
                    lastEnterDebounceTime=millis();
                  }
                 
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEnterState = reading;
                 

    //Esc button              
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEsc);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise: 
               
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEscState) {
                    // reset the debouncing timer
                    lastEscDebounceTime = millis();
                  }
                 
                  if ((millis() - lastEscDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEscState = reading;
                    lastEscDebounceTime=millis();
                  }
                 
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEscState = reading;
                 
                    
   //Down button              
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinRight);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise: 
               
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonRightState) {
                    // reset the debouncing timer
                    lastRightDebounceTime = millis();
                  }
                 
                  if ((millis() - lastRightDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonRightState = reading;
                   lastRightDebounceTime =millis();
                  }
                 
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonRightState = reading;                 
                 
                 
    //Up button              
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinLeft);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise: 
               
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonLeftState) {
                    // reset the debouncing timer
                    lastLeftDebounceTime = millis();
                  }
                 
                  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonLeftState = reading;
                    lastLeftDebounceTime=millis();;
                  }
                 
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonLeftState = reading; 

                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;

                  }else if(buttonEscState==HIGH){
                    lastButtonPushed=buttonPinEsc;

                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

                  }else if(buttonLeftState==HIGH){
                    lastButtonPushed=buttonPinLeft;

                  }else{
                    lastButtonPushed=0;
                  }                 
}

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();
 
  switch (lastButtonPushed){
    case buttonPinEnter:
      if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
        menu.use();
      }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
        menu.moveDown();
       }
      break;
    case buttonPinEsc:
      menu.toRoot();  //back to main
      break;
    case buttonPinRight:
      menu.moveRight();
      break;     
    case buttonPinLeft:
      menu.moveLeft();
      break;     
  }
 
  lastButtonPushed=0; //reset the lastButtonPushed variable
}

 


Licenza Creative Commons
Tutorial: come gestire menu e display LCD con Arduino by Giuseppe Di Cillo - Coagula.org is licensed under a Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported License.

Commenti(27)

Scusate io vorrei progettare un controller arduino x il mio acquario marino, qualcuno potrebbe inviarmi qualche sketch con molta gentilezza? Grazie.

Ciao, nessun ha un progetto in cui ha usato questo codice per esempio per impostare dei limiti o dei diversi metodi di misura tipo gradi centrigradi o ecc ecc ?

Ciao, intanto complimenti. Sto realizzando un controllo temperature e gestione pompe di circolazione di termocamino,puffer,caldaia e pannello solare, più un parte meteo, tutto tramite menu. ho un problema con menu Used: ho cominciato collegando un sensore dht11 per temperatura e umidità e tutto procede ma quando arrivo a menu Used legge il sensore ma crea una "fotografia" della lettura nonostante il delay del sensore o il delay che ho provato ad aggiungere. non va in loop del Item selezionato da use. se tengo premuto il tasto Enter invece rimane in lettura continua perchè ho tolto il menu.toRoot. come posso fare per mantenere high il pin enter solo in menu Used?
e forse colpa del debounce? grazie anticipatamente.

è l'unico che mi funziona perfettamente !!

//==========================================================================
// Author : CYTRON TECHNOLOGIES SDN BHD
// Project : Arduino Duemilanove
// Project description : Project_1: "Hello World" and utilize switch
//==========================================================================

#include

/*
The circuit:
* LCD RS pin to digital pin 8
* LCD Enable pin to digital pin 9
* LCD D4 pin to digital pin 4
* LCD D5 pin to digital pin 5
* LCD D6 pin to digital pin 6
* LCD D7 pin to digital pin 7
* LCD R/W pin to ground
*/

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int analogPin = A0;
int adc_key_old;
int adc_key_in;
int NUM_KEYS = 5;
int key=-1;
int adc_key_val[5] ={30, 150, 360, 535, 760 };

char msgs[5][15] = {"Right Key OK ",
"Up Key OK ",
"Down Key OK ",
"Left Key OK ",
"Select Key OK"};

/*******************************************************************************
* PRIVATE FUNCTION: setup()
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Define of I/O pin as Input or Output
*
*******************************************************************************/
// The setup() method runs once, when the sketch starts
void setup ()
{
lcd.begin(16, 2); // set the lcd dimension
lcd.clear(); // LCD screen clear
lcd.print(" CYTRON TECH."); // display the text
lcd.setCursor(0,1); // set lcd.setCursor (column,row)
lcd.print(" Eg. LCD Shield");
delay(3000); // delay for 3000ms
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Hello World");
lcd.setCursor(0,1);
lcd.print("Pls press any");
adc_key_old = analogRead(analogPin); // store the unpress key value
}

/*******************************************************************************
* PRIVATE FUNCTION: loop()
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Non-Stop looping
*
*******************************************************************************/
void loop()
{
adc_key_in = analogRead(analogPin); // read ADC value
adc_key_in = get_key(adc_key_in);
lcd.setCursor(0, 1);
lcd.print(msgs[adc_key_in]); //display message key
}

/*******************************************************************************
* PRIVATE FUNCTION: get_key
*
* PARAMETERS:
* ~ integer
*
* RETURN:
* ~ unsigned int input
*
* DESCRIPTIONS:
* convert the ADC value to number between 0 to 4
*
*******************************************************************************/
int get_key(unsigned int input)
{
int k;

for (k = 0; k < NUM_KEYS; k++)
{
if (input < adc_key_val[k])
{

return k;
}
}

if (k >= NUM_KEYS)
k = -1; // No valid key pressed

return k;
}

Ciao,
Complimenti bella spiegazione !
Come walter ho però il problema che vorrei usare dei pulsanti collegati in analogico (ho un LCD Keypad Shield DF robotics già bella pronta), ma .... sono alle prime armi ... non è che hai qualche dritta per fare la sostituzione ? allego nel prossimo messaggio l'unico progetto che ho trovato funzionante pel la shield in questione.
Grazie
Sergo

Purtroppo non posso esserti d'aiuto.

..... ottimo progetto, complimenti.
Ho caricato il tutto e dalle prove fatte tutto gira, ora la mia domanda forse stupida è,,
quali righe di codice e dove inserirle per far si che alla fine di ogni menu si possa far fare un azione diversa.?
Ad esempio accendere il Led1 o il Led2 ....
Grazie e spero che qualcuno mi illumini sulla soluzione ....

Vedi risposte precedenti ;-) Magari qualche altro utente potrebbe postare del codice per fare cose simili.

Ciao Giuseppe
complimenti per il progetto che oltre ad essere interessante tecnicamente è anche a mio avviso molto utile,
premetto che sono un principiante del "mondo arduino" ma nonostante questo spero siano ugualmente graditi i complimenti di un esordiente.
Vado alla richiesta di aiuto:
vorrei innescare un processo di cambio di stato di un pin di arduino da Basso ad Alto che adeguatamente collegato elettricamente mi faccia accendere una "Led" al momento che dal menu arrivi a confermare il menu "Item1SubItem2" , a questo punto nel menu del Display sia a conferma dell'inizio processo sia se in un secondo momento di controllo dovrà esserci indicato "Item1SubItem2 STATO ON", ovviamente quando si riconferma lo stesso menu avverrà il processo opposto, cioè "Item1SubItem2 STATO OFF".
In sostanza un menu che attivi e disattivi uno stato di un pin e mantenga lo stato stesso del pin oltre che tenere in memoria lo stato e quindi visualizzarlo sul Display.
Se non ti chiedessi troppo qualora fossi disposto ad aiutarmi, ti chiederei di scrivermi Cosa e Dove modificare il tuo codice.
grazie in anticipo.

Vale la risposta data al commento precedente: non c'è una risposta univoca ma in genrale nell'evento menuUsed potresti eseguire delle operazioni a seconda del menu usato. Purtroppo, almeno fino a dicembre, non credo di trovare il tempo per pubblicare altri post di approfondimento su questo argomento.

scusate la mia super gnoranza, ma dov'è che inserisco le funzioni per ogni voce del menu?

Non esiste una risposta univoca, dipende da quello che ti serve. PEr esempio potresti nell'evento menuUsed potresti eseguire delle operazioni a seconda del menu usato.

Ciao. Come si potrebbe tornare al menu principale durante l'utilizzo di un sottomenu?
Ti ringrazio anticipatamente.

menu.toRoot();

Ciao.
Ho caricato il tuo codice sulla scheda e quando provo a selezionare i vari menu va avanti da solo, non permettendomi di selezionarli. Esempio: seleziono il primo menu e invece di fermarsi sul primo sottomenu va direttamente al secondo sottomenu, come se stessi tenendo premuto il tasto down.
Aspetto una risposta. Grazie in anticipo.

Mi vien da pensare che ci sia qualche problema sulle connessioni del pulsante. Hai verificato se ci sono corti?

Sì, era lì il problema. Grazie della risposta.,

Ciao grazie del grande progetto che hai realizzato !
è veramente un gran bel progetto, il mio problema è che non riesco a capire qual'è la stringa che dice che nel menu di ultimo livello non deve andare a leggere più NavigateMenus ma menuUsed in quanto grazie a MenuUsed dovrei gestire l'accensione di varie luci.
aspetto una tua illuminazione grazie

NavigateMenus viene sempre richiamato: è proprio lì che viene verificato se eseguire il metodo "moveDown" oppure il metodo "use". Questultimo innesca l'evento MenuUsed.

if(!(currentMenu.moveDown())){ //if the current menu has a child and has been pressed enter then menu navigate to item below
menu.use();
}else{ //otherwise, if menu has no child and has been pressed enter the current menu is used
menu.moveDown();
}

Ottimo! Oggi me lo sono studiato un poco. Assemblato e funziona. Solo che mi trovo in difficoltà nel gestire l'evento del menù. Ovvero se mi trovo in questa situazione:

Menù-----Primo (Sottomenù1, Sottomenù2)-------Secondo (Sottomenù 1, Sottomenù2). Se ad esempio in Primo.sottomenù1 voglio mettere un numero con la possibilità di essere modificato e salvato come potrei fare?
Grazie!

Puoi dare un'occhiata al post http://www.coagula.org/content/it/pages/coagula-midi-ribbon-controller-20-2 e cerca nel codice la parte dove gestisco i settings.

Grazie per la risposta. E' abbastanza complesso, in quanto non sto facendo un progetto simile, ma un'altra cosa, ovvero un carrello dolly per reflex. Praticamente ho creato il menù, con le varie voci, e mi pare di capire che posso gestire dalla classe menuUsed e richiamare navigatesMenus nel loop giusto?
Grazie!

Più o meno esatto. NavigateMenus serve per gestire i pulsanti per navigare attraverso il menu.
Nel loop puoi notare che c'è uno switch che fa si che navigateMenus venga richiamato solo in alcuni stati. Se premi "Enter" quando ti trovi su un elemento di menu di ultimo livello (una voce tipo "Set qualcosa") viene innescato l'evento menuUsed e questo cambia lo stato del codice, in modo che nel loop non venga per il momento richiamato navigateMenus ma vengano letti i pulsanti per cambiare ed eventualmente salvare i valori del setting.

Ciao,
Ho voluto provare il codice con la mia UNO, ma non mi funziona.
Nello specifico quando vado a modificare il file MenuBackend.h come spieghi tu, al momento di compilare il codice mi dice " 'class MenuBackend' has no member named 'toRoot'",
e di seguito tutto questo:
In file included from MenuBackend_lcd.cpp:25:
C:\Elettronica\arduino-0022\libraries\MenuBackend/MenuBackend.h: In member function 'void MenuItem::toRoot()':
C:\Elettronica\arduino-0022\libraries\MenuBackend/MenuBackend.h:105: error: 'getRoot' was not declared in this scope
C:\Elettronica\arduino-0022\libraries\MenuBackend/MenuBackend.h:105: error: 'setCurrent' was not declared in this scope
MenuBackend_lcd.cpp: In function 'void setup()':
MenuBackend_lcd:80: error: 'class MenuBackend' has no member named 'toRoot'
MenuBackend_lcd.cpp: In function 'void menuUsed(MenuUseEvent)':
MenuBackend_lcd:131: error: 'class MenuBackend' has no member named 'toRoot'
MenuBackend_lcd.cpp: In function 'void navigateMenus()':
MenuBackend_lcd:275: error: 'class MenuBackend' has no member named 'toRoot'
Mi puoi aiutare?
Grazie

Qualcosa è andato storto nella modifica alla library. Prova a riscaricarla e a rifare la modifica della library.

Grazie per tutte le info!
Mi è veramente utile per poter creare tutta una serie ci applicazioni per l'acquario.

Purtroppo non ho ancora una grande esperienza e mi trovo in difficoltà nella programmazione.
Mi potresti spiegare come potrei usare gli stessi pulsanti per poter modificare il valore di una variabile annidata nel menu?

Esempio:
menu 1: setta temperatura:
menu2: temperatura acqua giorno:
ALZA/ABBASSA TEMPERATURA CON I PULSANTI DEL MENU'

E' possibile inoltre usare dei tasti su un solo ingresso analogico, tipo tastiera analogica pulsanti+varie resistenze?
In questo modo si liberano 3 pin!
Grazie ancora!

Per quanto riguarda l'impostazione di variabili all'interno dei menu puoi dare un'occhiata al mio altro post sul MIDI Ribbon controller.
L'idea di usare un solo input analogico per più pulsanti è buona.

Invia nuovo commento

CAPTCHA
Questa domanda serve per verificare che tu non sia uno spammer automatico.
Image CAPTCHA
Inserisci i caratteri e i numeri visualizzati nell'immagine.