Codificador Rotativo KY-040 – ESP32

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:

Modulo Ky-040 Rotary Encoder

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.

Representação do KY-040
PinoDescrição
CLK (A)Gera um sinal de clock ao girar
DT (B)Gera um sinal diferente para a direção girada
SWCaso o eixo for pressionado, é fechado ao GND
+Alimentação 3,3V ou 5V dos Resistores de Pull-up para os pulsos
GNDAlimentação do Comum do circuito

Abaixo segue as características do Modulo:

ModeloKY-040
Tensão máxima5V
Corrente aproximada10mA
Pulsos por revolução20 pulsos
Diâmetro do eixo5mm
Comprimento do eixo10mm
Dimensões Gerais32 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:

Modo Fotoelétrico do Encoder. Fonte: http://domoticx.com/

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:

Montagem em Protoboard do Circuito

Subi a programação no XPboard e funcionou normalmente:

Montagem Físicar

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 ST7920DescriçãoPino ESP32
1. VSS / GNDComumGND
2. VDD / 5VAlimentaçãoVin / 5V
3. VoRef. ContrastePotenciômetro
4. RSSelec. RegistradorGPIO35
5. RWEscrita Registrador GPIO32
6. ENABLEHabilitar I/O GPIO33
15. PSBComun. Serial / ParalelaGND
17. RESETReiniciar LCDGPIO27
19. BLAAnodo LED5V
20. BLKCatodo LEDGND

E o Codificador deve estar ligado na seguinte ordem:

Pino KY-040Pino ESP32
CLKGPIO15
DTGPIO14
SWGPIO12
++3,3V
GNDGND

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:

RotaryEncoder

GitHub

Acesse o Reposítorio do Desenvolvedor mathertel no site do GitHub clicando do botão abaixo:

Ou Então baixe diretamente do XProjetos:

ícone

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:

ícone

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
  }
}
Licença CC 4.0

Creative Commons

O trabalho “Codificador Rotativo KY-040 – ESP32” de JailsonBR está licenciado com uma Licença Creative Commons Atribuição 4.0 Internacional.

Jailson Oliveira

Sou Engenheiro Eletricista com Enfase em Eletrônica e Técnico em Eletrônica, gosto de estar praticando montagens de circuitos e também programar sistemas embarcados. Acredito que compartilhar informações gratuita gera mais informações novas por parte de outras pessoas.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *