Esempio di menu su display LCD con un microcontrollore PIC, gestito da encoder rotativo

Sto continuando a realizzare esempi per le schede Microchip Curiosity Nano: devo dire la verità, mi piacciono davvero tanto.

Se non sapete di cosa sto parlando, vuol dire che vi siete persi un articolo precedente! Ahi ahi ahi!

Cosa fa l’esempio

Qui vi illustro un esempio, purtroppo forse nemmeno tanto semplice, ma sicuramente nemmeno difficile, per realizzare un semplicissimo menù costituito da due pagine mostrate su un display LCD alfanumerico (di quelli gestiti da un controller tipo HD44780).

In questo video vi illustro di cosa si tratta:

In pratica, premendo il pulsante di cui è munito l’encoder (quello che si attiva abbassando l’alberino) si cicla tra le pagine del menù.

Nel video mi vedete premere il pulsante SW0 a bordo della scheda perchè ho schiantato l’encoder dato che uso sempre lo stesso da anni solo per gli esperimenti! Ma è lo stesso in quanto nel codice l’ho collegato allo stesso IO sfruttato dal pulsante onboard.

Ruotando l’encoder si cambia il valore di una variabile e ogni pagina permette di gestire una variabile diversa. Per questo esempio ho sfruttato le nozioni che abbiamo imparato in passato nella lezione sugli encoder.

Il codice

Il codice sorgente lo trovate sul mio repository Github a questo indirizzo. Faccio uso della classica libreria, ormai storica, che abbiamo sviluppato insieme in questi anni, per gestire un display LCD da 20 caratteri x 4 righe. Il progetto è stato sviluppato per MPLAB X con il compilatore XC8 versione 2.10 e la scheda utilizzata è una PIC16F15376 Curiosity Nano. Faccio uso dell’ MPLAB Code Configurator, perciò vi ritrovate una cartella mcc_generated_files che contiene tutti i file generati da questo tool.

In particolare faccio uso dei seguenti interrupts:

  • Sul Timer0 ogni millisecondo, con cui ho implementato una routine antirimbalzo per l’encoder
  • Sul cambio di stato (ANY, ovvero sia da livello alto a basso che viceversa) dei due pin dell’encoder rotativo (che per coerenza chiamo sempre Dir e Pulse)

La rotazione degli encoder è gestita da alcune variabili:

  • EncoderState : assume il valore TRUE quando i pin Dir e Pulse si trovano allo stesso livello (entrambi a livello alto o entrambi a livello basso). Questo mi serve per tenere traccia di due stati consecutivi dell’encoder e decidere quindi se sta ruotando in senso orario o antiorario
  • EncAntiBounce: è un flag che mi segnala se è attiva la routine di antibounce. Nel caso in cui sia true e si verifica un interrupt sull’encoder, salto tutta la funzione. Se la routine di antibounce non è attiva, nel momento in cui mi si verifica un interrupt, disattivo gli interrupt, faccio tutte le mie elaborazioni e la attivo. Dopodichè il controllo passa al Timer.
  • EncTimer: counter incrementato dal Timer0 per conteggiare il tempo di antibounce
  • ENCTIMERRESTART: costante, fissata a 4, che indica il tempo di durata della routine di antirimbalzo in millisecondi
  • cpVar e cnVar: sono contatori del numero di tick rilevati rispettivamente per la rotazione in senso orario e in senso antiorario. Girando il microcontrollore a 32MHz e utilizzando encoder cinesi di pessima qualità, con tutti gli accorgimenti del caso capitava sempre che, anche girando molto delicatamente, un singolo scatto causava un incremento delle variabili superiore ad una unità. Ho fatto quindi in modo di contare x tick successivi prima di incrementare la variabile controllata di uno.
  • CCOUNT: costante fissata a 3, imposta il numero di tick successivi, nella stessa direzione, di cui tener conto per incrementare di una unità la variabile controllata.

Con tutti questi accorgimenti l’encoder si comporta bene anche se spesso è necessario dare più di uno scatto all’encoder per incrementare la variabile, ma poco male.

Links

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)