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