dispositivo per la lettura di un encoder incrementale

DISPOSITIVO PER LA LETTURA DI UN ENCODER
INCREMENTALE
Si propone l'uso di un microcontrollore pic16F84 della Microchip.
Si acquisiscono i segnali di un encoder con due canali in quadratura con la possibilità di selezionare
il conteggio di 2 o 4 fronti. La modalità di acquisizione è il polling. Il risultato del conteggio deve
poter essere acquisito da un pc per esempio attraverso software Labview. Per tal motivo si pubblica
il risultato del conteggio su PORTB (RB0...RB7) il cui valore va da 0 a 255 per poi azzerarsi e
ripartire. Al fine di acquisire correttamente a pc il valore, si fa uso di un segnale per la scrittura del
risultato del conteggio su PORTB. Tale segnale è una variazione di stato su RA3 e dovrà essere
inviato al microcontrollore al fine di aggiornare il valore del conteggio su PORTB.
Nella tabella che segue le corrispondenze tra pin e funzioni.
RA0
Ingresso: canale A dell'encoder
RA1
Ingresso: canale B dell'encoder
RA2
Ingresso: per la selezione del conteggio:
Low - 2 fronti
High - 4 fronti
La selezione va fatta all'avvio o al reset del microcontrollore
RA3
Ingresso: alla variazione di stato scrive il conteggio su PORTB (RB0....RB7)
RA4
Ingresso: non utilizzato nel software
RB0....RB7
Uscite: scrittura del conteggio 0...255
Il seguente software è scritto in C per il compilatore MikroC.
#define A PortaA.B0
#define B PortaA.B1
#define Scrivi PortaA.B3
void configurazione()
{
TRISA = 0B11111111;
PORTB = 0B00000000;
TRISB = 0B00000000;
//la variabile PortaA viene utilizzata per memorizzare PORTA
//RA0 E RA1 ingressi canale A e B encoder
//RA2 permette all'avvio la scelta della
//modalità di lettura 2 o 4 fronti
//RA3 alla variazione di fronte pubblica il
//il risultato viene scritto su PORTB
//inizializza PORTB a 0
//definizione PORTB tutte output
}
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 1 di 7
bit OldA,OldB,OldScrivi;
unsigned short PortaA,Conta;
void Conta2fronti()
{
Conta = 0;
PortaA = PORTA;
OldA = A;
OldScrivi = Scrivi;
//variabili globali ad 1 bit
//variabili globali ad 1 byte 0...255
//acquisisce l'intera porta A e la mette in PortaA
//A è il bit 0 della variabile PortaA
//Scrivi è il bit 3 della variabile PortaA
while(1)
{
PortaA = PORTA;
if (A!=OldA)
{
OldA = A;
if (A!=B) Conta--;
else Conta++;
}
if (Scrivi!=OldScrivi)
{
OldScrivi = Scrivi;
PORTB=Conta;
}
}
}
void Conta4fronti()
{
Conta = 0;
PortaA = PORTA;
OldA = A;
OldB = B;
OldScrivi = Scrivi;
//B è il bit 1 della variabile PortaA
while(1)
{
PortaA = PORTA;
if (A!=OldA)
{
OldA = A;
if (A!=B) Conta--;
else Conta++;
}
else if (B!=OldB)
{
OldB = B;
if (A!=B) Conta++;
else Conta--;
}
if (Scrivi!=OldScrivi)
{
OldScrivi = Scrivi;
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 2 di 7
PORTB=Conta;
}
}
}
void main() {
configurazione();
Delay_ms(10);
if(PORTA.F2==1) Conta4fronti();
else Conta2fronti();
}
//se RA2 è High chiama Conta4fronti
//altrimenti chiama Conta2fronti
Di seguito lo schema del circuito elettrico.
L'alimentazione va connessa a P1 (pin1 +7 ÷ +10 V, pin2 GND). Il regolatore di tensione 7805
provvede poi all'alimentazione di tutto il sistema. L'alimentazione all'encoder può essere fornita
attraverso P5 (pin1 +5 V, pin2 GND). Al connettore P2 sono presenti 4 ingressi al microcontrollore
come descritti precedentemente. Ai connettori P3 e P4 sono presenti 8 uscite del microcontrollore. I
resistori inseriti tra il micro e i connettori hanno la funzione di protezione delle porte in caso di
collegamenti errati.
Il pulsante SW1 permette il reset del micro, il pulsante SW2, se premuto all'avvio o al reset,
permette di selezionare la modalità di conteggio 4 fronti diversamente impostata su 2 fronti.
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 3 di 7
Due immagini 3D del circuito stampato completo di componenti.
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 4 di 7
ACQUISIZIONE DEL CONTEGGIO SU PERSONAL COMPUTER
Per l'acquisizione a pc del conteggio fatto dal microcontrollore si fa uso di una DAQ NI e relativo
software scritto in Labview.
Il risultato che si vuole ottenere è un'interfaccia con un indicatore che mostri la posizione angolare
dell'albero dell'encoder.
Il software deve inviare al pin RA3 del microcontrollore una variazione di fronte al fine che questo
scriva il risultato del conteggio su PORTB. Dopo una successiva breve pausa deve poi leggere il
codice binario presente su PORTB. Il tutto si ripete in un ciclo while.
Il problema principale è la gestione dell'azzeramento del conteggio quando questo giunge alla soglia
di transizione 255→0 (in binario 11111111→00000000) nella rotazione ad incrementare o viceversa
255←0 (in binario 11111111←00000000) nella rotazione a decrementare.
Sul pc il conteggio viene accumulato su una variabile I32 (32 bit con segno). Tale variabile va
incrementata con la differenza di lettura di PORTB. Non si usa il valore assoluto di PORTB ma la
sua variazione tra una lettura e la successiva:
incremento=valore_attuale–valore_precedente.
L'incremento può risultare positivo o negativo a seconda del verso di rotazione.
Durante la lettura di PORTB, nella rotazione positiva, può capitare che in un ciclo si legga
11111111 (255) e nel successivo ciclo ad esempio 00001000 (8) con un incremento complessivo di
9 fronti di conteggio. Questo per il fatto che l'albero dell'encoder gira velocemente quando invece la
lettura da parte del pc risulta relativamente lenta. Se si calcola però l'incremento come differenza tra
il valore attuale 8 e quello precedente 255 il risultato è 8-255=-247. Per correggere il calcolo in
questi casi basterà scrivere 256+(8-255)=9 e cioè, quando il risultato è negativo si applica la: 256+
(valore_attuale–valore_precedente).
Quindi l'algoritmo da applicare sembra essere:
if(valore_attuale–valore_precedente<0) incremento=256+(valore_attuale–valore_precedente)
else incremento= valore_attuale–valore_precedente
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 5 di 7
Durante la lettura di PORTB, nella rotazione negativa, con pari ragionamento si giunge però a
scrivere l'algoritmo:
if(valore_attuale–valore_precedente>0) incremento=(valore_attuale–valore_precedente)-256
else incremento= valore_attuale–valore_precedente
Visto che il verso di rotazione è determinabile esclusivamente dalla lettura di PORTB l'algoritmo
deve essere unico per entrambi i casi.
L'algoritmo sarà tale da:
• nella rotazione positiva accettare valori di incremento tra 1 e 127
• nella rotazione negativa accettare valori di incremento tra -1 e -127
• se l'incremento è uguale o supera -128 (-128 ...-255) significa che la rotazione è positiva.
• se l'incremento è uguale o supera 128 (128...255) significa che la rotazione è negativa.
In definitiva:
if (valore_attuale–valore_precedente<-127)
incremento=256+(valore_attuale–valore_precedente)
else if (valore_attuale–valore_precedente>127)
incremento=(valore_attuale–valore_precedente)-256
else incremento= valore_attuale–valore_precedente
Tale algoritmo entra in crisi nel momento in cui la rotazione dell'encoder raggiunge una velocità
tale da far si che nel contatore del microcontrollore, tra una lettura e l'altra da parte del pc, si
verifichi una variazione di conteggio pari o superiore a 128 fronti.
Nella figura a seguire l'immagine del software Labview scritto con le indicazioni appena esposte.
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 6 di 7
Tullio Carlassara – Dispositivo per la lettura di un encoder incrementale – 2011
pag. 7 di 7