Encoder con schema di collegamento dei pulsanti. Come utilizzare un codificatore rotativo in un progetto di microcontrollore

Il modulo encoder KY-040 è un sensore meccanico dell'angolo di rotazione; converte l'angolo di rotazione di un oggetto rotante (ad esempio un albero) in segnali elettrici sfalsati di 90 gradi l'uno rispetto all'altro. Questo modulo ha tre uscite: CLK, DT e SW. I segnali sfalsati di 90 gradi l'uno rispetto all'altro appaiono esattamente sui pin CLK e DT quando ruotati in senso orario/antiorario, il pin SW viene utilizzato per ottenere lo stato dell'asse centrale dell'encoder, che funziona come un pulsante.

Quindi, senza entrare nei dettagli del dispositivo in-circuit dell’encoder (di cui parleremo in un articolo a parte), colleghiamolo alla scheda Arduino Uno. Schema di collegamento del modulo encoder in combinazione con un indicatore a sette segmenti a più cifre:

Ci basterà semplicemente analizzare lo stato dei segnali che danno origine ai pin CLK e DT; per questo è disponibile un piccolo schema elettrico che mostrerà come si spostano i segnali quando vengono ruotati in un senso o nell'altro.

Il diagramma mostra che ogni volta che il segnale A (pin CLK dell'encoder) passa da alto a basso, viene letto lo stato del segnale B (pin DT dell'encoder). Se il segnale B fornisce un livello di segnale alto, ciò significa che l'encoder ruota in senso orario. Se il segnale B fornisce un livello di segnale basso quando il segnale A passa dal livello basso a quello alto, significa che l'encoder ruota in senso antiorario. Leggendo entrambi questi segnali nel programma, è possibile determinare la direzione di rotazione; inoltre, quando si contano gli impulsi del segnale B, è possibile incrementare o decrementare il contatore degli impulsi del programma.

Per leggere i segnali A e B, nonché i segnali dall'asse centrale dell'encoder (lascia che te lo ricordi, funziona come un pulsante), puoi utilizzare il design descritto di seguito. Questo disegno può essere incorporato in uno schizzo, aggiungendovi varie funzionalità, tutto è limitato solo dal desiderio e dall'immaginazione dello sviluppatore. Il corpo della struttura è abbastanza ben commentato; in futuro, per semplificare il testo dello schizzo, sarà possibile eliminare i commenti. Quindi, il progetto per leggere e convertire i segnali dell'encoder in dati utili:

//Variabili temporanee per la memorizzazione dei livelli di segnale //ricevuti dall'encoder unsigned char encoder_A, encoder_B, encoder_A_prev; //Variabile per tracciare la pressione dei pulsanti - //l'asse centrale dell'encoder static bool SW_State = false; void setup() ( // Impostazioni preliminari // Dichiarazioni di variabili // Inizializzazione delle porte, ecc. ) void loop() ( // CLK collegato al pin 3 sulla scheda Arduino // DT collegato al pin 4 sulla scheda Arduino / / Leggiamo i valori delle uscite dell'encoder //E li memorizziamo nelle variabili encoder_A = digitalRead(3); encoder_B = digitalRead(4); //Se il livello del segnale A è basso, //e nel ciclo precedente era alto if(!encoder_A && encoder_A_prev) ( //Se il livello del segnale B è alto if(encoder_B) ( //Ciò significa che la rotazione avviene in senso orario //Qui puoi inserire un'operazione di incremento //Qui puoi inserire una qualsiasi delle le tue //operazioni di elaborazione dati nella direzione desiderata) //Se il livello del segnale è troppo basso altrimenti ( //quindi la rotazione avviene in senso antiorario //qui puoi inserire un'operazione di decremento //qui puoi inserirne una tua // operazioni di elaborazione dati nella direzione desiderata) ) //È imperativo salvare lo stato del livello di segnale attuale A // per utilizzare questo valore nel successivo ciclo di scansione del programma encoder_A_prev = encoder_A; //Lavoriamo con l'asse centrale dell'encoder: un pulsante //Questo pezzo di codice forma una sorta di trigger flip-flop //Leggi il valore del pin 2 sulla scheda Arduino //a cui si collega il contatto SW dell'encoder è collegato //Se viene premuto l'asse centrale, il segnale SW sarà di livello basso if(!digitalRead(2)) ( //Se la variabile SW_State è impostata su false, impostala su true if(!SW_State) ( / /E ricorda lo stato SW_State = true; ) //E viceversa: se la variabile SW_State è impostata su true, //reimpostala su false altrimenti ( //E ricorda lo stato SW_State = false; ) ) )

Di seguito è mostrato uno schizzo per l'elaborazione dei segnali dell'encoder e la visualizzazione del valore del contatore sul display. Questo schizzo contiene un progetto integrato per la lettura e la conversione dei segnali dell'encoder, descritto sopra.

#include "LedControl.h" /* * Colleghiamo la libreria LedControl.h * e creiamo un oggetto della classe LedControl * in questo caso un display a 7 segmenti con driver MAX72xx * deve essere collegato alla scheda Arduino come segue : * Arduino -> Modulo display MAX72xx * Arduino -> Modulo display MAX72xx * Arduino -> Modulo display MAX72xx * Arduino -> Modulo display MAX72xx * Arduino -> Modulo display MAX72xx * Arduino -> Modulo encoder * Arduino -> Modulo encoder * Arduino -> Modulo encoder */ LedControl lc = LedControl(12, 11, 10, 1); //Nomina gli indirizzi delle porte sulla scheda Arduino const int Dir = 4; const int Passo = 3; const int Switch = 2; //Contatore - variabile per memorizzare il valore del contatore static long Counter = 0; //SW_State - flag di trigger per tracciare la pressatura dell'asse centrale static bool SW_State = false; //Variabili temporanee per la memorizzazione dei livelli di segnale dell'encoder unsigned char encoder_A, encoder_B, encoder_A_prev; void setup() ( //Il dispositivo (display a 7 segmenti) esce dalla modalità di sospensione lc.shutdown(0, false); //Imposta la luminosità del display su 8 //Modalità di luminosità totali possibili da 0 a 15 lc. setIntensity(0 ,8); //Cancella il display lc.clearDisplay(0); //Configura le porte per l'encoder pinMode(Dir, INPUT); pinMode(Step, INPUT); pinMode(Switch, INPUT); ) void loop() ( // Leggi i valori delle uscite dell'encoder //E memorizzali nelle variabili encoder_A = digitalRead(Step); encoder_B = digitalRead(Dir); //Se il livello del segnale A è basso, //e nel ciclo precedente era alto if(!encoder_A && encoder_A_prev) ( //Se il livello del segnale B è alto if(encoder_B) ( //Ciò significa che la rotazione avviene in senso orario //La nostra condizione: //Se il valore del contatore è maggiore superiore o uguale al numero massimo if(Counter >= 99999999) ( //Reimposta il valore del contatore Counter = 0; ) else ( //Altrimenti incrementa di uno ad ogni clic Counter ++; ) ) //Se il livello del segnale B è basso else ( //Ciò significa che la rotazione è in senso antiorario //Se il valore del contatore è inferiore o uguale a zero if(Contatore<= 0) { //проинициализировать значение максимальным числом Counter = 99999999; } else { //Иначе декрементировать при каждом щелчке на единицу Counter --; } } } //Обязательно нужно сохранить состояние текущего уровня сигнала А //для использования этого значения в следующем цикле сканирования программы encoder_A_prev = encoder_A; //Работаем с центральной осью энкодера - кнопкой //Этот кусок кода образует собой как бы перекидной триггер //Считываем значение пина 2 на плате Arduino //которомый проименован как Switch //Если центральная ось нажата - то сигнал Switch будет иметь низкий уровень if(!digitalRead(Switch)) { //Если переменная SW_State установлена в false то установить её в true if(!SW_State) { //И запомнить состояние SW_State = true; } //И наоборот - если переменная SW_State установлена в true, //то сбросить её в false else { //И запомнить состояние SW_State = false; } } //Часть программы которая заполняет разряды //семисегментного дисплея значением счетчика long intCounter = Counter; int divCounter; for(int i = 0; i < 8; i ++) { divCounter = intCounter % 10; intCounter = intCounter / 10; if(intCounter == 0 && SW_State) { if(divCounter == 0) { if(i == 0) { lc.setChar(0, 0, "0", false); } else { lc.setChar(0, i, " ", false); } } else { lc.setDigit(0, i, divCounter, false); } } else { lc.setDigit(0, i, divCounter, false); } } }

Video di come funziona:


Ci auguriamo che il materiale contenuto in questo articolo ti sia piaciuto; lascia le tue domande, suggerimenti e critiche nei commenti qui sotto.

  • Utilizzo di encoder ottici industriali in Arduino
Abilita Javascript affinché i commenti funzionino.

Da questo articolo imparerai cos'è un codificatore, perché è necessario e come collegarlo a un microcontrollore. Se hai utilizzato una moderna lavatrice, un forno a microonde o un sistema audio, molto probabilmente hai già avuto a che fare con un codificatore senza saperlo. Ad esempio, la maggior parte dei moderni impianti stereo domestici e per auto utilizzano codificatori per regolare il volume audio.
Un encoder o sensore dell'angolo di rotazione è un dispositivo elettromeccanico progettato per convertire la posizione angolare di un albero o di un asse in segnali elettrici. Esistono due tipi principali di encoder: incrementale e assoluto.
Durante la rotazione, l'encoder incrementale genera impulsi, il cui numero è proporzionale all'angolo di rotazione. Contando il numero di questi impulsi otterremo l'angolo di rotazione dell'albero dell'encoder rispetto alla sua posizione iniziale. Questo tipo di encoder non genera impulsi in uscita quando il suo albero è fermo. Gli encoder incrementali sono ampiamente utilizzati nei controlli industriali, negli elettrodomestici e nelle apparecchiature musicali.
Un encoder assoluto produce un codice univoco per ogni posizione del suo albero. A differenza di un encoder incrementale non necessita di contatore; l'angolo di rotazione è sempre noto. Un encoder assoluto genera un segnale sia quando l'albero ruota che quando è fermo. Un encoder assoluto non perde le informazioni sulla sua posizione in caso di interruzione dell'alimentazione e non richiede il ritorno alla posizione iniziale. Questo tipo di encoder viene utilizzato in apparecchiature industriali: robotica, macchine utensili, linee di trasporto.
Vorrei parlare dell'abbinamento di un encoder meccanico incrementale con un microcontrollore. Per fare ciò, ho acquistato un encoder incrementale da Bourns - PEC12-4220F-S0024. Ecco la decodifica del suo nome secondo la scheda tecnica: PEC12 – modello, 4 – posizione verticale dei reofori, 2 – 24 stopper, 20 – lunghezza asta in mm, S – presenza di un pulsante, 0024 – 24 impulsi per giro.

Ha 5 pin. 2 pin nella foto a sinistra sono i pin dei pulsanti, 3 pin nella foto a destra sono i pin dell'encoder. Di questi, 2 sono di segnalazione e 1 è generale. Lui è nel mezzo. Lo schema di collegamento dell'encoder non è diverso dal collegamento dei pulsanti convenzionali. Colleghiamo i pin di segnale dell'encoder a qualsiasi porta di ingresso/uscita del microcontrollore. Posizioniamo a terra l'uscita comune dell'encoder. Per proteggersi dal rimbalzo dei contatti, sarebbe una buona idea aggiungere un paio di condensatori ceramici in più con un valore di diversi nanofarad. Configuriamo i pin del microcontrollore nel programma come ingressi e accendiamo le resistenze pull-up. Si possono usare quelli esterni.

Quando la manopola dell'encoder è ferma, ci sono unità logiche agli ingressi del microcontrollore. Quando si gira la manopola dell'encoder, sui pin del microcontrollore compaiono due segnali rettangolari, spostati l'uno rispetto all'altro. Il senso di rotazione dell'albero dell'encoder determina quale segnale guiderà l'altro. La figura seguente mostra le possibili opzioni di segnale per un caso ideale.


All'interno dell'encoder sono presenti dei contatti che, quando ruotati, si chiudono o si aprono. Questo processo è naturalmente accompagnato da un rimbalzo, quindi i segnali reali potrebbero assomigliare a questo.


I segnali sono stati prelevati da un vecchio encoder, acceso senza condensatori di filtro.


L'algoritmo di elaborazione del segnale dell'encoder è il seguente. La funzione di polling dell'encoder viene avviata nel gestore degli interrupt del timer. Legge i livelli logici presenti sui pin del microcontrollore a cui è collegato l'encoder e li scrive in una variabile temporanea. All'interno di una funzione è presente una variabile statica (una variabile che mantiene il suo valore quando la funzione esce) che memorizza la sequenza degli stati precedenti. Utilizzando una maschera di bit, il microcontrollore estrae l'ultimo stato da questa variabile e lo confronta con quello corrente per determinare se si sono verificati cambiamenti. Se gli stati sono uguali la funzione termina; se sono diversi il valore della variabile statica viene spostato a sinistra di 2 bit e lo stato corrente viene scritto nello spazio “liberato”. Pertanto, se l'albero dell'encoder ruota, la funzione memorizzerà costantemente una determinata sequenza di codici ripetitiva. Ruotando verso destra sarà 11100001. Ruotando verso sinistra sarà 11010010. Utilizzando queste sequenze il microcontrollore capirà in quale direzione avviene la rotazione.

Il codice sorgente per lavorare con l'encoder può essere scaricato. L'archivio contiene due file: encoder.h e encoder.c. L'intestazione specifica la porta e i numeri di pin a cui è collegato l'encoder, le costanti LEFT_SPIN e RIGHT_SPIN. Qui vengono descritti anche i prototipi delle funzioni. Il file C contiene l'implementazione delle funzioni.


void InitEncoder(void)– inizializza i pin della porta.

void PollEncoder(void)
– interroga l'encoder una volta. Se viene rilevata la rotazione, scrive una delle costanti nel buffer; in caso contrario, esce semplicemente.

carattere senza segno GetStateEncoder(void)
– restituisce il contenuto del buffer e lo cancella.

Di solito eseguo il polling dell'encoder con una frequenza di ~ 4 kHz. Se il polling è più lento, il microcontrollore salterà gli impulsi quando la manopola dell'encoder viene ruotata rapidamente. Se l'encoder viene utilizzato per impostare un valore variabile linearmente, ad esempio per impostare l'ora in ore, allora è conveniente utilizzare i numeri 255 e 1 come costanti LEFT_SPIN e RIGHT_SPIN, rispettivamente. Nel processore del segnale dell'encoder questi numeri vengono semplicemente aggiunti al valore impostato. Quando si aggiunge con 1, il valore aumenta di 1, quando si aggiunge con 255 diminuisce di 1. Naturalmente, questo è rilevante se questo valore è di un byte. Bene, in linea di principio, le costanti LEFT_SPIN e RIGHT_SPIN possono essere scelte arbitrariamente, l'importante è scrivere correttamente il gestore. È tutto.

Codice sorgente per lavorare con l'encoder.

Finalmente ho ottenuto questo meraviglioso spinner e ora voglio dirti come lavorarci. Il mio codificatore (EC12E24204A9) è qualcosa del genere:

L'encoder ha tre contatti: Comune, A e B. Il comune è solitamente sempre collegato a terra e gli altri due a qualsiasi pin del microcontrollore. I terminali A e B devono essere collegati al positivo dell'alimentazione tramite resistenze da circa 10 kOhm per evitare che falsi positivi possano causare interferenze. Non consiglierei di utilizzare un serraggio interno del microcontrollore. E' molto debole. Per dimostrare il lavoro, appenderemo altri 8 LED. (nota: se vengono utilizzati mega16, mega32 e versioni precedenti, jtag deve essere spento, altrimenti metà dei LED non si accenderanno)
Quindi abbiamo ottenuto il seguente diagramma:


Giriamo la manopola dell'encoder verso destra: la luce corre verso destra. Giriamo a sinistra: la luce corre a sinistra. Come funziona un codificatore? Lo scopriremo. Non c'è niente di complicato. Diamo un'occhiata ai grafici sottostanti.
Quando l'encoder viene ruotato in una direzione, il segnale appare così:

Ad un altro:

Sorge la domanda: come può il microcontrollore distinguere la direzione di rotazione dell'encoder?

Esistono due popolari algoritmi di polling dell'encoder:

  • Polling tramite interruzioni
  • Interrogazione con confronto tra lo stato precedente dell'encoder e quello attuale

Ciascuno di questi metodi di indagine presenta vantaggi e svantaggi. Li ho provati entrambi e ho optato per il secondo metodo. Il polling utilizzando gli interrupt è utile perché può fornire una risposta istantanea alla rotazione della manopola dell'encoder. Ma c'è anche un grave inconveniente. Come il rimbalzo dei contatti. Per sopprimerlo, ovviamente, puoi utilizzare vari software e hardware, ma non mi sono preoccupato. Diamo uno sguardo più da vicino al secondo algoritmo di polling. Durante il funzionamento, il microcontrollore legge continuamente i dati dai pin su cui è appeso l'encoder e confronta ciò che legge con il risultato della lettura precedente. A seconda del risultato del confronto degli stati, il programma trae conclusioni sulla direzione di rotazione. Il programma ha dei commenti, penso che saranno sufficienti per capire l'algoritmo. Se avete domande potete farle, come sempre, nei commenti.

