Visto che interessa e non ho altro da fare in questa Domenica di freddo... 'Na roba fatta un po' di tempo fa con un dsPIC.
Dal datasheet:
Nella prima immagine vediamo la struttura di un Encoder in quadratura, dotato di tre uscite: A, B e Z (INDEX).
Gli impulsi generati tramite un sistema fotodiodo/disco ottico sono due, e sfasati uno rispetto all'altro di 90° ovvero in quadro (da qui "in quadratura"). Verificando la fase di A rispetto a B, riusciamo, oltre che a contare gli impulsi, a rilevare la direzione della rotazione in avanti o indietro.
La terza uscita Z è riferita ad un solo impulso generato da una singola feritoia in concomitanza del passaggio di questa di fronte al fotodiodo, passaggio che avviene UNA sola volta per giro, permettendo così di avere un riferimento/giro preciso, da cui ZERO.
Nella seconda immagine possiamo osservare la struttura del modulo QEI.
Integra in Hardware tutto il necessario per gestire un Encoder Incrementale, così da sollevare la CPU interna da questi calcoli, ed evitare i LAG che con un Arduino inevitabilmente si avrebbero.
Inoltre i dsPIC hanno - insieme alla ALU normale - un core DSP, quindi esegue tutte le operazioni per calcolare le posizioni e le velocità angolari (con un sacco di pesanti funzioni di seno e coseno) alla velocità della luce (rispetto ad Arduino)
Osserviamo il modulo. Troviamo subito dei filtri digitali su ogni ingresso, così si puliscono i segnali da glitches vari, nonchè riflessioni parassite (avvengono sui bordi delle feritoie ad alta velocita, in cui il fotodiodo legge degli impulsi in più causati dalle riflessioni sulle pareti interne delle feritoie)
Bene, anzi, benissimo, non dobbiamo mettere dei filtri esterni!
Dopo abbiamo la logica della quadratura che legge le fasi tra i due segnali A e B e capisce se stai andando AVANTI o INDIETRO, e quindi fornisce un segnale di UP o DOWN sull'apposito piedino (a cui - per esempio - potremmo collegare due LED a freccia).
Dopo di che c'è un contatore (indicato con POSCNT, che è un registro) avanti/indietro a 16 bit (quindi conta da 0 a +32.767, oppure da 0 a a -32.768, oltre questi valori va in overflow, ovvero si azzera).
Poi c'è un comparatore che lavora insieme al registro MAXCNT.
Come funziona? Si inserisce un numero (il numero degli impulsi/giro che fornisce l'Encoder) dentro il registro MAXCNT e il comparatore lo confronta in tempo reale con quello dentro il contatore di posizione POSCNT, quando i due sono uguali significa che il contatore POSCNT è a tappo, ovvero il Motore-Encoder ha fatto un giro e allora il comparatore azzera il contatore POSCNT, che riparte da 0, dalla posizione zero.
Una seconda modalità - ancora più precisa ed affidabile - consiste nell'azzerare il contatore di POSIZIONE, non arbitrariamente contando gli impulsi per giro, ma utilizzando l'impulso dell'uscita Z (INDEX) quale avviene una sola volta per giro, e per una unica, specifica, posizione dell'Encoder.
Ora due righe sul codice:
Questo codice inizializza il modulo QEI. Per vedere tutti i parametri bisogna pupparsi tutta la sezione che lo riguarda sul datasheet, ma prendendo solo le funzioni che ci interessano (ce ne sono tantissime) che sono anche le più semplici, possiamo semplificare un pò:
void InitQEI(void)
{
ADPCFG |= 0x0038; // Configura i PIN del QEI come INGRESSI DIGITALI
QEICONbits.QEIM = 0; // Disabilito il QEI Module (un modulo si spegne sempre prima di configurarlo, poi lo si riaccende alla fine
QEICONbits.CNTERR = 0; // Azzera il contatore degli errori (si, c'è anche un rilevatore di errori e li conta!)
QEICONbits.QEISIDL = 0; // Continua le operazioni di conteggio anche se la CPU va in sleep
QEICONbits.SWPAB = 0; // Qua puoi scambiare QEA e QEB nel caso hai invertito i fili
QEICONbits.PCDOUT = 0; // Normali operazioni di I/O
QEICONbits.POSRES = 1; // Quando arriva un impulso dal pin INDEX, si resetta il POSCNT
DFLTCONbits.CEID = 1; // Contatore degli errori DISABILITATO
DFLTCONbits.QEOUT = 1; // Filtro Digitale sugli ingressi Qa e QB ABILITATO
DFLTCONbits.QECK = 5; // Frequenza di taglio del Filtro Digitale (bisogna fare il calcolo)
DFLTCONbits.INDOUT = 1; // Filtro Digitale sull' ingresso INDEX, ABILITATO
DFLTCONbits.INDCK = 5; // Frequenza di taglio del Filtro Digitale (bisogna fare il calcolo)
POSCNT = 0; // Reset contatore di posizione (si può settare anche "a mano")
QEICONbits.QEIM = 6; // X4 mode = magheggio per trasformare un encoder da 100 imp a 400 imp.
return;
}
La suite di sviluppo è la versione 8.9 di MPLAB IDE. Non uso l'ultimissima perchè lavoro da anni con questa e mi trovo meglio.