Codificador Rotativo KY-040 – ESP32
O Codificador Rotativo KY-040 em inglês conhecido como “Rotary Encoder”, é um ótimo dispositivo para uso de navegação em display. Normalmente ele é montado em um módulo já com alguns resistores de pull-up para auxiliar na geração dos pulsos de codificação, como esse modulo a seguir:
O KY-040 transforma o movimento em pulsos digitais, por isso o nome de codificador, o sinal digital gerado pelo KY-040 precisa ser decodificado por um microcontrolador, neste artigo iremos usa um ESP32 porem pode ser usado um Arduino também.
Pinagem
O modulo possui 5 pinos, onde o pino CLK sempre irá gerar um conjunto de pulsos fixos, o DT gerar uma serie de pulsos conforme o sentido de giro, o SW é ligado ao botão do eixo se você pressionar o eixo irá acionar o SW para o GND, o pino de + é a alimentação positiva que pode ser de 3,3V ou 5V.
Pino | Descrição |
CLK (A) | Gera um sinal de clock ao girar |
DT (B) | Gera um sinal diferente para a direção girada |
SW | Caso o eixo for pressionado, é fechado ao GND |
+ | Alimentação 3,3V ou 5V dos Resistores de Pull-up para os pulsos |
GND | Alimentação do Comum do circuito |
Abaixo segue as características do Modulo:
Modelo | KY-040 |
Tensão máxima | 5V |
Corrente aproximada | 10mA |
Pulsos por revolução | 20 pulsos |
Diâmetro do eixo | 5mm |
Comprimento do eixo | 10mm |
Dimensões Gerais | 32 x 19 x 30mm |
Geração dos Pulsos
O pino CLK gera um conjunto de pulsos que podem variar a largura e frequência conforme a velocidade de giro do eixo, o DT gerar uma serie de pulsos conforme o sentido de giro, casso giro seja no sentido horário o Sinal DT irá disparar um pouco de tempo depois do CLK cerca de 50% do ciclo positivo do primeiro pulso, se for girado no sentido anti-rorário, irá ser disparado antes do CLK na mesma proporção 50% do tempo do primeiro pulso, conforme a ilustração abaixo:
Se você observar há um Horário escrito em roxo, esta parte é onde o software da programação (Biblioteca) se não for bem escrito pode se confundir, onde é necessário descartar ou então tratar os pulsos recebidos com um tempo de espera (debounce).
Sobre o como ele gera os pulsos, há duas maneiras que pesquisei, uma é através de fotodiodos que recebem pulsos luminosos através de um disco com orifícios do mesmo padrão (disco de encoder), onde ao girar irá gerar uma série de pulsos conforme os furos dos discos passam pelo fotodiodo, acredito que esta maneira é muito utilizada em Encoder Rotários mais caros que tenham uma precisão absoluta, veja mais conforme a ilustração abaixo:
Outra maneira e a que eu creio que é o que realmente usam é por contato elétrico pois é muito mais barato fabrica-lo deste jeito pois evita o uso de diodos, não cheguei a abrir um pessoalmente porem a ideia funciona da mesma maneira que o modo óptico:
O contato C do eixo é alimentado com o sinal GND, e os contatos A e B ficam responsáveis por gerar a ordem do pulso, ele se movem sobre um disco Fixo (figura 2) onde conforme o sentido que o disco girar é ordem de qual pulso será gerado primeiro o CLK ou o DT.
Exemplo de Aplicação
Desenvolvi um pequeno exemplo utilizando um display gráfico que é o ST7920 que fizemos um artigo explicando ele, eu utilizei a placa de nosso Hardware XPboard, mas também fiz uma pequena montagem no Fritzing para que você também possa efetuar a montagem pessoal mesmo sem a placa do XPboard:
Subi a programação no XPboard e funcionou normalmente:
Caso você girar o encoder ou pressionar o eixo ele irá exibir no display as informações conforme a seguir:
Basta montar o LCD ST7920 conforme o circuito do XPboard, conforme a tabela aseguir:
Pino ST7920 | Descrição | Pino ESP32 |
1. VSS / GND | Comum | GND |
2. VDD / 5V | Alimentação | Vin / 5V |
3. Vo | Ref. Contraste | Potenciômetro |
4. RS | Selec. Registrador | GPIO35 |
5. RW | Escrita Registrador | GPIO32 |
6. ENABLE | Habilitar I/O | GPIO33 |
15. PSB | Comun. Serial / Paralela | GND |
17. RESET | Reiniciar LCD | GPIO27 |
19. BLA | Anodo LED | 5V |
20. BLK | Catodo LED | GND |
E o Codificador deve estar ligado na seguinte ordem:
Pino KY-040 | Pino ESP32 |
CLK | GPIO15 |
DT | GPIO14 |
SW | GPIO12 |
+ | +3,3V |
GND | GND |
A biblioteca está disponível dentro do PlatformIO com o seguinte título “RotaryEncoder by Matthias Hertel” mas caso você queira baixar diretamente do Repositório GitHub do desenvolvedor:
Ou Então baixe diretamente do XProjetos:
RotaryEncoder – KY-040 12KB 141 downloads
Biblioteca RotaryEncoder desenvolvida por Matthias Hertel que pode ser utilizada…Também você pode baixar a biblioteca do U8G2:
u8g2 – Biblioteca para Displays Gráficos 49,1MB 467 downloads
Esta é uma biblioteca desenvolvida pelo olikraus U8g2: Biblioteca para displays…Você também pode conferir os valores do Codificador pelo Monitor Serial, alem do display.
Comentei cada linha da programação, caso encontre alguma dificuldade deixe seu comentário, se gostou também deixe um comentário seu Feedback me deixa muito motivado para criar mais conteúdos aqui no XProjetos.
Abaixo segue a programação feita no Visual Studio Code:
/*============================================================================ Programa de teste para o Codificador KY-040 para ESP32, desenvolvido por JailsonBR utilizando a biblioteca u8g2 do olikraus. Código adaptado por JailsonBR do site XProjetos.net em 19-01-2020, o uso deste código é livre porem deve respeitar e mante o nome do criador e tambêm de quem modificou. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) Copyright(c) sobre o XPsys 2020, XProjetos.net ------------------------------------------------------------------------------ Program test for the KY-040 Encoder for ESP32, developed by JailsonBR using the olikraus u8g2 library. Code adapted by JailsonBR from the site XProjetos.net on 01-19-2020, the use of this code is free but must respect and keep the name of the creator and also those who modified it. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) Copyright (c) about XPsys 2020, XProjetos.net ==============================================================================*/ #include <Arduino.h> #include <RotaryEncoder.h> #include <U8g2lib.h> #include <SPI.h> #define FontePadrao u8g2_font_5x8_tf //Seleciona a fonte padrão U8G2_ST7920_128X64_1_SW_SPI u8g2(U8G2_R0, 33, 32, 35, 27); //Enable, RW, RS, RESET RotaryEncoder KY_040(14, 15); //Configura os pinos CLK e DT do Codificador KY-040 //Variáveis Globais para a programação bool BotaoSW = 1; int NovaPosicao = 0; bool Inicio = 1; void setup() { u8g2.begin(); //Inicia a Biblioteca do Display u8g2.setFont(FontePadrao); //Configura o tipo de Fonte u8g2_font_5x8_tf pinMode(12, INPUT_PULLUP); //Habilita o GPIO12 como entrada com Pull-up para o SW pinMode(1, OUTPUT); //Configura o pino do LED de luz de fundo do LCD (opcional) digitalWrite(1, HIGH); //Liga o pino do LED de luz de fundo do LCD (opcional) Serial.begin(9600); //Inicia a Transmissão Serial Serial.println("Pronto para Transmitir - XProjetos.net:"); Serial.println("Gire o Codificador"); } //XProjetos.net void loop() { int PosicaoAtual = 0; //Variável Local de Posição do Codificador BotaoSW = digitalRead(12); //Lê o estado do Pino SW (Eixo do Codificador) KY_040.tick(); // Verificar o estado do Codificador int NovaPosicao = KY_040.getPosition(); if (PosicaoAtual != NovaPosicao || BotaoSW == 0 || Inicio == 1) { Serial.print(NovaPosicao); Serial.println(); Inicio = 0; u8g2.firstPage(); //Este comando é parte do loop (imagem) que renderiza o conteúdo da exibição. (Obrigatório) do { //Tudo o que estiver dentro do "do {}" será exibido na tela. u8g2.drawRFrame(0,0,127,10,2); //Desenha um retangulo em volta do titulo u8g2.drawStr(15,8,"Teste Encoder KY-040"); //Escreve o titulo o topo da página (semelhante ao print porem não aceita UTF-8) u8g2.drawStr(15,18,"Posi\xe7\xe3o:"); //Escreve o titulo o topo da página (semelhante ao print porem não aceita UTF-8) u8g2.drawRFrame(13,22,64,16,2); //Desenha um retangulo em volta do titulo u8g2.drawRFrame(80,16,42,42,4); //Desenha um retangulo em volta do icone u8g2.setCursor(2, 46); //Configura a posição do proximo item a ser escrito na tela u8g2.print("Bot\xe3o Eixo:"); //Escreve na tela baseado na posição informada anteriormente.. u8g2.setCursor(65, 46); //Configura a posição do proximo item a ser escrito na tela u8g2.print(BotaoSW); //Escreve na tela a variavel temporaria do botão do Eixo (SW). if(BotaoSW == 0) { //Caso o Eixo do Codificador seja pressionado u8g2.setCursor(2, 56); //Configura a posição do proximo item a ser escrito na tela u8g2.print("Eixo Press."); Serial.println("Botao Pressionado"); u8g2.setFont(u8g2_font_open_iconic_all_4x_t); //Configura a fonte para uma fonte diferente do padrão u8g2.drawGlyph(84, 55, 0x004f); //Exibe o Desenho de uma Flecha para Baixo u8g2.setFont(FontePadrao); //Retorna para a fonte padrão do projeto } if(NovaPosicao > PosicaoAtual){ //Caso o Eixo do Codificador for girado sentido horário u8g2.setFont(u8g2_font_open_iconic_all_4x_t); //Configura a fonte para uma fonte diferente do padrão u8g2.drawGlyph(84, 55, 0x0042); //Exibe o Desenho de uma Flecha girando para a Direita u8g2.setFont(FontePadrao); //Retorna para a fonte padrão do projeto } if(NovaPosicao < PosicaoAtual){ //Caso o Eixo do Codificador for girado sentido anti-horário u8g2.setFont(u8g2_font_open_iconic_all_4x_t); //Configura a fonte para uma fonte diferente do padrão u8g2.drawGlyph(84, 55, 0x0043); //Exibe o Desenho de uma Flecha girando para a Esquerda u8g2.setFont(FontePadrao); //Retorna para a fonte padrão do projeto } u8g2.setCursor(15, 35); //Configura a posição do proximo item a ser escrito na tela u8g2.setFont(u8g2_font_unifont_t_latin); //Configura a fonte para uma fonte diferente do padrão u8g2.print(NovaPosicao); //Escreve na tela a posição armazenada do Encoder. u8g2.setFont(FontePadrao); //Retorna para a fonte padrão do projeto } while ( u8g2.nextPage() ); //Este comando é parte do loop (imagem) que renderiza o conteúdo da exibição. (Obrigatório) PosicaoAtual = NovaPosicao; //Armazena a Posição Atual na Nova posição } }
- Fontes:
- https://www.arduinoecia.com.br/como-usar-encoder-rotativo-ky-040-arduino/
- https://www.filipeflop.com/produto/encoder-decoder-ky-040-rotacional/
- https://blogmasterwalkershop.com.br/arduino/como-usar-com-arduino-modulo-encoder-rotativo-ky-040/
- https://github.com/mathertel/RotaryEncoder
- https://docs.baslerweb.com/live_docu/RT5/en/documents/TriggerSystem/ShaftEncoder.html
- http://www.creative-science.org.uk/rotary_encoders.html
- http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/