In breve, gli encoder possono essere chiamati trasduttori di spostamento angolare. Servono a trasformare l'angolo di rotazione di un oggetto rotante, ad esempio l'albero di un meccanismo, in un segnale di corrente elettrica. In questo caso viene determinato non solo l'angolo di rotazione dell'albero, ma anche il suo senso di rotazione, nonché la velocità di rotazione e la posizione attuale rispetto alla posizione originale.

Gli encoder sono diventati più popolari se utilizzati nei sistemi di movimento di precisione, nelle fabbriche di macchine utensili, nei complessi di produzione che utilizzano la robotica, nei dispositivi di misurazione che richiedono la registrazione di misurazioni precise di inclinazioni, rotazioni, rotazioni e angoli.

Tipi e principio di funzionamento

Gli encoder sono sensori di rotazione. Il sensore più semplice ha una maniglia che può essere ruotata in senso orario o antiorario. A seconda dell'angolo di rotazione e della direzione viene emesso un segnale digitale che informa sulla posizione della maniglia o in quale direzione è stata girata.

Per un encoder di questo tipo, mostrato in figura, la maniglia può essere utilizzata anche come pulsante. Questa è una funzione ausiliaria di un tipo specifico di encoder.

In base al tipo di dati in uscita gli encoder si dividono in due grandi gruppi:
  1. Assoluto.
  2. Incrementale.
Encoder assoluti

Con un encoder assoluto, l'intero cerchio di rotazione è diviso in un certo numero di settori, molto spesso della stessa dimensione. Questi settori sono numerati. Durante il funzionamento, l'encoder visualizza il numero del settore in cui si trova attualmente. Ecco perché si chiama assoluto. Con questo tipo di encoder è sempre possibile determinare con quale angolo rispetto al settore zero viene ruotato l'encoder in un determinato momento, ovvero quando ruotato produce i valori dei numeri del settore, fino al valore massimo. Poi torna a zero.

Se l'albero dell'encoder viene ruotato nella direzione opposta, inizierà a produrre valori opposti. Nel nostro caso, utilizza cinque pin per emettere valori di rotazione.

Questo algoritmo ha i suoi svantaggi. La tabella 1 mostra l'ordine dei valori di uscita dell'n-esimo encoder. Vale la pena prestare attenzione alle ultime due righe, il passaggio da 127 a 128.

Tabella 1

Assolutamente tutte le cose cambiano qui. In un encoder ideale cambiano tutti contemporaneamente e non ci sono problemi. In quasi un codificatore reale, i bit cambiano rapidamente, ma non simultaneamente. E ad un certo punto l'uscita dell'encoder risulta essere un valore completamente arbitrario. Poiché tutti i bit cambiano, quindi, l'encoder avrà un valore arbitrario da zero a tutti uno.

Un esempio di tale interruttore è mostrato a destra. Cosa potrebbe significare? Diamo un'occhiata a un esempio. Il microcontrollore utilizza un motore per controllare l'albero e ruotarlo fino a un certo angolo. Ad un certo punto, quando si passa dalla cella 127 alla cella 128, riceve un certo valore casuale. Il controllore conclude che l'albero si trova in una posizione completamente diversa, a differenza della posizione effettiva, e inizia a ruotarlo in una direzione diversa, a una velocità diversa, ecc.

Dopo un certo tempo, il microcontrollore riceve il valore corretto e inizia a provare a fermare l'albero e a ruotarlo nella direzione corretta. Questo processo può richiedere molto tempo, a condizione che un errore di questo tipo si verifichi frequentemente. Tali errori sono irregolari e piuttosto difficili da calcolare.

Codice grigio

Il problema sopra descritto viene risolto introducendo un codice Gray. Una caratteristica del codice Gray è che quando l'encoder viene impostato su uno, anche il valore del codice Gray cambia di uno. Cambia solo un tipo. Ciò può essere visto nella Tabella 2 nel confronto tra codice binario e codice Gray.

Tavolo 2

Le prime due righe sono le stesse, ma già nella seconda riga la parte centrale è cambiata. Poi cambia anche qualcosa. Vale anche la pena notare che l'ultimo e il primo codice Gray differiscono di un bit, il che significa che il codice Gray potrebbe entrare in un ciclo.

Il vantaggio di questo codice è che l'errore discusso sopra non è possibile. Tra gli svantaggi si può notare che il microcontrollore ha bisogno di convertire il codice Gray in codice binario per capire in quale posizione si trova l'encoder assoluto.

Encoder incrementali

Il tipo successivo è l'encoder incrementale, che ha una struttura più semplice. Ma allo stesso tempo non mostra la posizione specifica della sua penna. Mostra solo il senso di rotazione e il numero di divisioni di rotazione deve essere contato dal microcontrollore.

Un encoder incrementale ha una serie di strisce che sono collegate a terra per impostazione predefinita e, quando ruotate, creano e interrompono le connessioni. Il risultato è il segnale mostrato in figura (simile ad un'onda quadra). L'encoder ha due di queste strisce circolari. Le strisce sono sfalsate di un quarto e anche i segnali sono sfalsati di un quarto. Questo è importante perché consente di determinare il senso di rotazione.

Il circuito di un encoder incrementale può essere rappresentato nella figura a destra. I pulsanti indicano i collegamenti periodici dell'encoder a terra. Poiché l'encoder non è collegato internamente a un'unità logica, è necessario collegare indipendentemente le unità logiche dall'esterno tramite resistori all'uscita dell'encoder. In questo caso, quando nessuno dei piedini dell'encoder è collegato a terra, ce ne sarà uno logico sui piedini.

Se l'encoder ha collegato una gamba a terra, questa gamba avrà uno zero logico. In uno stato silenzioso, l'uscita dell'encoder è logica. Quando inizi a ruotare l'encoder in qualsiasi direzione, prima un pin è collegato a terra, poi l'altro. Successivamente, questi pin vengono disconnessi a loro volta da terra e su di essi viene nuovamente formata un'unità logica.

Il senso di rotazione può essere determinato da quale dei terminali è stato collegato per primo a terra. Quando si contano i cicli completi, è possibile contare il numero di clic effettuati dall'encoder.

Infatti l’encoder ha quattro stati:
  1. Due unità.
  2. Zero e uno.
  3. Zero e zero.
  4. Uno e zero.

Tre stati che non sono uguali a uno sono instabili e il codificatore non può trovarsi in essi. Molti microcontrollori implementano la funzione di conteggio dei turni utilizzando timer dotati di ingressi specifici. Il timer conta a livello hardware quanti clic e in quale direzione è stato ruotato l'encoder e ne visualizza il valore. Cioè, il contatore incrementa un numero.

Modificando questo numero è possibile determinare di quanti clic è stato ruotato l'encoder. Dal numero di clic è possibile determinare l'angolo di rotazione. L'encoder presenta anche un rimbalzo dei contatti, che rende difficile l'analisi del segnale.

Encoder ottici

Tale convertitore è realizzato sotto forma di un disco fissato su un albero e realizzato in vetro. Il sensore di rotazione ottico differisce dagli altri tipi in quanto dispone di un gruppo ottico aggiuntivo che si muove quando l'albero viene ruotato. Allo stesso tempo converte la coppia in un flusso luminoso, che viene poi ricevuto da un fotosensore.

Il convertitore ottico ricorda gli angoli di rotazione. In questo caso ad ogni singola posizione corrisponde uno speciale codice digitale che, insieme al numero di giri, costituisce l'unità di misura del sensore. L'encoder si collega e funziona in modo simile a un encoder incrementale.

In base alla natura del loro funzionamento, sono suddivisi in fotovoltaico E magnetico . Il principio di funzionamento del magnetico si basa sull'uso del , scoperto per la prima volta nel 1879. In questo caso, la differenza di potenziale appare solo quando un filo di corrente continua viene inserito in un campo magnetico.

In termini di precisione e proprietà di risoluzione, il tipo di sensore magnetico è inferiore a quello fotoelettrico, tuttavia è più semplice nel design e meno impegnativo in termini di condizioni operative e spazio. Un encoder magnetico è un dispositivo che rileva il passaggio del polo magnetico di un magnete durante la rotazione, posto in prossimità dell'elemento sensibile. Le informazioni del trasmettitore sono espresse in codice digitale.

Encoder fotoelettrico è un sensore che funziona secondo il principio fotoelettrico. Questo effetto si osserva quando una sostanza è esposta alla luce. Questo principio fu scoperto nel 1887. Quando si utilizza un tale sensore, il raggio luminoso viene costantemente convertito in un segnale di corrente elettrica.

Gli analoghi del codificatore fotoelettrico sono optoelettronici, ottici e. Questi sensori sono più sensibili alle caratteristiche di produzione, al funzionamento e ad altri fattori rispetto ad altri modelli. Tuttavia, ciò è giustificato dalla loro maggiore precisione, a differenza dei loro concorrenti.

Sicuramente tutti si sono imbattuti in un codificatore nella vita di tutti i giorni. Ad esempio, nelle autoradio vengono utilizzati per controllare il volume. O nei mouse dei computer, una rotella di scorrimento.

Con il loro aiuto è molto comodo organizzare il menu. Conosco casi in cui, su un dispositivo molto serio e costoso, tutto il controllo è organizzato utilizzando un solo encoder. Allo stesso modo, nell’antichità, esisteva un modello di telefono in cui anche tutti i comandi erano organizzati con una sola rotella.

Innanzitutto esistono diversi tipi di encoder; quello trattato in questo articolo è incrementale meccanico. Pec12-4220f-s0024 è stato utilizzato come soggetto del test. Esternamente, sembra un resistore variabile, ma, a differenza di un resistore, non ha limitatori, ad es. può girare all'infinito in qualsiasi direzione.

Il risultato di un tale dispositivo è un codice Gray binario. Può essere ottenuto analizzando lo stato delle gambe a cui arrivano gli impulsi dell'encoder.

Ora diamo un'occhiata a tutto in modo più dettagliato. Elettricamente è composto da 2 pulsanti senza bloccaggio, quando iniziamo a girare funzionano a turno: il primo, poi il secondo. A seconda della direzione in cui ruotiamo, uno dei pulsanti si attiva prima o dopo. Per scoprire in quale stato si trovano questi pulsanti, i piedini della porta (a cui è collegato l'encoder) devono essere sollevati fino all'alimentatore “+”.

Su encoder smontato 1/3 dell'area appartiene al 1° contatto, 1/3 al 2° contatto, la zona piena è comune. Quando i contatti scorrevoli colpiscono le aree isolate (nere), si sente un clic. In questo momento, l'encoder è in uno stato stabile quando entrambi i pulsanti sono aperti. Ci saranno unità di registro sulle tratte portuali (stato 11).

Non appena iniziamo a ruotare in qualsiasi direzione, uno dei contatti si chiude a terra. Su questa tratta apparirà il registro 0, sulla seconda tratta apparirà ancora il registro 1 (stato 01). Se continuiamo a ruotare, log0 (stato 00) apparirà sulla seconda tappa. Successivamente, il contatto sulla prima gamba scompare (stato 10) e alla fine l'encoder ritorna ad uno stato stabile (11). Quelli. Ci sono 4 cambiamenti di stato per clic. Il diagramma temporale è simile al seguente:

Quando si ruota nella direzione opposta, l'idea rimane la stessa, solo la seconda gamba si chiuderà per prima.

Se scriviamo questi stati nel sistema binario e li convertiamo in decimale, otteniamo il seguente ordine (per la rotazione in una direzione):
11=3
01=1
00=0
10=2

Quando si ruota nella direzione opposta:
11=3
10=2
00=0
01=1

Ora resta da capire come elaborare questi valori. Diciamo che l'encoder è collegato ai pin della porta B0 e B1. Dobbiamo leggere queste gambe. Esiste un modo piuttosto intelligente, ma prima dobbiamo comprendere l'operazione logica e (&).

Il risultato sarà uguale a uno solo se entrambi i numeri sono uguali a 1, cioè il risultato dell'operazione 1&1 sarà uguale a 1. Pertanto 1&0=0, 0&0=0, 0&1=0.

Logico e ci aiuterà a isolare dall'intero porto solo le gambe che ci interessano. Quelli. operazione x=0b00000011 & PINB; ci permetterà di leggere nella variabile “x” lo stato delle prime due gambe, indipendentemente da cosa si trova sulle restanti gambe. Il numero 0b00000011 può essere convertito in esadecimale 0x3.

Ora abbiamo tutte le conoscenze necessarie per scrivere il firmware. Compito: aumentare/diminuire la variabile Vol utilizzando un encoder, visualizzare il risultato sul display LCD.

