Sommario:

Un menu in Arduino e come usare i pulsanti: 10 passaggi (con immagini)
Un menu in Arduino e come usare i pulsanti: 10 passaggi (con immagini)

Video: Un menu in Arduino e come usare i pulsanti: 10 passaggi (con immagini)

Video: Un menu in Arduino e come usare i pulsanti: 10 passaggi (con immagini)
Video: Menu a livelli con Arduino e LCD shield - 2/2 - Video 262 2024, Dicembre
Anonim
Un menu in Arduino e come usare i pulsanti
Un menu in Arduino e come usare i pulsanti

Nel mio tutorial Arduino 101, ti verrà insegnato come configurare il tuo ambiente in Tinkercad. Uso Tinkercad perché è una piattaforma online piuttosto potente che mi consente di dimostrare agli studenti una serie di abilità per la costruzione di circuiti. Sentiti libero di creare tutti i miei tutorial usando l'IDE Arduino e un vero Arduino!

In questo tutorial, impareremo a conoscere i pulsanti! Dobbiamo sapere:

  • Come cablarli?
  • Leggendo il loro valore
  • Antirimbalzo, e perché è importante
  • Un'applicazione pratica (creazione di un menu)

La maggior parte delle persone pensa che la cosa più pratica da fare con un pulsante sia accendere e spegnere una luce. Lo faremo, non qui! Useremo il nostro per creare un menu e impostare alcune opzioni su Arduino.

Pronto? Iniziamo!

Passaggio 1: imposta la scheda

Imposta la scheda
Imposta la scheda
Imposta la scheda
Imposta la scheda

Il primo passo è mettere Arduino e Breadboard Small nell'area di prototipazione. Controlla le immagini sopra per vedere come cablare i binari di alimentazione.

Un Breadboard Mini ha due binari di alimentazione in alto e in basso. Li colleghiamo ad Arduino in modo da poter fornire energia a più componenti. Più avanti in questo tutorial useremo 3 pulsanti quindi avremo bisogno di più potenza. La cosa da notare è che su una breadboard piccola, i binari di alimentazione corrono su tutta la scheda, orizzontalmente. Questo è diverso dalle colonne nell'area di prototipazione principale al centro; questi corrono verticalmente. È possibile utilizzare uno qualsiasi dei pin di alimentazione per fornire alimentazione a qualsiasi colonna nell'area principale al centro.

Quando aggiungi potenza, usa i fili nero e rosso rispettivamente al negativo e al positivo. Aggiungi i fili all'estremità che alimentano l'altro lato della scheda. Non useremo quel lato, ma è una buona pratica.

Passaggio 2: aggiungi il pulsante e il resistore

Aggiungi il pulsante e il resistore
Aggiungi il pulsante e il resistore
Aggiungi il pulsante e il resistore
Aggiungi il pulsante e il resistore
Aggiungi il pulsante e il resistore
Aggiungi il pulsante e il resistore

Aggiungere un piccolo pulsante dal vassoio dei componenti. Dovrebbe assomigliare a quello nell'immagine. Assicurati che non sia un interruttore! Aggiungi anche un resistore. Fare clic e impostare il suo valore su 10kΩ. Questo è sufficiente per abbassare il pin quando non è collegato, il che è molto importante più avanti nel codice.

Posiziona il componente al centro della breadboard. Il modo in cui funziona un pulsante è:

  • Da un angolo all'altro, il pulsante non è collegato. Premendo il pulsante si chiudono i contatti e si collegano gli angoli.
  • I lati del pulsante sono collegati. Se si collegasse un filo in alto a sinistra e in basso a sinistra, il circuito sarebbe chiuso.

Questo è il motivo per cui mettiamo il componente attraverso lo spazio nel mezzo. Si assicura che gli angoli non siano collegati sotto i pin della scheda.

Il passaggio successivo fornisce un paio di immagini che illustrano questi punti.

Posiziona il resistore dal pin in basso a destra attraverso le colonne, in modo che si trovi orizzontalmente.

Passaggio 3: collegamenti dei pulsanti

Collegamenti dei pulsanti
Collegamenti dei pulsanti
Collegamenti dei pulsanti
Collegamenti dei pulsanti

Le immagini sopra rendono abbastanza chiaro come si collegano i pulsanti. È sempre stato un punto di confusione quando pensi che qualcosa va bene e non funziona!

Ora aggiungiamo i fili.

  • Posiziona un cavo rosso da un pin di alimentazione positivo alla stessa colonna del pin in basso a destra sul pulsante
  • Posizionare un cavo nero da un pin di alimentazione negativo alla stessa colonna del resistore.
  • Posiziona un filo colorato (non rosso/nero) dal pin in alto a sinistra al pin digitale 2 su Arduino

Controlla le immagini sopra per assicurarti che il cablaggio sia corretto.

Passaggio 4: il codice…

Il codice…
Il codice…
Il codice…
Il codice…

Diamo un'occhiata al codice per un pulsante di base.

Apri l'editor del codice e passa da Blocchi a Testo. Cancella l'avviso visualizzato. Siamo contenti del testo!

Conosci la configurazione di base, quindi definiamo il pulsante ed eseguiamo una lettura di base. Stamperemo l'output su Serial.

Ho inserito alcuni commenti in più nel codice qui sotto in modo che sia più facile da leggere rispetto all'immagine.

// Definisci le costanti

#define button 2 void setup() { pinMode(button, INPUT); Serial.begin(9600); } void loop() { // Legge il pin digitale per verificare lo stato del pulsante int premuto = digitalRead(pulsante); // Il pulsante restituisce HIGH se premuto, LOW se non viene premuto if(premuto == HIGH){ Serial.println("Premuto!"); } }

Ok, funziona bene!

In sostanza, tutto ciò che stiamo facendo è controllare lo stato del pin digitale ogni volta che il codice si ripete. Se fai clic su Avvia simulazione e premi il pulsante, vedrai il monitor seriale (fai clic sul pulsante sotto il codice) che visualizza "Premuto!" ripetutamente.

Una caratteristica che vedrai nel codice sopra è la valutazione della condizione if() in corso. Tutto ciò che il codice sta facendo è porre una domanda e valutare se è vero, in questo caso. Usiamo è uguale (doppio segno di uguale, come questo: ==) per verificare se il valore della variabile è uguale a un certo valore. Un digitalRead() restituisce HIGH o LOW.

Usando if() else if / else possiamo controllare molte condizioni o tutte le condizioni, e se torni alle basi di Arduino, vedrai alcuni dei confronti che puoi fare.

Ora… Il nostro codice potrebbe sembrare completo… Ma abbiamo un problema.

Vedi, funziona davvero bene quando sei nel simulatore. Ma la vera elettricità ha rumore, specialmente l'elettronica DC. Quindi il nostro pulsante potrebbe restituire una lettura falsa a volte. E questo è un problema, perché il tuo progetto potrebbe non rispondere nel modo giusto per l'utente.

Ripariamolo!

Passaggio 5: un po' di antirimbalzo

Un po' di rimbalzo
Un po' di rimbalzo

Usiamo una procedura chiamata antirimbalzo per superare il nostro problema con i pulsanti. Questo essenzialmente attende un periodo di tempo specificato tra il momento in cui il pulsante è stato premuto e la risposta effettiva alla pressione. È ancora naturale per l'utente (a meno che tu non richieda troppo tempo). Puoi anche usarlo per controllare la durata della stampa, in modo da poter rispondere in modo diverso ogni volta. Non è necessario modificare alcun cablaggio!

Diamo un'occhiata al codice:

#define button 2#define debounceTimeout 100

La prima modifica riguarda l'ambito globale. Ricorderai che è qui che definiamo le variabili che molte delle nostre funzioni potrebbero utilizzare o quelle che non possono essere ripristinate ogni volta che il ciclo si attiva. Quindi, abbiamo aggiunto debounceTimeout alle costanti definite. Abbiamo realizzato questo 100 (che in seguito si tradurrà in 100 ms), ma potrebbe essere più breve. Ancora un po' e sembrerà innaturale.

long int lastDebounceTime;

Questa variabile è dichiarata sotto le costanti. Questo è un tipo long int, che fondamentalmente ci consente di memorizzare numeri lunghi in memoria. L'abbiamo chiamato lastDebounceTime.

Non è necessario modificare nulla nella funzione void setup(). Lasciamo quello.

void loop() { // Legge il pin digitale per verificare lo stato del pulsante int premuto = digitalRead(pulsante); long int currentTime = millis(); // Codice pulsante }

La prima modifica che apportiamo alla funzione loop() è sotto la chiamata per leggere il pulsante. Dobbiamo tenere traccia dell'ora corrente. La funzione millis() restituisce l'ora corrente dell'orologio dall'avvio di Arduino in millisecondi. Dobbiamo memorizzarlo in una variabile di tipo int lungo.

Ora, dobbiamo assicurarci di essere a conoscenza del tempo trascorso da quando è stato premuto il pulsante, quindi reimpostiamo il timer quando non viene premuto. Guarda:

void loop() { // Legge il pin digitale per verificare lo stato del pulsante int premuto = digitalRead(pulsante); long int currentTime = millis(); if(pressed == LOW){ // Reimposta il tempo di conteggio mentre il pulsante non è premuto lastDebounceTime = currentTime; } // Codice pulsante }

L'algoritmo if(pressed == LOW) controlla se il pulsante non è premuto. In caso contrario, il codice memorizza l'ora corrente dall'ultimo antirimbalzo. In questo modo, ogni volta che viene premuto il pulsante, abbiamo un punto nel tempo dal quale possiamo controllare quando è stato premuto il pulsante. Possiamo quindi eseguire un rapido calcolo matematico per vedere per quanto tempo è stato premuto il pulsante e rispondere correttamente. Diamo un'occhiata al resto del codice:

void loop() { // Legge il pin digitale per verificare lo stato del pulsante int premuto = digitalRead(pulsante); long int currentTime = millis(); if(pressed == LOW){ // Reimposta il tempo di conteggio mentre il pulsante non è premuto lastDebounceTime = currentTime; } // Il pulsante è stato premuto per un certo tempo if(((currentTime - lastDebounceTime) > debounceTimeout)){ // Se viene raggiunto il timeout, pulsante premuto! Serial.println("Premuto!"); } }

L'ultimo blocco di codice prende l'ora corrente, sottrae l'ultimo tempo di antirimbalzo e lo confronta con il timeout che abbiamo impostato. Se è maggiore, il codice presume che il pulsante sia stato premuto per quel tempo e risponde. Pulito!

Esegui il tuo codice e verifica che funzioni. Se hai errori, controlla il tuo codice!

Ora, diamo un'occhiata a un esempio pratico.

Passaggio 6: la creazione di un menu

La realizzazione di un menu
La realizzazione di un menu

I pulsanti sono interessanti, perché ci sono così tante possibilità con loro! In questo esempio, creeremo un menu. Supponiamo che tu abbia creato questo dispositivo davvero eccezionale e che gli utenti siano in grado di modificare le opzioni per attivare o disattivare determinate cose o impostare un valore particolare per un'impostazione. Questo design a tre pulsanti può farlo!

Quindi, per questo progetto abbiamo bisogno di:

  • Tre pulsanti
  • Tre resistori impostati su 10kΩ

Ne abbiamo già uno, ci servono solo gli altri due. Quindi aggiungi quelli alla lavagna. Il cablaggio è un po' più complesso, ma solo perché volevo mantenerlo davvero compatto. Puoi seguire lo stesso schema per il primo pulsante o seguire l'immagine sopra.

I tre pulsanti sono un'opzione di apertura/successiva del menu, un'opzione di modifica (ad esempio, modifica dell'impostazione) e un pulsante di menu di salvataggio/chiusura.

Collegalo, diamo un'occhiata al codice!

Passaggio 7: scomposizione del codice - Globale

Ok, sarà un passo lungo, ma esaminerò ogni sezione del codice.

Per prima cosa, diamo un'occhiata alle variabili globali necessarie.

// Definisci le costanti#define menuButton 2 #define menuSelect 3#define menuSave 4 #define debounceTimeout 50 // Definisce le variabili int menuButtonPreviousState = LOW; int menuSelectPreviousState = BASSO; int menuSavePreviousState = BASSO; long int lastDebounceTime; // Opzioni del menu char * menuOptions = {"Controlla temperatura", "Controlla luce"}; bool featureSetting = {false, false}; bool menuMode = false; bool menuNeedsPrint = false; int optionSelected = 0;

Questi tre blocchi sono abbastanza simili a quelli che abbiamo visto prima. Nella prima ho definito i tre pulsanti e il timeout. Per questa parte del progetto, l'ho impostato su 50 ms, quindi ci vuole una stampa deliberata per farlo funzionare.

Il secondo blocco è tutte le variabili. Dobbiamo tenere traccia del buttonPreviousState e dobbiamo tenere traccia dell'ultimoDebounceTime. Queste sono tutte variabili di tipo int, ma l'ultimo è un tipo lungo perché presumo che abbiamo bisogno dello spazio in memoria.

Il blocco delle opzioni di menu ha alcune nuove funzionalità. Primo, il char * (sì, questo è un asterisco deliberato), che è una variabile letterale carattere/stringa. È un puntatore a un'archiviazione statica in memoria. Non puoi cambiarlo (come puoi in Python, per esempio). Questa riga char *menuOptions crea un array di stringhe letterali. Puoi aggiungere tutte le voci di menu che desideri.

La variabile bool featureSetting è solo l'array di valori che rappresenta ogni voce di menu. Sì, puoi memorizzare tutto ciò che ti piace, basta cambiare il tipo di variabile (devono essere tutte dello stesso tipo). Ora, potrebbero esserci modi migliori per gestirlo, come dizionari o tuple, ma questo è semplice per questa applicazione. Probabilmente creerei uno di questi ultimi in un'applicazione distribuita.

Ho tenuto traccia del menuMode, quindi se volessi altre cose sul mio display potrei farlo. Inoltre, se avessi la logica del sensore, potrei metterla in pausa durante il funzionamento del menu, nel caso in cui qualcosa sia in conflitto. Ho una variabile menuNeedsPrint perché voglio stampare il menu in momenti specifici, non sempre. Infine, ho una variabile optionSelected, così posso tenere traccia dell'opzione selezionata mentre vi accedo in un certo numero di posti.

Diamo un'occhiata al prossimo set di funzioni.

Passaggio 8: scomposizione del codice - Configurazione e funzioni personalizzate

La funzione setup() è abbastanza semplice, solo tre dichiarazioni di input:

void setup() { pinMode(menuSelect, INPUT); pinMode(menuSave, INPUT); pinMode(menuSelect, INPUT); Serial.begin(9600); }

Le prossime sono le tre funzioni personalizzate. Diamo un'occhiata ai primi due, poi l'ultimo separatamente.

Abbiamo bisogno di due funzioni che restituiscano alcune informazioni. Il motivo è che vogliamo assicurarci che sia leggibile dall'uomo. Aiuterà anche con il debug del codice se abbiamo un problema. Codice:

// Funzione per restituire l'opzione attualmente selezionata. *ReturnOptionSelected(){ char *menuOption = menuOptions[optionSelected]; // Return optionSelected return menuOption; } // Funzione per restituire lo stato dell'opzione attualmente selezionata char *ReturnOptionStatus(){ bool optionSetting = featureSetting[optionSelected]; char *optionSettingVal; if (optionSetting == false){ optionSettingVal = "False"; }else{ optionSettingVal = "Vero"; } // Return optionSetting return optionSettingVal; }

La funzione char *ReturnOptionSelected() controlla l'opzione selezionata (se vedi sopra, impostiamo una variabile per tenerne traccia) e estrae la stringa letterale dall'array che abbiamo creato in precedenza. Quindi lo restituisce come tipo char. Lo sappiamo perché la funzione indica il tipo restituito.

La seconda funzione, char *ReturnOptionStatus(), legge lo stato dell'opzione salvata nell'array e restituisce una stringa letterale che rappresenta il valore. Ad esempio, se l'impostazione che abbiamo memorizzato è false, restituirei "False". Questo perché mostriamo all'utente questa variabile ed è meglio tenere insieme tutta questa logica. Potrei farlo più tardi, ma ha più senso farlo qui.

// Funzione per attivare l'opzione corrente ToggleOptionSelected(){ featureSetting[optionSelected] = !featureSetting[optionSelected]; restituire vero; }

La funzione bool ToggleOptionSelected() è una comoda funzione per modificare il valore dell'impostazione che abbiamo selezionato nel menu. Inverte semplicemente il valore. Se avessi un set di opzioni più complesso, questo potrebbe essere molto diverso. Restituisco vero in questa funzione, perché il mio callback (la chiamata più avanti nel codice che attiva questa funzione) si aspetta una risposta vero/falso. Sono sicuro al 100% che funzionerà, quindi non ho tenuto conto del fatto che non funzionasse, ma lo farei in un'applicazione distribuita (per ogni evenienza).

Passaggio 9: il ciclo…

La funzione loop() è abbastanza lunga, quindi la faremo in parti. Puoi presumere che tutto ciò che segue si annida all'interno di questa funzione:

ciclo vuoto() {

// Lavora qui <----- }

Ok, abbiamo già visto queste cose:

// Legge i pulsanti int menuButtonPressed = digitalRead(menuButton); int menuSelectPressed = digitalRead(menuSelect); int menuSavePressed = digitalRead(menuSave); // Ottieni l'ora corrente long int currentTime = millis(); if(menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW){ //Reimposta il tempo di conteggio mentre il pulsante non viene premuto lastDebounceTime = currentTime; menuButtonPreviousState = BASSO; menuSelectPreviousState = BASSO; menuSavePreviousState = BASSO; }

Tutto quello che dovevo fare qui era aggiungere le tre chiamate digitalRead() e assicurarmi di aver tenuto conto del fatto che se tutti i pulsanti erano bassi, dovremmo reimpostare il timer (lastDebounceTime = currentTime) e impostare tutti gli stati precedenti su bassi. Memorizzo anche millis() in currentTime.

La sezione successiva si annida all'interno della linea

if(((currentTime - lastDebounceTime) > debounceTimeout)){

//Lavoro qui <---- }

Ci sono tre sezioni. Sì, avrei potuto spostarli nelle loro funzioni, ma per semplicità ho mantenuto i tre algoritmi principali dei pulsanti qui.

if((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)){ if(menuMode == false){ menuMode = true; // Comunica all'utente Serial.println("Il menu è attivo"); }else if (menuMode == true && optionSelected = 1){ // Reimposta opzione optionSelected = 0; } // Stampa il menu menuNeedsPrint = true; // Attiva/disattiva il pulsante precedente. stato di visualizzare solo menu // se il pulsante viene rilasciato e premuto nuovamente menuButtonPreviousState = menuButtonPressed; // Sarebbe ALTO }

Questo primo gestisce quando menuButtonPressed è HIGH o quando viene premuto il pulsante menu. Inoltre, verifica che lo stato precedente fosse BASSO, in modo che il pulsante debba essere rilasciato prima di essere premuto di nuovo, il che impedisce al programma di attivare costantemente lo stesso evento più e più volte.

Quindi verifica che se il menu non è attivo, lo attiva. Stamperà la prima opzione selezionata (che è il primo elemento nell'array menuOptions per impostazione predefinita. Se premi il pulsante una seconda o terza (ecc) volta, otterrai l'opzione successiva nell'elenco. Qualcosa che potrei correggere è che quando arriva alla fine, torna indietro all'inizio. Questo potrebbe leggere la lunghezza dell'array e rendere più facile il ritorno indietro se hai cambiato il numero di opzioni, ma per ora era semplice.

L'ultima piccola sezione (//Stampa il menu) ovviamente stampa il menu, ma imposta anche lo stato precedente su HIGH in modo che la stessa funzione non venga ripetuta (vedi la mia nota sopra sul controllo se il pulsante era precedentemente LOW).

// viene premuto menuSelect, fornire logicif((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)){ if(menuMode){ // Cambia l'opzione selezionata // Al momento, questo è solo vero/falso // ma potrebbe essere qualsiasi cosa bool toggle = ToggleOptionSelected(); if(toggle){ menuNeedsPrint = true; }else{ Serial.println("Qualcosa è andato storto. Riprova"); } } // Commuta lo stato per commutare solo se rilasciato e premuto nuovamente menuSelectPreviousState = menuSelectPressed; }

Questo bit di codice gestisce il pulsante menuSelectPressed allo stesso modo, tranne che questa volta si attiva semplicemente la funzione ToggleOptionSelected(). Come ho detto prima, potresti cambiare questa funzione in modo che faccia di più, ma è tutto ciò di cui ho bisogno.

La cosa principale da notare è la variabile toggle, che tiene traccia del successo della richiamata e stampa il menu se true. Se non restituisce nulla o falso, stamperà il messaggio di errore. Qui è dove puoi usare la tua richiamata per fare altre cose.

if((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)){ // Esci dal menu // Qui puoi eseguire qualsiasi operazione di riordino // o salvare su EEPROM menuMode = false; Serial.println("Menu uscito"); // Commuta lo stato in modo che il menu esca solo una volta menuSavePreviousState = menuSavePressed; } }

Questa funzione gestisce il pulsante menuSave, che esce dal menu. Qui è dove potresti avere un'opzione di annullamento o salvataggio, magari fare un po' di pulizia o salvare nella EEPROM. Ho appena stampato "Menu uscito" e impostato lo stato del pulsante su ALTO in modo che non si ripeta.

if(menuMode && menuNeedsPrint){ // Abbiamo stampato il menu, quindi a meno che // non accada qualcosa, non è necessario stamparlo di nuovo menuNeedsPrint = false; char *optionActive = ReturnOptionSelected(); char *optionStatus = ReturnOptionStatus(); Serial.print("Selezionato: "); Serial.print(optionActive); Serial.print(": "); Serial.print(optionStatus); Serial.println(); }

Questo è l'algoritmo menuPrint, che si attiva solo quando il menu è attivo e quando la variabile menuNeedsPrint è impostata su true.

Questo potrebbe sicuramente essere spostato in una sua funzione, ma per semplicità..!

Bene, è così! Vedere il passaggio successivo per l'intero blocco di codice.

Passaggio 10: blocco di codice finale

// Definisci le costanti

#define menuButton 2 #define menuSelect 3 #define menuSave 4 #define debounceTimeout 50 int menuButtonPreviousState = LOW; int menuSelectPreviousState = BASSO; int menuSavePreviousState = BASSO; // Definisce le variabili long int lastDebounceTime; bool lightSensor = true; bool tempSensor = true; // Opzioni del menu char * menuOptions = {"Controlla temperatura", "Controlla luce"}; bool featureSetting = {false, false}; bool menuMode = false; bool menuNeedsPrint = false; int optionSelected = 0; // Funzione di configurazione

void setup() { pinMode(menuSelect, INPUT); pinMode(menuSave, INPUT); pinMode(menuSelect, INPUT); Serial.begin(9600); }

// Funzione per restituire l'opzione attualmente selezionata char *ReturnOptionSelected(){ char *menuOption = menuOptions[optionSelected]; // Return optionSelected return menuOption; } // Funzione per restituire lo stato dell'opzione attualmente selezionata char *ReturnOptionStatus(){ bool optionSetting = featureSetting[optionSelected]; char *optionSettingVal; if (optionSetting == false){ optionSettingVal = "False"; }else{ optionSettingVal = "Vero"; } // Return optionSetting return optionSettingVal; } // Funzione per attivare l'opzione corrente bool ToggleOptionSelected(){ featureSetting[optionSelected] = !featureSetting[optionSelected]; restituire vero; } // Il ciclo principale

void loop(){ // Legge i pulsanti int menuButtonPressed = digitalRead(menuButton); int menuSelectPressed = digitalRead(menuSelect); int menuSavePressed = digitalRead(menuSave); // Ottieni l'ora corrente long int currentTime = millis(); if(menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW){ //Reimposta il tempo di conteggio mentre il pulsante non viene premuto lastDebounceTime = currentTime; menuButtonPreviousState = BASSO; menuSelectPreviousState = BASSO; menuSavePreviousState = BASSO; } if(((currentTime - lastDebounceTime) > debounceTimeout)){ // Se viene raggiunto il timeout, pulsante premuto!

// viene premuto menuButton, fornisce la logica

// Si attiva solo quando il pulsante è stato precedentemente rilasciato if((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)){ if(menuMode == false){ menuMode = true; // Comunica all'utente Serial.println("Il menu è attivo"); }else if (menuMode == true && optionSelected = 1){ // Reimposta opzione optionSelected = 0; } // Stampa il menu menuNeedsPrint = true; // Attiva/disattiva il pulsante precedente. stato di visualizzare solo menu // se il pulsante viene rilasciato e premuto nuovamente menuButtonPreviousState = menuButtonPressed; // Sarebbe ALTO } // menuSelect viene premuto, fornisce la logica if((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)){ if(menuMode){ // Modifica l'opzione selezionata // Al momento, questo è solo vero/falso // ma potrebbe essere qualsiasi cosa bool toggle = ToggleOptionSelected(); if(toggle){ menuNeedsPrint = true; }else{ Serial.print("Qualcosa è andato storto. Riprova"); } } // Commuta lo stato per commutare solo se rilasciato e premuto nuovamente menuSelectPreviousState = menuSelectPressed; } if((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)){ // Esci dal menu // Qui puoi fare qualsiasi cosa // o salvare su EEPROM menuMode = false; Serial.println("Menu uscito"); // Commuta lo stato in modo che il menu esca solo una volta menuSavePreviousState = menuSavePressed; } } // Stampa l'opzione di menu corrente attiva, ma stampala solo una volta if(menuMode && menuNeedsPrint){ // Abbiamo stampato il menu, quindi a meno che // non accada qualcosa, non è necessario stamparlo di nuovo menuNeedsPrint = false; char *optionActive = ReturnOptionSelected(); char *optionStatus = ReturnOptionStatus(); Serial.print("Selezionato: "); Serial.print(optionActive); Serial.print(": "); Serial.print(optionStatus); Serial.println(); } } }

Il circuito è disponibile sul sito Tinkercad. Ho incorporato anche il circuito qui sotto per farti vedere!

Come sempre, se avete domande o problemi, fatemelo sapere!

Consigliato: