Tutorials - PIC - Corso A&C

 

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.


 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 18/03/15.