Esercitazioni
PIC Baseline
|
20A - Lettura di un encoder incrementale
Lo scopo dell' esercitazione è l' utilizzo di encoder .
Un encoder è un dispositivo che converte la posizione angolare o il movimento di un albero o asse
in un codice analogico o digitale. Vengono comunemente impiegati in ambito industriale, su macchine automatiche, per realizzare
controllo di motori e movimenti, posizionamenti e regolazioni.
Abbiamo numerose tipologie di encoder in base alle loro modalità di
funzionamento, ai sistemi di codifica, ai segnali in uscita. Principalmente possiamo suddividerli in encoder assoluti e encoder
incrementali.
I primi forniscono la posizione angolare immediatamente e la conservano al
cadere dell'alimentazione; questo richiede una costruzione abbastanza
complessa e un certo numero di pin in uscita per poter leggere la codifica. Si
tratta di dispositivi di alta precisione, ma costosi.
|
Gli encoder incrementali, invece, forniscono una coppia di uscite di
impulsi, normalmente in quadratura tra di loro e dall' analisi dei
quali la logica a cui sono collegati deve derivare posizione,
direzione, velocità dell' albero.
Esistono modelli che utilizzano sensori ottici o magnetici; si tratta
solitamente di apparecchi di un certo costo (varie centinaia di euro)
e con caratteristiche elevate (anche 10k impulsi per giro e velocità
di rotazione di 30krpm), adatti all' integrazione in macchinari
automatici e robotica.
Ci sono, però, altri modelli, realizzati con contatti meccanici: questi non sono previsti per essere messi in
rotazione da meccanismi e servire per il posizionamento o il controllo
di motorizzazioni, ma, piuttosto, per essere azionati manualmente, agendo su una manopola, analogamente ad un
potenziometro. |
Questa destinazione fa si che abbiano un basso numero di impulsi per
giro (da 4 a 24) ed una bassa velocità di rotazione massima (60-120rpm),
che, assieme alla tecnologia costruttiva, ne fanno oggetti costo molto
limitato (<5€). |
|
Sono impiegati intensivamente come dispositivi di ingresso per
sistemi digitali, da strumentazione ad
apparecchiature audio, dove, ad esempio, vanno a sostituire proprio i
potenziometri analogici: lo spostamento angolare viene interpretato
dal microcontroller e trasformato nelle variazioni di PWM o tensione
necessarie alla regolazione.
Costruttivamente, l'encoder contiene due contatti striscianti su piste
opportunamente sagomate che aprono e chiudono tra un terminale comune
e due uscite A e B.
Queste uscite, fornite
di pull-up, sono collegate agli I/O del microcontroller; la sequenza di aperture e chiusure che si determinano con
la rotazione permettono al software di elaborare l'informazione.
|
Va notato che, nonostante appaia in molti esempi sul WEB, l'utilizzo dei
weak pull-up integrati nel chip può non essere una buona soluzione. Infatti,
se si utilizzano questi, si risparmiano due resistenze esterne, ma abbiamo a
che fare con contatti meccanici, che richiedono una minima corrente per
funzionare correttamente. I WPU hanno valori abbastanza alti (70-100k), mentre
i fogli dati indicano generalmente la necessità di un pull-up mediamente da
10k.
L'impiego con correnti troppo basse determina incertezze nelle commutazioni,
sopratutto dopo un certo uso.
|
Dal punto di vista logico, la relazione tra le fasi permette di determinare
il senso di rotazione.
Come si vede nel diagramma, per convenzione comune:
- se la transizione in salita di B anticipa quella di A, la
rotazione è antioraria (CCW - CounterClockWise).
- se A anticipa B la rotazione sarà oraria (CW - ClockWise)
|
L'interpretazione dei segnali viene sviluppata considerando le transizioni
degli impulsi. Esistono diversi modi: quello che vediamo ora si basa su una
considerazione.
|
Osserviamo come la sovrapposizione delle due onde quadre determina 4
fasi in un ciclo:
CCW |
00 |
01 |
11 |
10 |
CW |
10 |
11 |
01 |
00 |
|
Si tratta, in pratica, di un codice Gray a due bit, in cui cambia un solo
bit ad ogni transizione.
Possiamo analizzare la situazione sincronizzandoci con un o più fronti di
commutazione attraverso un interrupt di I/O (INT) e verificando con una lookup
table. Però i Baseline non dispongono di questa funzione, per cui si può
ricorrere ad un polling sull' I/O. Inoltre, possiamo anche elaborare volta per
volta le variazioni del codice Grey.
Innanzitutto possiamo determinare con facilità se si sono verificati
cambiamenti di stato nei segnali: se prendiamo una immagine dei livelli logici
segnali e successivamente compariamo questa con la situazione attuale
attraverso un XOR, un cambiamento è indicato con un risultato diverso da
0.
Se c'è stato un cambiamento, eseguiamo un XOR tra la situazione precedente,
shiftata a sinistra di una posizione, e quella attuale; ogni coppia di valori
per il movimento CCW renderà 0, mentre CW renderà 1.
Ad ogni variazione valida, il programma deriverà un impulso in uno dei due
sensi di rotazione, permettendo sia un conteggio up/down, sia il rilevamento
della posizione angolare , valutando il rapporto tra impulsi per giro e angolo
di rotazione. Inoltre è possibile rilevare la velocità calcolando il periodo
degli impulsi e, di conseguenza, anche accelerazione o decelerazione.
|
Va tenuto presente, però, che gli encoder con contatti meccanici sono soggetti a
rimbalzi durante le commutazioni; dato che i rimbalzi occupano tempi alquanto
più lunghi di un ciclo istruzione, occorre evitare che il programma
interpreti questi eventi come segnali validi.
Inoltre, essendo ruotati a mano,
è possibile qualche irregolarità (chattering o slippage) durante la
rotazione, cose che, se non considerate, falserebbero il
conteggio. |
Il foglio dati dichiara 3ms massimo di rimbalzi e 2ms per l'eventuale
rumore durante la rotazione. Si tratta di valori massimi che difficilmente
sono riscontrabili su un componente nuovo, ma possibili dopo un lungo tempo di
lavoro, con il consumarsi delle superfici di contatto.
Una tecnica per correggere la situazione è quella di verificare lo stato
dell' encoder ogni 1/(risoluzione*max. giri_al_secondo). Così,
un encoder a 24 impulsi per giro con una possibilità massima di 120rpm (1 giro
al secondo), sarà interrogato ogni 1/24*2 = 20ms. Abbiamo
detto che si tratta di encoder messi in rotazione a mano, agendo su una
manopola e che il valore nominale di 120rpm riportato sul foglio dati ben difficilmente è raggiungibile in pratica, per cui ci si potrà basare su
valori molto minori. In questa direzione, può essere utile sapere che più la manopola ha un
diametro elevato, minore sarà la velocità di rotazione possibile e quindi
minore la necessità di campionare.
D'altra parte, disponendo di processori abbastanza veloci, si potranno fare
campionamenti molto più rapidi o utilizzare interrupt di I/O per verificare i
fronti di commutazione su cui applicare algoritmi per isolare i disturbi.
Questo può essere gravoso o non proponibile per microcontroller di fascia
bassa: l' appesantimento del programma con l' aggiunta del debounce software
complessi può essere evitato con l'inserimento di una rete RC che riduca o
annulli i rimbalzi:
|
Il circuito è consigliato da Panasonic per i suoi encoder meccanici
della serie EVE ed è adatto praticamente per tutti i modelli.
I pull-up sono da 10k e, tra questi e l' ingresso del PIC sono
inseriti filtri passa basso RC composti da un' altra resistenza da 10k
e condensatore da 10nF.
I valori non sono critici: le resistenze possono variare tra 4k7 e
47k e i condensatori salire a 100nF. Maggiori sono i valori, maggiore
sarà la reiezione del disturbo, ma peggiore sarà il fronte di
commutazione, il che richiede un ingressi del chip dotato di Schmitt
trigger. In particolare, il valore dei pull-up consigliato dai
costruttori varia da 4k7 a 10k (e simili): una lettura del foglio dati
del componente permette la scelta più adeguata..
|
Va notato che, nonostante appaia in molti esempi sul WEB, l'utilizzo dei
weak pull-up integrati nel chip può non essere una buona soluzione. Infatti,
se si utilizzano questi, certamente si risparmiano due resistenze esterne;
però abbiamo a
che fare con contatti meccanici, che richiedono una minima corrente per
funzionare correttamente. I WPU hanno valori abbastanza alti (70-100k), mentre
i fogli dati indicano generalmente la necessità di un pull-up tra 5 e 22k.
Questo può portare a incertezze nelle commutazioni, sopratutto dopo un certo
uso del componente. Da
qui la scelta di usare pull-up esterni ai quali basta l'aggiunta di un
ulteriore RC per realizzare un anti rimbalzi.
Da notare che se utilizziamo versioni ottiche degli encoder, un debounce
hardware non è necessario, in quanto le commutazioni, prodotte da coppie
fotodiodo/fototransistor non presentano
rimbalzi. Il maggior costo viene ripagato da una maggiore precisione e
risoluzione e da un minore carico nel firmware.
Alcuni di questi piccoli encoder integrano un pulsante che si aziona
premendo l' albero; altri dispongono in testa all' albero di uno o due LED.
Queste opzioni permettono di realizzare comandi complessi e segnalazioni in
una sola manopola.
Detent
Gran parte degli encoder meccanici previsti per l' azionamento manuale con
una manopola sono dotati di detent: si tratta semplicemente di arresti
meccanici che fanno avanzare a scatti la rotazione, con il tipico click.
Questa soluzione rende sensibile all' utente la manovra della manopola e,
nello stesso tempo, la arresta in posizioni determinate. Questo non penalizza
l' uso dell' encoder: abbiamo visto che per ogni ciclo i due segnali
permettono di determinare 4 diverse posizioni. Ad esempio, se l' encoder
svolge 24 passi per giro, tra un passo e il successivo ci sono 15°; rilevando
i codici intermedi possiamo individuare spostamenti di 15/4=3.75°. Questo si
chiama "risoluzione 4x" e può essere utile per definire
maggiormente posizionamenti effettuati da servo controlli.
Però, nell' azionamento manuale, l' encoder va a sostituire un commutatore o
un potenziomento in un ambito diverso dal posizionamento e una definizione
troppo elevata diventerebbe controproducente, per l' incertezza dovuta all'
azionamento a mano. Inoltre, si presentererebbe la possibilità di backslash,
ovvero, al rilascio della monopola, di uno o più scatti all' indietro del
conteggio. I detent, solitamente in numero pari alla risoluzione dell' encoder,
evitano tutto questo, oltre a fornire all' utente un feedback chiaro della
rotazione; il detent diventa indispensabile in presenza di vibrazioni, come
nel caso di equipaggiamenti per autoveicoli. La definizione di variazioni
diverse da quelle delle risoluzione nominale sono comunque effettuabili dal
programma di gestione, ma non sono utili all' atto pratico se non per
aumentare il rapporto tra un passo e il numero da conteggiare oppure per
determinare accelerazione o decelerazione della rotazione.
|
I modelli senza detent hanno una rotazione continua similmente ad un
potenziometro e consentono al software di implementare sia una
risoluzione 4x (un conteggio per ogni variazione), sia un 2x (un
conteggio ogni due variazioni) sia un 1x (un conteggio ogni ciclo).
Se i modelli con detent sono preferiti per dare un feedback tattile
all' utilizzatore, molto pratico negli apparecchi consumer, i modelli
senza detent trovano posto sui pannelli apparecchiature audio e video,
dove vanno a sostituire i classici potenziometri analogici. Li
troviamo anche come regolazioni di strumenti, dove premettono una
maggiore risoluzione - anche se qui, in larga parte, va considerato
che si tratta di encoder ottici e non meccanici, dato il problema dei
rimbalzi dei contatti, la cui correzione diventa più difficoltosa con
l' aumentare della risoluzione. |
I modelli con detent possono avere rapporti diversi tra impulsi per giro e
detent per giro; ad esempio, ecco alcuni modelli dal catalogo
di Alps:
Modello |
EC11B15202AA |
EC11E09244AQ |
EC11E1830401 |
EC20A1824401 |
EC12E24204A7 |
Impulsi per giro |
15 |
9 |
15 |
20 |
24 |
Detent per giro |
30 |
18 |
- |
20 |
24 |
Inoltre, non tutti operano nella stessa maniera, anche se la tendenza è
quella di avere i contatti aperti sul detent; questo consente di avere il
minimo consumo se l'albero non ruota.
|
Encoder CUI. L' immagine a sinistra si riferisce a
modelli con 12 e 20 impulsi e detent per giro.
Quella a destra si riferisce a encoder con 15 impulsi e 30 detent. |
La conoscenza di questi elementi è necessaria nel caso in cui si vogliano
implementare algoritmi di decodifica basati su interrupt e tabelle o dove sia
richiesta una rilevazione dell' accelerazione e simili prestazioni
extra.
In generale, la scelta del tipo di encoder dipenderà dall' applicazione;
risoluzioni o velocità di rotazione elevate non sono necessarie nelle
regolazioni manuali. Nel nostro caso, dove l' analisi dei segnali in
quadratura è effettuata da un Baseline, senza interrupt, e con una procedura
semplificata, possiamo utilizzare un economicissimo modello a contati
meccanici con detent pari al numero degli impulsi, in modo da avere un
feedback positivo immediato tra la rotazione ed la variazione del conteggio
elaborato..
L' hardware
Utilizziamo un PIC a 14 pin, 16F505 ad esempio:
Utilizziamo un encoder della serie 3315
di Bourns oppure serie EVE
di Panasonic o 510
di Honeywell con 16 impulsi per giro; questo permette di contare da 0 a Fh per ogni giro. Ovviamente si potranno utilizzare anche altri
modelli, come la serie DPL12 di
Tyco, con 24 impulsi per giro. In tal caso il
conteggio arriverà a Fh a 2/3 del giro.
PORTC e un bit del PORTB
sono usati per pilotare i sette segmenti, mentre
due pin sono dedicati ai segnali dell' encoder. Ruotando in senso orario l'
albero dell' encoder il display conterà a crescere in esadecimale; l' opposto se il senso è
antiorario.
Il pulsante di RESET azzera il risultato, facendo ripartire il programma
dall'inizio.
La LPCuB
semplifica le connessioni, anche se occorre un supporto a parte per l'encoder:
I jumper "gialli" collegano i segmenti da a a f.
Il jumper volante "giallo" collega il segmento g.
I jumper volanti "verde" e "nocciola" collegano i segnali
dalla scheda dell' encoder.
Il jumper "verde" attiva il primo display.
Il pulsante RES è utilizzato come RESET; quindi occorrono i jumper
"rosso" e "viola"
Se si utilizza il filtro RC antirimbalzi sui contatti dell' encoder,
durante la programmazione occorre scollegare si RB0 e RB1, dato che la
capacità collegata renderebbero difficoltosa l'operazione. |
L' encoder trova posto su una schedina Smart
Proto Board di Mikroelektronika, inserita nel connettore JMK,
come in precedenza.
I segnali A e B sono accessibili dai pin D4 e D6
del connettore. L' encoder usato (Tyco)
dispone anche di un pulsante che è accessibile da D7, ma non viene
usato in questa applicazione.
I componenti RC dell' antirimbalzo non sono indispensabili, dato che il
software campiona con un tempo maggiore di quello che il foglio dati assegna
ai bounces.
Una foto della realizzazione: pull-up e RC sono installabili su contatti a
tulipano per poter effettuare cambiamenti con facilità. In questa versione
sono installati solo i pull-up da 10k; i condensatori non sono presenti
(contati a tulipano in bassi a sinistra) e le resistente dell' RC sono
sostituite da due ponticelli (rossi).
Una foto dell' insieme durante lo sviluppo con un Pickit3:
Il programma
Il sorgente è compilabile per 16F505/506/526 con il solito sistema di #ifdef
visto
nelle esercitazioni.
A questo riguardo, occorre notare che in ambiente MPLAB non occorre
strettamente che il sorgente riporti la definizione del processore
usato e la configurazione, dato che queste voci sono inseribili
dal menu principale:
- Configure -> Select Device per il processore
- Configure -> Configuration Bits per la
configurazione, de selezionando la casella Configuration Bits
Set in Code
Però, operando questa scelta non si ottiene alcun vantaggio:
- occorre comunque includere il file nomeprocessore.inc
delle definizioni, mentre non risulta immediatamente chiaro quale
processore è usato
- una modifica della configurazione va fatta dal menu principale,
cosa che richiede lo stesso tempo che operandola sul sorgente
- dovendo trasferire ad altri o conservare il lavoro fatto,
occorre trasferire o conservare l'intero progetto, senza il quale
va persa la configurazione che non risulta nel sorgente.
Inoltre, cosa essenziale, il sorgente perde funzione di auto
documentazione.
Quindi, la pratica di assegnare questi elementi all' ambiente di
sviluppo è poco sensata e controproducente. |
Le routines e la lookup table del display sono nella prima metà della pagina 0.
Il programma principale consiste solamente in un loop con la chiamata delle
varie subroutines:
; loop di conteggio
countloop:
call Dly3msT0
; cadenza 3ms
call Chck_Encoder
; verifica encoder e aggiorna contatore
movf counter,W
; recupera contatore
call Segtbl
; converti numero->maschera 7 segm
call Display
; al display
goto countloop |
Il test sull' encoder è effettuato ad una cadenza di 3ms circa, il che
permette una azione di debounce. La routine di tempo è una di quelle già
viste nelle Esercitazioni, con l' impiego del Timer0 precaricato con un valore
specifico e attendendo l'overflow.
La routine di verifica dello stato dell' encoder rileva l'ultimo valore degli ingressi
e salva solo i bit dei due canali:
;-----------Chck_Encoder----------------
; Verifica stato encoder e aggiorna contatore
Chck_Encoder:
movf
encoderport,W ; legge encoder
andlw b'00000011'
; maschera solo bit utili
movwf attuale
; e salva
|
Un XOR con una copia del valore precedente permette di determinare se c'è
stata una variazione:
; Se la lettura auttuale è uguale a quella precedente
; non c'è stata variazione.
xorwf precedente,W
skpnz
; se diversi, salta
retlw 0
; uguali - rientra |
in questo caso, la routine shifta il valore precedente
di una posizione a sinistra, iniettando uno zero al bit 0 attraverso il carry.
Questo allinea l'LSB con il bit 2 del valore attuale. L'XOR dei due determina
la direzione e quindi se il contatore incrementa o decrementa.
; Sposta i bit letti a sinistra per l' xor
clrc
rlf precedente,F
; XOR stato corrente con il precedente shiftato
movf attuale,W
;
xorwf precedente,f
; Set uscite
btfss precedente,1
; test bit 1
goto SetUp
; count Up
goto SetDn
; count Down |
Il contatore viene aggiornato solamente ogni 4 impulsi validi, ovvero pari
ai detent dell' encoder, con un uguale numero di impulsi per giro:
; Risoluzione x1
; - per ciascuna transizione (4 per ciclo) viene definita la direzione
; e viene decrementato un counter locale realtivo alla direzione.
; - ogni 4 transizioni sarà variato il contatore generale
; ==================== Movimento Orario ===========================
; Movimento orario, check per 4 step nella stessa direzione
SetUp decfsz
dirup,f
goto
setendU ; n - per ora esci
incf
counter,f ; s - incrementa contatore
goto
EndPulse ; fine procedura |
Analogamente per il conteggio Down. Volendo incrementare la risoluzione, si
potrà modificare il valore della costante step:
step |
variazioni
sul contatore |
4 |
1 per ciclo |
2 |
2 per ciclo |
1 |
4 per ciclo |
All'uscita dalla procedura, vengono
aggiornati i contatori locali e viene copiata la situazione attuale nella
precedente, per il prossimo check:
endp
movf attuale,W ; salva lettura attuale per il
movwf precedente
; prossimo test
retlw 0 |
La trasformazione dell' LSB del contatore in maschera di comando dei sette
segmenti è effettuata con la lookup table come abbiamo visto
nell'Esercitazione 5.
La divisione delle azioni in subroutines consente di modificare con facilità
il programma. Così, ad esempio, la presentazione del dato sul display potrà
essere facilmente modificata per un hardware differente.
Da osservare che il metodo di identificazione della rotazione è
trasferibile su qualsiasi altro PIC senza problemi, dato che tutti possono
eseguire il set di istruzione dei Baseline.
File compresso contenente il progetto MPLAB.
|