Come configurare smartphone e PC. Portale informativo

Circuito encoder incrementali. Corso di formazione

In questo progetto demo, esamineremo il compito di interfacciare un controllo chiamato encoder con un microcontrollore PIC.

Per implementare il progetto demo, abbiamo bisogno di:

  • encoder a 24 posizioni;
  • 16 LED (3 mm);
  • driver LED;
  • microcontrollore.

L'encoder è un elemento moderno e originale per il controllo di dispositivi digitali e in apparenza sembra un resistore variabile (vedi figura sotto). Un altro nome per questo controllo è sensore angolare, sensore di rotazione. La rotazione dell'albero è accompagnata da clic, ad esempio 24 clic per giro. L'encoder ha 3 uscite - A, B, C e viene utilizzato per l'immissione rapida di dati in dispositivi digitali. Alcuni modelli hanno un pulsante integrato che viene attivato premendo l'albero dell'encoder (viene aggiunta un'altra uscita).

Come funziona l'encoder

Ruotando un clic, ad esempio, a destra, il contatto A + C viene chiuso prima, quindi B + C. Quando l'albero gira in questo scatto, i contatti si aprono nella stessa sequenza. Quando l'albero viene ruotato nell'altro senso, la sequenza di chiusura con il contatto C cambia, cioè quando si gira a sinistra, prima B + C, poi A + C sono chiusi.

Utilizzando l'encoder nei progetti di microcontrollori, è possibile implementare diversi tipi di input di dati utilizzando lo stesso encoder, tuttavia, ciò richiede un feedback e una visualizzazione in modo che l'utente sappia quali informazioni sta inserendo e in quale posizione l'encoder.


Schema: collegamento di un encoder a un microcontrollore PIC (clicca per ingrandire)

Le uscite dell'encoder A e B sono collegate alle porte del microcontrollore RB4 e RB5, l'uscita dell'encoder C è collegata a massa. Vale la pena notare che i resistori di pull-up devono essere collegati alle linee di segnale dei pin A e B. L'encoder non è collegato accidentalmente alle linee I/O specificate del microcontrollore: in primo luogo, la porta B ha resistori di pull-up integrati e non dobbiamo collegare quelli esterni, e in secondo luogo, la porta B del microcontrollore ha un funzione utile - "interrupt-on-change" - interruzione per cambio di livello, che ci consentirà di monitorare lo stato dell'encoder.

16 LED convenzionali da 3 mm vengono utilizzati per visualizzare i dati in ingresso e saranno posizionati sul PCB attorno all'encoder montato. I LED sono collegati al chip A6276.

Il chip è un driver LED con ingresso seriale a 16 bit. Il driver contiene un registro a scorrimento CMOS a 16 bit, latch e driver LED appropriati e può pilotare più LED di quanti ne possa gestire il microcontrollore. Inoltre, il driver può essere controllato tramite l'interfaccia SPI, che riduce ulteriormente il numero di linee di I/O utilizzate e rende il progetto scalabile.

Il software del microcontrollore per risolvere il nostro problema è relativamente semplice. Sono disponibili 3 modalità di funzionamento (immissione di informazioni) e feedback:

  • Modalità di posizionamento a 360° - in questa modalità, i LED indicano la "posizione" corrente dell'encoder, l'utente può ruotare l'albero dell'encoder a sinistra ea destra in qualsiasi angolo;
  • Modalità "Volume/Livello" - in questa modalità, i LED indicano il valore corrente tra i livelli minimo e massimo della gamma di ingresso (come il livello del volume nei dispositivi audio);
  • Modalità interruttore rotante a 3 posizioni - In questa modalità, ci sono solo tre posizioni selezionabili che l'utente seleziona ruotando l'albero dell'encoder a sinistra/destra.

Dimostrazione del progetto

Un encoder per un convertitore di frequenza è simile nell'aspetto a un resistore variabile oa un potenziometro. Le stesse tre uscite, lo stesso corpo del pannello. È qui che finisce la somiglianza. Al suo interno ha due interruttori, che hanno un'uscita comune di compiti di controllo e due propri.

Affinché l'encoder funzioni, il pin centrale deve essere collegato a terra e gli altri due tramite resistori all'alimentazione. Il segnale di controllo deve essere rimosso direttamente dalle uscite del pannello encoder.

Ora immagina che l'encoder sia l'ideale e che i suoi contatti non soffrano di rimbalzo. Collegare un oscilloscopio alle uscite dell'encoder e iniziare a ruotare la manopola dell'encoder. Gli impulsi verranno spostati l'uno rispetto all'altro di 90 gradi. Se giri la manopola di potenza (kW) a destra, sinistra o indietro, avremo le sequenze del pannello di controllo:

Se le forme d'onda sono un'applicazione di una sequenza di attività di zeri e uno logici, avranno questo aspetto:

Prendiamo un codificatore ordinario, che ha un rimbalzo dei contatti. Zona di chiacchiere:

Quando si passa da uno logico a uno zero logico, si verifica un rimbalzo. Chatter può essere gestito in due modi: hardware e software applicativo.

Il metodo hardware consiste nel collegare una serie di condensatori del convertitore di frequenza, trigger Schmitt, come indicato nello schema del pannello di controllo:

Si consiglia di utilizzare il metodo per gestire le chiacchiere - software. Tale metodo è descritto nella libreria Rothery. Questa libreria contiene diverse funzioni necessarie per impostare le uscite del controller vettoriale sull'ingresso e collegare i resistori di pull-up di potenza (kW). La libreria dovrebbe specificare i comandi e le attività appropriati. Questo comando accende la resistenza di pull-up all'interno.

La funzione Get position vfd series restituisce il valore dell'encoder. Questa funzione è necessaria per ottenere il numero di impulsi conteggiati dall'encoder. La funzione impostata Posizione vfd è necessaria per caricare il valore da cui l'encoder inizierà a contare.

La funzione tick deve essere considerata in modo più dettagliato. Le variabili di questa funzione sig1 e sig2 registrano lo stato del pin vettoriale a cui è collegato l'encoder. Successivamente, questi pin vengono scritti nella variabile thisState vfd, che è lo stato corrente del codificatore. Se lo stato attuale dell'encoder non è uguale a quello precedente, vengono calcolate le nuove direzioni di conteggio e il numero di impulsi di potenza viene memorizzato nella variabile Posizione. Quando l'encoder ritorna alla sua posizione vettoriale iniziale, ci sarà uno spostamento a destra di due bit e il nuovo valore di controllo deve essere scritto nella variabile PositionExt. Questa variabile è necessaria per memorizzare una serie di risultati di attività che verranno utilizzati nel programma principale.

Dai un'occhiata

Dopo aver analizzato lo stato dell'encoder durante la rotazione a sinistra e a destra, compiliamo una tabella:

La sua posizione di partenza è 1-1. Quando si gira a destra, si è verificato un clic, l'unità è diventata uno zero logico. Il nuovo valore di questo Stato vfd è 01. Secondo il comando, questo risultato viene aggiunto al valore della variabile Posizione.

A causa del rimbalzo, la posizione è diventata 11, dopo il ricalcolo il numero di serie è diventato 7. Al termine del rimbalzo, è necessario correggere la nuova posizione 01 e uno viene aggiunto allo zero precedente. Quando si gira l'encoder, c'è stato un clic e il valore della variabile Posizione è diventato uno.

C'è un secondo clic quando si gira l'encoder a destra e invece della posizione 01 abbiamo la posizione 00. Dopo che tutte le vibrazioni sono terminate, anche l'uscita di controllo ha un valore di uno. Al quarto clic, quando la posizione da 10 diventa 11, abbiamo un valore di 6. Al termine del rimbalzo, rimane 6.

In alcuni codificatori viene utilizzato un pulsante del pannello. Quando lo premi e lo rilasci, ci sarà anche un rimbalzo di contatti, devi applicare la libreria Bounce. Le funzioni di questa libreria sono necessarie per impostare il pin a cui verrà collegato il pulsante, compiti del tempo di ritardo in millisecondi. Se il pulsante è stato premuto, la funzione di potenza (kW) restituisce il valore del vettore true, in caso contrario, false vfd.

Schema di collegamento dell'encoder al convertitore di frequenza

Nell'industria delle macchine utensili, gli encoder sono ampiamente utilizzati per i convertitori di frequenza di motori asincroni. Sono montati come sensori di retroazione della velocità. Tali encoder hanno un'alta risoluzione da 100 impulsi per giro a 1 milione di impulsi per giro. Questo marchio ha una discrezione di 500 imp. viceversa.

Gli encoder sono suddivisi in tipi di attività in base a. Sono assoluti e incrementali. Il nostro encoder svolge la consueta funzione di emettere un segnale di differenziazione allo spegnimento e poi alla riaccensione. Lo stato precedente non viene salvato.

Gli encoder a vista assoluta hanno una memoria interna che ricorda le ultime posizioni. Perché è necessaria la memoria e perché salvare questi dati? Nella fabbrica di macchine utensili, prima di spostare un determinato dispositivo, viene prima indicato il punto zero. Questo processo è chiamato referenziazione, cioè andare a zero.

L'utilizzo di un sensore di visione assoluta consente di evitare questa procedura per la seconda volta, di ridurre i tempi, a condizione che il sistema abbia delle limitazioni di movimento.

Considera i codificatori seno e coseno. Producono un segnale di uscita coseno o seno. Inoltre, con l'aiuto del dispositivo di interpolazione di potenza, da essi si formano impulsi. I segnali di questo tipo possono essere ridimensionati. L'encoder è alimentato da una tensione di 5 volt.

Il segnale "A" è un segnale a impulsi di tipo diretto. Il numero di impulsi da questo segnale arriva ad ogni giro. È uguale a 500 (risoluzione del sensore).

Anche il segnale "B" è un segnale a impulsi diretti. Da esso, ad ogni giro, viene ricevuto il numero di impulsi secondo la discrezione del sensore, che viene spostato dal canale "A" di 90 gradi (500).

Il segnale "R" è il segnale della tacca "zero". Con un giro del sensore si ottiene un impulso.

Negli encoder industriali, un segnale di differenziazione viene utilizzato per funzionare con un convertitore di frequenza (chastotnik). Il suo nome è complicato, ma in realtà tutto è semplice. Tutti i canali vengono copiati individualmente dalla loro inversione. Ciò è necessario per dare un segnale a distanze considerevoli. Il canale di uscita dell'encoder è collegato ad un ricevitore speciale realizzato su amplificatori di tipo operazionale. L'impulso è infine determinato nell'aggregato di due segnali.

Connessione

La connessione è semplice. Colleghiamo una tensione di 5 volt alle uscite dell'encoder. Abbiamo una disposizione: filo marrone - 0 V, bianco - +5 V, rosa, verde e rosso - A, B, R.

Il programma di collegamento dell'encoder si basa sugli allarmi dei canali A e B. Gli allarmi vengono attivati ​​sul fronte di salita. Risulta che l'encoder frena al momento dell'intersezione del raster e il segnale di uscita del canale rimane sempre positivo. Gli impulsi vengono contati continuamente da un contatore.

Nel nostro caso, non utilizzeremo gli interrupt, perché stiamo lavorando con 4 sensori, vengono azionati contemporaneamente. Se si utilizza lo schema di interruzione, ci sarà sicuramente una situazione di perdita di impulsi. Risolviamo questo problema impostando l'icona per la presenza di movimento. E abbiamo considerato il funzionamento degli encoder industriali.

Funzionamento del contatore di impulsi basato sul modulo encoder

Il contatore funziona in combinazione con un modulo indicatore a sette cifre, che visualizzerà il numero di impulsi avvolti dall'encoder. Quando abilitato, il valore del contatore è zero.

Ruotare la manopola dell'encoder in senso orario. Il valore del contatore viene incrementato di uno ogni volta che si fa clic sull'encoder. Il numero più grande che puoi ottenere è 999999999. Questo numero dovrebbe riempire tutte le cifre del nostro indicatore a sette segmenti. Se si ruota ulteriormente la manopola, il contatore si azzererà, ricominciando a contare da zero.

Ad esempio, avvolgiamo 120 impulsi. Ora gira indietro ruotando la maniglia in senso antiorario. L'asse centrale dell'encoder funziona come un pulsante. Cancella da zero le cifre libere dell'indicatore. Il pulsante ha un leggero rimbalzo dei contatti, quindi lo spegnimento e l'accensione non avvengono immediatamente. A livello di codice, le chiacchiere vengono eliminate. Questa è la base per lavorare con il modulo encoder.

Ho voluto a lungo adattare un controllo del volume fatto di codificatore. Dovrai collegare questo regolatore a USB in modo che tutto sia "in modo adulto" (e non puoi collegare un dispositivo esterno a un laptop in nessun altro modo). Giriamo l'encoder a sinistra - il volume dovrebbe diminuire, a destra - dovrebbe aumentare. Premi la manopola dell'encoder verso il basso: lanciamo qualche programma utile o passiamo al controllo del tono.

Per coloro che non sanno cosa sia un codificatore, è una svolta, come una manopola del volume basata su un resistore convenzionale, solo questa svolta non ha posizioni limite: ruota quanto vuoi in qualsiasi direzione. L'encoder gira con piacevoli clic morbidi, ma sembra un normale resistore variabile.

Tali dispositivi non sono rari nelle moderne autoradio e qualsiasi dispositivo domestico, la cui interfaccia utente viene elaborata da un microcontrollore (e questo è un qualsiasi elettrodomestico) e dove è necessaria una regolazione o una messa a punto fluide. Un terzo contatto è spesso integrato nell'encoder, che funziona come un pulsante sull'impugnatura: quando si spinge l'impugnatura dell'encoder verso il basso (lungo l'asse), questo pulsante funziona. Arricchisce notevolmente le possibilità dell'interfaccia utente: su un codificatore puoi costruire l'intero sistema di controllo di un dispositivo elettronico (ma il programmatore è emorragico, ma queste sono già sciocchezze). Ho appena avuto un codificatore del genere.

Il principio di funzionamento dell'encoder è abbastanza semplice: ha solo due contatti (il pulsante sull'impugnatura non conta), che iniziano a chiudersi non appena l'utente inizia a ruotare la manopola dell'encoder. I contatti sono collegati a due gambe del microcontrollore (che funzionano come ingressi digitali) e quando la manopola dell'encoder viene ruotata, su queste gambe compaiono degli impulsi, in base alla fase e al numero di cui il microcontrollore determina il senso di rotazione e l'angolo di rotazione della manopola dell'encoder.

Per far funzionare il controllo del volume, devi risolvere almeno tre problemi di ingegneria:

Passo 1. Creazione di un dispositivo USB a bassa velocità su una breadboard.
Passo 2. Collegare un encoder a questo dispositivo USB, farlo elaborare dal microcontrollore e trasferire le informazioni sulla rotazione dell'encoder al computer.
Passaggio 3. Scopri come puoi controllare a livello di codice il controllo del volume. Sicuramente c'è qualche API multimediale che ti permette di farlo. Il programma minimo: è necessario scrivere un programma che riceverà segnali da un dispositivo USB e controllerà il volume. Sarebbe bello, ovviamente, scrivere un driver, ma è spaventoso affrontarlo. Faremmo meglio a lasciarlo per dopo.

Quindi, descriverò passo dopo passo il processo di creazione di un regolatore. Ometto i dettagli, altrimenti sarà troppo noioso. Per chi fosse interessato, consultare il codice sorgente e la documentazione ai link.

[Passaggio 1: crea un dispositivo USB a bassa velocità su una breadboard]

Questo passaggio è passato senza nemmeno iniziare - in qualche modo troppo semplice e banale. Stupidamente scaricato un progetto di esempio dal link. Corretto il file usbconfig.h - per lo show-off chiamato il mio dispositivo DIMOSTRAZIONE ENCODER, perché più fantasia non bastava. Ho controllato il tipo di processore (ATmega16) nel Makefile, la frequenza del quarzo (16 MHz) - in modo che corrisponda alla mia breadboard AVR-USB-MEGA16. Ho compilato il progetto in AVRStudio, ho eseguito il flashing della breadboard, l'ho collegata al computer - tutto si è avviato subito, il mio dispositivo USB ha funzionato correttamente come porta COM virtuale - tutto è esattamente come scritto nell'articolo.

[Passaggio 2. Collegare l'encoder al dispositivo USB]

Questo passaggio ha causato i miei più grandi timori che tutto avrebbe funzionato come dovrebbe. Che avrei collegato l'encoder e sarei stato in grado di leggerlo - su questo non avevo dubbi. C'erano dubbi sul fatto che potessi leggerlo con alta qualità quando anche l'elaborazione del protocollo USB funziona in background - dopotutto, questo non è un compito facile per il microcontrollore (come si è scoperto in seguito, ero preoccupato invano).

Come al solito, ho iniziato a frugare in Internet alla ricerca di subroutine già pronte per la lettura dell'encoder. Ho trovato ciò di cui avevo bisogno molto rapidamente: solo per AVR, codice C molto semplice, file encoder.ce encoder.h. Dì quello che ti piace, ma l'open source è una cosa interessante.

Ho attaccato due led di segnalazione - VERDE e GIALLO - per indicare il senso di rotazione dell'encoder. Per comodità ho collegato l'encoder direttamente al connettore ISP, sfruttando il fatto che i segnali MOSI, MISO e SCK sono solo le gambe PB5, PB6 e PB7 del microcontrollore ATmega16 (ho collegato lì le fasi A e B, oltre a un pulsante codificatore).

Definizioni corrette delle gambe, aggiunto codice di inizializzazione. Attaccato il modulo encoder.c al progetto. Aggiunto il controllo dei LED verdi e gialli al loop principale quando infa proviene dall'encoder. Ho legato il LED ROSSO al pulsante dell'encoder: quando lo premiamo si accende il LED rosso, quando lo rilasci si spegne. Compilato, flashato - funziona. Ruoto la manopola verso sinistra e, a tempo con i clic dell'encoder, il LED verde lampeggia. Giro la manopola a destra: il LED giallo lampeggia. Nonostante il fatto che l'encoder venga letto utilizzando il metodo polling, grazie all'efficiente codice per la lettura dell'encoder, NON ci sono lamentele anche quando si lavora con la libreria V-USB (rispetto, Pashgan!). Aggiunto l'output delle informazioni dall'encoder alla porta COM virtuale (ruoto l'encoder a sinistra, emetto i segni meno "-" sulla console, ruotalo a destra, emetto i segni più "+" sulla console ). Secondo il timer, ogni 10 ms visualizzo lo stato del pulsante dell'encoder e lo indico con un LED rosso (il pulsante viene premuto - trasmetto il carattere "1", rilasciato - "0"). Tutto funziona. Cose noiose.

In conclusione, ho eliminato i moduli cmd.c, crc16.c, eepromutil.c, strval.c. La quantità di codice è scesa a 3 kilobyte: ottimo, ora si adatta alla memoria ATtiny45 (è possibile utilizzare la breadboard AVR-USB-TINY45 in futuro, è più piccola ed economica).

[Passaggio 3. Comprendi come puoi controllare a livello di codice il controllo del volume]

Come al solito, ho cercato su Google la domanda. Eliminato un mucchio di immondizia, e infine rastrellato una perla -. La prossima è la questione della tecnologia. Tiro fuori il mio designer preferito per bambini: Visual Studio. Senza pensare a nulla, creo un'applicazione basata su dialoghi con una procedura guidata. Lancio un motore di controllo del volume sul pannello, vi lego una variabile, aggiungo un gestore per la posizione del motore. All'avvio dell'applicazione, ho impostato il motore su un minimo di 0 e un massimo di 65535 (per far corrispondere i limiti del valore del volume, che viene manipolato dalle librerie di controllo del mixer). Ho letto per funzione mixerGetControlDetails il valore del volume corrente e impostare il dispositivo di scorrimento nella posizione appropriata. Nel gestore della posizione del motore, è vero il contrario: leggo la posizione del motore e la funzione mixerSetControlDetails Ho impostato il volume desiderato. Faccio il controllo del volume esattamente come è scritto nell'articolo. Controllato - funziona.

Ora l'unica cosa rimasta è leggere cosa viene dalla porta COM virtuale (abbiamo un dispositivo USB appena sfornato con un codificatore appeso). Se è arrivato un segno meno (-), spostare il cursore a sinistra (ridurre il volume), il segno più (+), quindi spostare il cursore a destra (aumentare il volume). Se vengono visualizzati i caratteri 0 e 1, controlliamo di conseguenza lo stato della casella di controllo (solo per indicare se il pulsante dell'encoder è premuto o meno). Puoi lavorare con una porta COM proprio come con un file normale (vedi ). Inizializziamo la connessione alla porta COM come l'apertura di un file (chiamando ::Crea file) in modalità di blocco. Lanciamo un thread separato, aggiungiamo la lettura del file al ciclo infinito (usando una chiamata di blocco ::LeggiFile) un carattere alla volta e analizziamo questo carattere. In base a quale simbolo è arrivato, giriamo il motore di scorrimento nella giusta direzione (il volume verrà regolato dal gestore di scorrimento) o aggiorniamo lo stato della casella di controllo. Controllato - funziona.

Questo è tutto, in effetti. Quindi puoi impegnarti in un miglioramento infinito (e probabilmente inutile). Effettuare una ricerca automatica della porta COM virtuale desiderata (ora, per semplicità, il nome della porta COM viene passato attraverso la riga di comando). Converti dispositivo USB da Centro per la prevenzione e il controllo delle malattie-lezione attiva NASCOSTO- può semplificare il codice del dispositivo USB e facilitare la ricerca e l'apertura programmatica del dispositivo sul computer tramite VID e HID. Oppure scrivi un servizio invece di un programma (quindi non devi eseguire un programma separato). O anche un autista. Questo è molto interessante, ma non so come (forse uno degli Habravchan insegnerà l'ingegno? ..). Allega qualche azione al pulsante dell'encoder. E così via all'infinito.

Spero che la mia ricerca sarà utile a qualcuno nei propri sviluppi. Se mi sono perso qualcosa, sarò felice di sentire commenti nei commenti.

[UPD120803]

Una persona alfabetizzata assemblata su un microcontrollore AVR

Encoder incrementale esteriormente simile a potenziometro, ma a differenza di un potenziometro non ha posizioni estreme, può ruotare in entrambi i sensi un numero illimitato di giri. Va inoltre notato che l'encoder incrementale non ruota in modo fluido come un potenziometro, ma a passi. Può essere visto sull'autoradio, oscilloscopio, music center, lavatrice e altre apparecchiature, dove la regolazione di alcuni parametri viene effettuata su un'ampia gamma. Naturalmente, i parametri possono essere modificati anche utilizzando i pulsanti, ad esempio, per aumentare il volume della musica di 20 valori, quando si controlla il pulsante, è necessario premerlo 20 volte e quando si controlla l'encoder, ruotarlo su un determinato angolo, a seconda dell'algoritmo di elaborazione.

Encoder incrementale sono due contatti il cui ordine di chiusura dipende dal senso di rotazione.


Infatti l'encoder incrementale converte la rotazione dell'albero in impulsi elettrici, contenente informazioni sul senso di rotazione.

Assembliamo il circuito di prova mostrato nell'immagine sopra e colleghiamo ai pin A e B oscilloscopio, resistori pull-up - 4.7K.
Ruotare l'encoder in senso orario.


Ora in senso antiorario.


Gli oscillogrammi mostrano che, a seconda del senso di rotazione, l'ordine di chiusura dei contatti cambia. Ma la parte anteriore non è sempre così bella.


Poiché i contatti sono meccanici, sono inclini a rimbalzare, ovvero quando si chiudono a causa dell'elasticità dei materiali, si verificano più chiusure e aperture incontrollate, che possono essere viste nell'oscillogramma sopra.

Ci sono due modi per affrontare il tintinnio. il primo consiste nell'aggiungere condensatori e resistori, come mostrato nella figura sottostante.


Poiché il rimbalzo è un fenomeno a breve termine, viene facilmente estinto dal condensatore.


L'oscillogramma mostra che dopo aver installato i condensatori, i fronti sono diventati meno ripidi e il rimbalzo è scomparso.

Secondo modo- software e tutto dipende dall'implementazione del polling delle uscite encoder. Se una stato dell'encoder monitorato da interrupt esterni, quindi dopo l'attivazione dell'interruzione, è necessario effettuare un ritardo di 20 - 30 millisecondi, durante i quali l'MK non risponderà a un cambiamento nello stato dell'uscita, ovvero non sentirà un rimbalzo. Se una Polling uscite encoder implementate su un timer, quindi l'intervallo tra i sondaggi dovrebbe essere maggiore della durata del rimbalzo, gli stessi 20 -30 millisecondi.

consideriamo metodi di elaborazione dei dati provenienti dall'encoder.
Il primo metodo consiste nel collegare una delle gambe dell'encoder all'uscita degli interrupt esterni e configurarla per interrompere su un fronte di discesa. Nell'interruzione, controlliamo lo stato dell'altra gamba e se è zero, la rotazione avviene in una direzione, altrimenti nell'altra. Di seguito è riportato il codice che implementa questo metodo per AVR.
#includere ISR(INT2_vect) ( se (PINB & 0X02) ( PORTB |= (1<<0); } else { PORTB &= ~(1<<0); } //антидребезг _delay_ms(20); //сбрасываем флаг прерывания вызванный дребезгом GIFR = (1<Ruotando l'encoder in una direzione si accende il led, ruotandolo nell'altra si spegne.

Il secondo metodo è confronto tra lo stato attuale e quello precedente. Esprimiamo i livelli logici del treno di impulsi come zeri e uno.


Quindi otteniamo un numero finito di stati dell'encoder. La prima cifra è il livello logico della prima uscita dell'encoder, la seconda è il livello logico della seconda uscita.

Supponiamo che l'ultimo stato in cui si trova l'encoder sia uguale a tre, se lo stato successivo è uguale a uno, allora ruoti in una direzione, se due, quindi nell'altra. Si scopre che è possibile correggere la transizione da uno stato all'altro e determinare la direzione di rotazione, ma l'implementazione più semplice è quando si passa da 11 a 01 e 10. Di seguito è riportato il codice che implementa l'algoritmo descritto per AVR,
#define F_CPU 8000000UL #includi #includere uint8_t last_state = 0; ISR(TIMER0_COMP_vect) ( //entrambe le uscite encoder sono collegate ai pin 2 e 3 della porta B //legge il loro stato uint8_t current_state = (PINB & 0x06)>>1; //considera la transizione solo se lo stato precedente è 11 //e se non è uguale al nuovo if ((last_state == 3) && (last_state != current_state)) ( //se il nuovo stato è 01 - accende il LED if(current_state == 1) ( PORTB |= 0x01; ) //se il nuovo stato è 10 - spegni il LED if(current_state == 2) ( PORTB &= ~0x01; ) ) //quando si esce dall'interrupt, lo stato corrente diventa il passato last_state = current_state ; ) int main(void) ( //due ingressi per il collegamento dell'encoder DDRB &= ~ 0x06; //alza gli ingressi al PORTB di alimentazione |= 0x06; //uscita per il collegamento del LED DDRB |= 0x01; // impostare il timer in modo che si azzeri per coincidenza TCCR0=(1<È tutto.
Encoder acquistato

Un encoder è una cosa che sembra un resistore variabile, ma, a differenza di quest'ultimo, non ha limitatori e può ruotare all'infinito in qualsiasi direzione. Con l'aiuto di un encoder è molto comodo organizzare tutti i tipi di menu su schermo, in generale un encoder "premebile" (cioè se può funzionare anche da pulsante) è l'ideale per organizzare ciclici unidimensionali menu.

Esistono due tipi di encoder: assoluto - che emette immediatamente il codice dell'angolo di rotazione e incrementale - che emette impulsi durante la rotazione. Per quest'ultimo, il microcontrollore dovrebbe essere coinvolto nel conteggio degli impulsi e nella loro conversione in un angolo di rotazione.

Dal punto di vista progettuale gli encoder sono meccanici ed ottici, nei primi vengono generati degli impulsi durante la rotazione su una coppia di contatti quando vengono chiusi da un contatto strisciante dell'albero, nel secondo i fotodiodi fungono da contatti e i il ruolo del contattore è un LED che brilla attraverso un disco scanalato (ciao a un mouse a sfera) .

Sebbene ci siano molte informazioni sulla programmazione dei codificatori sulla rete, oltre a librerie già pronte per questo, sono tutti in qualche modo inutilmente ingombranti (IMHO) - il polling dello stato è solitamente implementato come una macchina a stati sotto forma di interruttore blocco con if nidificati, che sembra alquanto complicato (specialmente se scritto in assembler). Tuttavia, l'implementazione potrebbe essere più semplice.

I più popolari nell'economia nazionale sono gli encoder incrementali meccanici economici e li considereremo. Il processo di rotazione dell'albero dell'encoder è schematicamente mostrato in figura (in alto - rotazione in senso orario, in basso - in senso antiorario):


Qui A e B sono gli stessi contatti, i livelli a cui il microcontrollore deve elaborare. Il contatto mobile li chiude a terra se non cadono nei suoi fori. Qui notiamo che la figura mostra solo quattro fori per semplicità. In effetti, ci sono molti più di questi fori (di nuovo, ricordiamo il mouse con la palla e come appare la sua rotella di interruttore ottico). Conclusioni A e B sono tirate su da resistori alla tensione di alimentazione. Di conseguenza, quando ruotato, si ottengono i diagrammi mostrati nella figura sopra.

Lascia che entrambi i contatti cadano inizialmente nel foro, quindi avranno un livello di alta tensione (vengono anche tirati su per l'alimentazione). Inoltre, ruotando in senso orario, il contatto A sarà il primo ad essere chiuso a massa, quindi si unirà il contatto B. Quindi, raggiunto il prossimo foro nel disco, il contatto A si aprirà e raggiungerà un livello alto, dopodiché il contatto B Dopo questi movimenti, i contatti torneranno allo stato originale e, con un'ulteriore rotazione, questo diagramma verrà ripetuto ciclicamente.

Pertanto, risulta che lo stato attuale dell'encoder è descritto da un valore a due bit. Ma di per sé, lo stato attuale contiene poche informazioni utili e per l'analisi della rotazione deve essere considerato insieme al valore dello stato precedente. E questa coppia determina già in modo inequivocabile la direzione di rotazione della maniglia. Per comodità, prendiamo un numero a quattro bit, i cui due byte alti contengono gli stati precedenti dei contatti A e B, ei due byte bassi contengono quelli correnti.

E quando si ruota in senso antiorario

Binario Decimale
1110 14
0001 1
0010 2
0111 7

Ora l'algoritmo per determinare il senso di rotazione dell'encoder sembra molto semplice: otteniamo il valore e confrontiamo se rientra in uno degli insiemi (2, 4, 11, 13) e (1, 7, 8, 14). Se sì, allora abbiamo una svolta nella direzione corrispondente. Altrimenti, l'albero non ha ruotato affatto o ha ruotato così velocemente da saltare diversi stati (se ciò accade spesso, dovresti pensare ad aumentare la frequenza di polling dello stato) o si è verificato un "rimbalzo" di contatti. Senza approfondire il motivo, tutti gli altri valori possono essere tranquillamente ignorati.

Ad esempio, si consideri il funzionamento di un encoder in combinazione con un microcontrollore AVR:


Qui vengono utilizzate per la connessione due uscite inferiori della porta PB del microcontrollore ATMega8. Una coppia di resistori tira queste linee fino alla tensione di alimentazione (poiché i resistori interni dell'atmega potrebbero non essere sufficienti per un funzionamento stabile qui), una coppia di condensatori è installata per sopprimere il rumore dell'impulso.

Per un tale schema di connessione, puoi abbozzare la seguente implementazione nel linguaggio C:

uint8_t statico encoderGetVal() ( return PINB & 3; ) uint8_t statico encoderGetCode() ( uint8_t statico prev; uint8_t val = encoderGetVal(); uint8_t code = (prev<< 2) | val; prev = val; return code; } static void encoderInit() { DDRB &= ~0b11; PORTB |= 0b11; encoderGetCode(); } void onEncoderEvent(bool direction); void encoderCheck() { uint8_t code = encoderGetCode(); if (code == 1 || code == 7 || code == 8 || code == 14) { onEncoderEvent(true); } else if (code == 2 || code == 4 || code == 11 || code == 13) { onEncoderEvent(false); } }

Il codice è semplice da disonorare: un paio di if-s e nessun automa finito. La funzione encoderInit() viene chiamata all'inizio per inizializzare la porta e ricordare il valore iniziale. La funzione encoderCheck() viene chiamata nel loop degli eventi (all'interno di main() o su un timer). Il gestore onEncoderEvent(bool) verrà chiamato ogni volta che l'encoder ruota e riceve il flag della direzione di rotazione.

Ma c'è un punto importante qui: l'encoder è una cosa sensibile, e se si tenta di elaborare, ad esempio, gli eventi di navigazione del menu in questo modo, anche una piccola rotazione della manopola dell'encoder chiamerà ripetutamente il gestore onEncoderEvent(), di conseguenza, il cursore del menu invece di spostarsi all'elemento successivo/precedente, volerà immediatamente alla fine/inizio dell'elenco. È possibile regolare la sensibilità dell'encoder modificando la frequenza di chiamata encoderCheck() (in genere la frequenza ottimale è ~ 10 Hz). Allo stesso tempo, il metodo encoderGetCode() dovrebbe essere chiamato il più spesso possibile in modo da avere sempre il valore attuale dell'ultimo stato dei contatti (con una frequenza intorno a ~ 100 Hz).

In assembler, questo codice potrebbe assomigliare a questo:

EQU encoder_port PORTB .EQU encoder_pin PINB .EQU encoder_ddr DDRB .DSEG .ORG SRAM_START sEncoderPrev: .BYTE 1 ... .CSEG .ORG $0000 ... Encoder_init: cbi encoder_ddr, 0 cbi encoder_ddr, 1 sbi encoder_port, 0 sbi encoder_port, 1 in r0, encoder_pin andi r0, 3 sts sEncoderPrev, r0 ... Encoder_check lds ZL, sEncoderPrev lsl ZL lsl ZL in r0, encoder_pin andi r0, 3 sts sEncoderPrev, r0 o ZL, r0 ; 1 7 8 14 -> in senso orario cpi ZL, 1 breq Encoder_senso cpi ZL, 7 breq Encoder_senso cpi ZL, 8 breq Encoder_senso cpi ZL, 14 breq Encoder_orario ; 2 4 11 13 -> antiorario cpi ZL, 2 breq Encoder_senso antiorario cpi ZL, 4 breq Encoder_senso antiorario cpi ZL, 11 breq Encoder_senso antiorario cpi ZL, 13 breq Encoder_senso antiorario rjmp Encoder_done Encoder_orario: ; ; ecco il codice per il gestore di rotazione in senso orario; Codificatore_in senso antiorario: ; ; ecco il codice del gestore di rotazione in senso antiorario; Intervallo_enc_done.

Articoli correlati in alto