#includere int NewState, OldState, Vol, upState, downState; #asm.equ __lcd_port= 0x12 ; PORTD #endasm #include #includere interrupt [ TIM1_COMPA] void timer1_compa_isr(void ) ( NewState= PINB & 0b00000011 ; if (NewState!= OldState) ( switch (OldState) ( case 2 : ( if (NewState == 3 ) upState++; if (NewState == 0 ) downState++ ; break ; ) case 0 : ( if (NewState == 2 ) upState++; if (NewState == 1 ) downState++; break ; ) case 1 : ( if (NewState == 0 ) upState++; if (NewState == 3 ) downState++ ; break ; ) caso 3: ( if (NewState == 1 ) upState++; if (NewState == 2 ) downState++; break ; ) ) OldState= NewState; ) TCNT1H= 0x00 ; TCNT1L= 0x00 ; ) void main(void ) ( char lcd_buff[17]; // Inizializzazione delle porte di ingresso/uscita// Inizializzazione della porta B // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // Stato7=T Stato6=T Stato5=T Stato4=T Stato3=T Stato2=T Stato1=P Stato0=P PORTAB= 0x03 ; DDRB=0x00; // Inizializzazione del timer/contatore 1// Sorgente orologio: orologio di sistema // Valore orologio: 1000.000 kHz // Modalità: CTC top=OCR1A // Uscita OC1A: disconnesso. // Uscita OC1B: disconnesso. // Cancellazione del rumore: disattivata // Acquisizione dell'input sul fronte di discesa // Interruzione di overflow del timer 1: disattivata // Interruzione acquisizione input: disattivata // Confronta un'interruzione della partita: attiva // Confronta l'interruzione della partita B: disattivata TCCR1A= 0x00 ; TCCR1B=0x0A ; TCNT1H= 0x00 ; TCNT1L= 0x00 ; ICR1H=0x00; ICR1L=0x00 ; OCR1AH=0x03; OCR1AL= 0xE8 ; OCR1BH=0x00; OCR1BL=0x00; // Inizializzazione degli interrupt di timer/contatori/contatori TIMSK= 0x10 ; // Abilitazione globale degli interrupt #asm("sei") lcd_init(8 ); while (1 ) ( if (upState >= 4 ) ( Vol++; upState = 0 ; ) if (downState >= 4 ) ( Vol--; downState = 0 ; ) sprintf (lcd_buf, "vol=%d" , Vol) ; lcd_gotoxy(0, 0) ; lcd_clear() ; lcd_puts(lcd_buf) ; ) ; )

#includere int NuovoStato,OldStato,Vol,upState,downState; #asm .equ __lcd_port=0x12 ;PORTD #endasm #include #includere interrupt void timer1_compa_isr(void) ( NewState=PINB & 0b00000011; if(NewState!=OldState) ( switch(OldState) ( case 2: ( if(NewState == 3) upState++; if(NewState == 0) downState++; break; ) caso 0: ( if(NewState == 2) upState++; if(NewState == 1) downState++; break; ) caso 1: ( if(NewState == 0) upState++; if(NewState == 3) downState++; break; ) caso 3: ( if(NewState == 1) upState++; if(NewState == 2) downState++; break; ) ) OldState=NewState; ) TCNT1H=0x00; TCNT1L=0x00; ) void main(void) ( char lcd_buf; // Inizializzazione delle porte di ingresso/uscita // Inizializzazione della porta B // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4 =T State3=T State2=T State1=P State0=P PORTB=0x03; DDRB=0x00; // Inizializzazione timer/contatore 1 // Sorgente orologio: orologio di sistema // Valore orologio: 1000.000 kHz // Modalità: CTC top=OCR1A // Uscita OC1A: disconnesso. // Uscita OC1B: disconnesso. // Eliminazione del rumore: spento // Cattura ingresso su fronte di discesa // Interruzione overflow timer 1: spento // Interruzione acquisizione ingresso: spento // Confronta una corrispondenza Interrupt: On // Interruzione confronto corrispondenza B: Off TCCR1A=0x00; TCCR1B=0x0A; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x03; OCR1AL=0xE8; OCR1BH=0x00; OCR1BL=0x00; // Inizializzazione degli interrupt di timer/contatori TIMSK=0x10; // Abilitazione globale degli interrupt #asm("sei") lcd_init(8); while (1) ( if (upState >= 4) ( Vol++; upState = 0; ) if (downState >= 4) ( Vol--; downState = 0; ) sprintf(lcd_buf,"vol=%d",Vol) ; lcd_gotoxy(0,0); lcd_clear(); lcd_puts(lcd_buf); ); )

A titolo di chiarezza: il timer 1 è configurato per attivarsi 1000 volte al secondo, con la riga NewState=PINB & 0b00000011; Leggiamo lo stato dei pin 0 e 1 della porta B. if(NewState!=OldState) se lo stato non è cambiato, non c'è rotazione.
Se lo stato è cambiato, il costrutto switch determina in quale direzione è stata eseguita la rotazione, a seconda di ciò, aumenta il valore della variabile downState (sinistra) o upState (destra).

Da un clic al clic successivo si verificano 4 cambiamenti di stato, quindi cambiamo la variabile Vol una volta ogni 4 impulsi. Lo visualizziamo anche sul display. Firmware disponibile