Utilizzare 4 Rotary Encoder sfruttando solo 3 IO con Arduino
Questa soluzione, realizzata con un Arduino ed una manciata di componenti esterni, permette di “leggere” 4 Rotary Encoder utilizzando soltanto 3 ingressi del microcontrollore: un ingresso interrupt, un ingresso analogico ed un ingresso generico (analogico o digitale).
L’idea nasce dall’ esigenza di progettare un dispositivo in grado di offrire le seguenti specifiche:
- basso costo
- piccole dimensioni
- limitato utilizzo del numero di ingressi/uscite
- timing del processore ottimizzato mediante lettura basata su interrupt piuttosto che su polling.
Il programma/sketch non è elegantissimo (sorry ma sono alle prime armi con Arduino e con la programmazione in C🙂 ) ma è molto semplice e leggero perché non utilizza librerie esterne, protocolli di comunicazione seriale o manipolazioni di dati complesse.
Il sistema si presenta, quindi, come una valida alternativa a soluzioni più eleganti ma impegnative quali, ad esempio, quelle basate sull’utilizzo di IO expander, e preserva buona parte delle risorse del processore stesso lasciando ampio margine all’aggiunta di ulteriori funzionalità/componenti.
Prima di passare alla descrizione della soluzione, riepilogo brevemente le caratteristiche e la configurazione dei Rotary Encoder (RE) utilizzati in questo progetto. Per approfondimenti sui Rotary Encoder vi invito a leggere un precedente articolo qui su settorezero e, in particolare per Arduino, questa pagina sul Playground.
Indice dei contenuti
I Rotary Encoder
Da qui in poi utilizzerò la dicitura “RE” per indicare i Rotary Encoder.
I RE utilizzati in questo progetto sono di tipo incrementale, con uscite “in quadratura”, con detent su “OFF-OFF”, vale a dire che i 2 switch interni sono aperti quando il rotore è in posizione di riposo (detent). Considerando che sono collegati al microcontrollore tramite resistenze di pull-up, sulle uscite A e B a riposo leggeremo una tensione di 5V (Fig.1)
ATTENZIONE: il progetto illustrato funziona unicamente con RE con DETENT!
Il segnale A viene utilizzato come “clock”, ovvero come segnale di riferimento: in corrispondenza di una sua variazione di stato (in particolare di un fronte di discesa) avvia una routine di interrupt (ISR) che, inoltre, indica al processore l’inizio di un movimento meccanico del rotore del RE.
Il segnale B, una volta avviata la routine di interrupt e, quindi, una volta rilevato un movimento, in base al suo stato in corrispondenza del fronte di discesa di A, fornisce indicazione sul verso del movimento del rotore (direzione).
Ipotizzando che il rotore si muova in senso orario, si leggano i 2 segnali di Fig.1 da sinistra verso destra: in corrispondenza di ogni fronte di discesa di A lo stato di B è sempre basso. Viceversa, muovendo il rotore in senso opposto (anti orario), si leggano i 2 segnali di Fig.1 da destra verso sinistra: in corrispondenza di ogni fronte di discesa di A lo stato di B è sempre alto.
Quindi la routine SW di decodifica del movimento dei RE seguirà questo flusso:
Il Partitore VDM
La soluzione realizza la “parallelizzazione” dei Rotary Encoder mediante un partitore di tensione che fornisce, su un’ unica uscita, una tensione diversa per ogni encoder (Fig. 2).
Questa tecnica è molto simile a quella utilizzata per la realizzazione dei pulsanti multimediali presenti sugli auricolari dei telefoni cellulari e, da un certo punto di vista, è anche simile alla tecnica di multiplazione VDM (Voltage Division Multiplexing).
Per comodità da qui in poi chiamerò questo dispositivo partitore VDM.
In dettaglio, gli impulsi dei RE vengono invertiti dal partitore ed, in funzione dell’ ingresso (Ix) a cui sono collegati, vengono riportati in un’ unica uscita (U) con tensioni diverse. La Fig.2 mostra la manipolazione di 4 impulsi inviati su ingressi diversi ed in istanti (t) diversi e mette in evidenza la corrispondenza tra l’ ingresso e la tensione di uscita: I1->v1; I2->v2… etc. In questo modo il processore, leggendo la tensione in uscita al partitore, riconosce l’encoder che sta generando l’impulso.
Dal punto di vista elettrico il partitore VDM viene realizzato in questo modo (Fig.3):
Il circuito completo
Lo schema seguente (Fig.4) descrive il funzionamento del circuito che fornisce i 3 segnali necessari al processore per effettuare la decodifica dei movimenti dei singoli RE:
A valle del partitore di tensione, il blocco Comp, che in realtà è un amplificatore operazionale in configurazione comparatore_invertente, a partire dal segnale VDM, ripristina la forma d’onda originale degli impulsi provenienti dai pin A dei RE, invertendoli e riportandoli nel range 0-5V, tuttavia mantenendoli uniti su un unico filo.
I pin B dei rotary encoder vengono uniti semplicemente cortocircuitandoli tra loro.
I 3 segnali generati vengono interpretati dal processore in questo ordine cronologico:
- Segnale di interrupt (Clock) – è il segnale che fornisce l’indicazione dell’ inizio movimento del rotore di uno dei 4 RE ed avvia la routine di interrupt;
- Segnale VDM – è il segnale che indica quale dei 4 RE si è mosso;
- Segnale di direzione – è il segnale che fornisce l’indicazione relativa alla direzione del movimento del rotore.
Di seguito lo schema elettrico (Fig.5):
Realizzazione pratica del sistema
Per la realizzazione di questa soluzione ho utilizzato un clone di Arduino UNO ma ipotizzo che qualsiasi altra scheda basata su microprocessore con caratteristiche simili o superiori (o anche inferiori, entro certi limiti) possa funzionare. In particolare, se volete applicare questa soluzione ad un picmicro, fate riferimento a questo articolo ed apportate le opportune modifiche.
Di seguito lo schema di realizzazione del prototipo su Breadboard (Fig.6):
La lista dei componenti è scaricabile da QUI. Tutti i condensatori sono da 100nF.
Video dimostrativo
Il sistema, come potete vedere dal video, funziona in maniera molto fluida e veloce, non sembra perdere colpi e riesce a decodificare anche il movimento contemporaneo (in realtà direi “pseudo-contemporaneo”!) di più RE, anche se in teoria questo non dovrebbe essere possibile. Nel prossimo paragrafo farò qualche considerazione in dettaglio su questo aspetto.
Limitazioni/espansioni del sistema, approfondimenti e altre considerazioni
Espansione del numero di RE
Il partitore VDM è stato progettato in modo da fornire in uscita soltanto 4 valori di tensione, entro il range di conversione A/D di Arduino (0-5V), più o meno equidistanti tra di loro, oltre al valore di 0V che corrisponde alla condizione di riposo.
Il range reale del partitore VDM è leggermente più stretto di 0-5V per motivi legati alla tecnologia costruttiva dell’ integrato 74HC125 ed è, precisamente: 138mV-4,88V.
Il grafico seguente (Fig.7) mostra l’andamento reale dei segnali provenienti dai 4 ingressi, in uscita al partitore VDM, generati in sequenza a partire da I1:
Il numero ed il valore delle possibili tensioni che il partitore VDM può generare dipendono, rispettivamente, dal numero di ingressi/buffer necessari e dalla configurazione della rete resistiva che collega le uscite di tutti i buffer. In questo caso le tensioni disponibili sono le seguenti: 4,88V (I4), 3,7(I3), 2,6(I2) e 1,7(I1).
Ho preferito non scendere al di sotto degli 1,7V per minimizzare l’effetto di eventuali disturbi nei dintorni dello 0V e gli effetti prodotti da eventuali soglie dei semiconduttori utilizzati a valle del partitore, pur mantenendo una distanza consistente tra i vari valori per minimizzare errori di lettura analogica dovuti a tolleranze o disturbi.
Tuttavia, da misurazioni sperimentali, ho verificato che la conversione A/D rileva sempre il valore atteso con una tolleranza di circa 10mV, mentre lo sketch accetta variazioni intorno al valore teorico nell’ ordine di ±250mV. Pertanto, ritengo che con l’utilizzo di componenti di precisione e/o di qualità sia possibile espandere il numero di RE utilizzabili anche fino a circa 15/20.
Intervento contemporaneo di più RE
Per le sue caratteristiche costruttive il partitore VDM garantisce la lettura soltanto di un encoder alla volta. Nel caso di movimento contemporaneo di 2 o più RE la tensione rilevata all’ uscita del partitore sarà quella relativa all’ encoder collegato all’ ingresso più alto (più vicino all’ ingresso dell’ OP-AMP). Tuttavia non è garantita la corretta decodifica del movimento a causa dell’ impossibilità di discriminare lo stato delle uscite B degli encoder che intervengono nello stesso istante.
Ciononostante, come si può osservare dal video, viste le alte velocità di switching in gioco e vista la bassa probabilità che 2 impulsi si sovrappongano nell’ intervallo di qualche millisecondo, il sistema sembra reagire bene anche nei casi di “pseudo-contemporaneità” di intervento di più RE.
Velocità di rotazione dei RE
Per le reti di debounce utilizzate (Condensatore da 100nF e Resistenza da 10kΩ) e per la velocità degli altri componenti utilizzati, il sistema garantisce l’utilizzo di RE con velocità di rotazione capaci di produrre fino a circa 50 o 60 impulsi per secondo. Ad esempio RE con 24 PPR (Pulses Per Revolution) e velocità di rotazione di 150 RPM (Revolution Per Minute). Eventuali limiti di utilizzo potrebbero dipendere dal processore e dalla routine SW utilizzati.
Freeze del sistema in caso di blocco su “NON-DETENT”
I RE con detent sono realizzati in modo da portare il rotore in posizione di detent in situazione di riposo. Ovvero, quando viene rilasciato il rotore in seguito ad un movimento, la meccanica dovrebbe “richiamare” il rotore nella posizione di detent più vicina. Tuttavia, per problemi di qualità costruttiva, questo non accade sempre, come nel caso dei RE utilizzati per questo progetto.
Nel caso in cui uno o più RE dovessero bloccarsi in posizione di NON-DETENT (cioè tra 2 detent consecutivi) gli altri RE non vengono più decodificati.
Questo accade perché uno o entrambi gli switch dei RE bloccati in NON-DETENT restano chiusi forzando l’uscita del partitore VDM ad una tensione fissa maggiore di 0V che maschera tutti i segnali degli altri RE, in particolare i segnali di interrupt. Ovviamente questo problema si può superare utilizzando RE di qualità superiore.
Download
4 Encoders con 3 IO (681 download)