04 agosto 2015

Como utilizar um encoder rotativo com Arduino

Conhece o encoder rotativo ? Por fora, ele é um componente muito parecido com um potenciômetro, mas internamente funciona de uma forma bem diferente, sendo um componente interessante para você utilizar com seus projetos para Arduino. Eu utilizei um módulo encoder KY-040 para criar um pequeno sistema de seleção com display LCD 20x4.

como utilizar um encoder rotatico com Arduino

encoder é um componente utilizado para conversão de movimentos rotativos (ou lineares) em impulsos elétricos de onda quadrada. Esse impulsos podem ser lidos por um microcontrolador (no nosso caso, vamos utilizar o Arduino), e geram uma quantidade exata de impulsos por volta.

O encoder que utilizamos tem rotação contínua, e também um botão (basta empurrar o eixo) que vamos usar para selecionar uma das opções do "menu" no display. 

Módulo Encoder KY-040

Ligando o encoder no Arduino

O primeiro circuito de testes utiliza somente o encoder. Vamos utilizar 3 pinos do Arduino para ligar o componente, sendo que os pinos analógicos A2 e A3 serão ligados nos pinos de medição, e o pino digital 7 no pino do botão, junto com um resistor pull-up.

Circuito básico módulo encoder



Caso você esteja utilizando somente o encoder (sem o módulo, siga o esquema ligação abaixo:

Circuito básico encoder rotativo

Teste esse circuito carregando o programa abaixo, que utiliza a biblioteca RotaryEncoder (download). Baixe a biblioteca e coloque-a na pasta LIBRARIES da IDE do Arduino.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//Programa : Teste basico encoder Arduino
//Autor : Arduino e Cia

//Carrega a biblioteca do encoder
#include <RotaryEncoder.h>

//Pinos de ligacao do encoder
RotaryEncoder encoder(A2, A3);

//Variavel para o botao do encoder
int valor = 0;
int newPos = 0;

void setup()
{
  pinMode(7, INPUT);
  Serial.begin(9600);
  Serial.println("Gire o encoder....");
}

void loop()
{
  //Verifica se o botao do encoder foi pressionado
  valor = digitalRead(7);
  if (valor != 1)
  {
    Serial.println("Botao pressionado");
    while (digitalRead(7) == 0)
      delay(10);
  }

  //Le as informacoes do encoder
  static int pos = 0;
  encoder.tick();
  int newPos = encoder.getPosition();
  //Se a posicao foi alterada, mostra o valor
  //no Serial Monitor
  if (pos != newPos) {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;
  }
}

O programa aguarda que o usuário gire o encoder para a direita ou para a esquerda, atualizando o valor de um contador. Girando para a direita, o contador aumenta, e para a esqueda, o contador diminui. Caso o botão seja pressionado, uma mensagem também aparece no serial monitor:

Teste encoder Arduino

Esse é um circuito bem simples que você pode usar para testar se o seu encoder está funcionando corretamente.

Sistema de menu com display LCD 20x4 e encoder

Neste segundo circuito, vamos manter as ligações do encoder que utilizamos anteriormente, e adicionar um display LCD 20x4 ao circuito. O potenciômetro é de 10K e serve para ajustar o contraste do display. O resistor utilizado como pull-up do botão do encoder é de 330 ohms.

Circuito Arduino Encoder Arduino LCD 20x4


No programa deste circuito, vamos primeiramente criar caracteres customizados para os números de 1 a 6 que forem selecionados (são os números "invertidos"). Conforme giramos o encoder, os números no display vão sendo substituídos por esses número invertidos.

No loop, testamos se o botão foi pressionado, e também limitamos as opções de seleção entre 1 e 6, através do comando encoder.setPosition(). O programa checa se o valor do encoder foi alterado e, em caso positivo, chama a rotina  destaque_selecionado(), que atualiza os dados da tela.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//Programa : Menu com encoder e LCD 20x4
//Autor : Arduino e Cia

//Carrega biblioteca LCD e encoder
#include <LiquidCrystal.h>
#include <RotaryEncoder.h>

//Inicializa o LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//Pinos de ligacao do encoder
RotaryEncoder encoder(A2, A3);

int contador = 1;
int contador_anterior = 1;
int valor = 0;


byte Bloco_Cheio[8]  = {0b11111, 0b11111, 0b11111, 0b11111,
                        0b11111, 0b11111, 0b11111, 0b11111
                       };
byte Um_invertido[8] = {0b11011, 0b10011, 0b11011, 0b11011,
                        0b11011, 0b11011, 0b10001, 0b11111
                       };
byte Dois_invertido[8] = {0b10001, 0b01110, 0b11110, 0b11101,
                          0b11011, 0b10111, 0b00000, 0b11111
                         };
byte Tres_invertido[8] =  {0b00000, 0b11101, 0b11011, 0b11101,
                           0b11110, 0b01110, 0b10001, 0b11111
                          };
byte Quatro_invertido[8] = {0b11101, 0b11001, 0b10101, 0b01101,
                            0b00000, 0b11101, 0b11101, 0b11111
                           };
byte Cinco_invertido[8] = {0b00000, 0b01111, 0b00001, 0b11110,
                           0b11110, 0b01110, 0b10001, 0b11111
                          };
byte Seis_invertido[8] = {0b11001, 0b10111, 0b01111, 0b00001,
                          0b01110, 0b01110, 0b10001, 0b11111
                         };

static int pos = 1;
int newPos = 0;
int selecionado = 0;

void setup()
{
  Serial.begin(9600);
  //Inicializa o botao do encoder no pino 7
  pinMode(7, INPUT);
  //Define o LCD com 20 colunas e 4 linhas
  lcd.begin(20, 4);
  //Cria os caracteres customizados
  lcd.createChar(0, Bloco_Cheio);
  lcd.createChar(1, Um_invertido);
  lcd.createChar(2, Dois_invertido);
  lcd.createChar(3, Tres_invertido);
  lcd.createChar(4, Quatro_invertido);
  lcd.createChar(5, Cinco_invertido);
  lcd.createChar(6, Seis_invertido);

  //Informacoes iniciais
  lcd.setCursor(0, 0);
  lcd.print("  1  2  3  4  5  6");
  lcd.setCursor(1, 2);
  lcd.print("Valor atual: 0");
  lcd.setCursor(1, 3);
  lcd.print("Selecionado: -");
}

void loop()
{
  //Verifica se o botao do encoder foi pressionado
  valor = digitalRead(7);
  Serial.println(valor);
  if (valor != 1)
  {
    Serial.println("Botao pressionado");
    lcd.setCursor(14, 3);
    selecionado = newPos;
    lcd.print(selecionado);
    //while (digitalRead(7) == 1)
    //  delay(10);
  }

  //Le as informacoes do encoder
  encoder.tick();
  newPos = encoder.getPosition();
  if (pos != newPos)
  {
    //Limite maximo menu
    if (newPos > 6)
    {
      encoder.setPosition(6);
      newPos = 6;
    }
    //Limite minimo menu
    if (newPos < 1)
    {
      encoder.setPosition(1);
      newPos = 1;
    }
    Serial.print("Posicao: ");
    Serial.println(newPos);
    //Atualiza o menu no display
    destaque_selecionado(newPos);
    pos = newPos;
  }
}

void destaque_selecionado(int conta)
{
  //Define posicao inicial
  int posicao = (conta * 3) - 1;
  //Apaga selecao anterior
  if (conta > pos)
  {
    lcd.setCursor(posicao - 4, 0);
    lcd.print(" ");
    lcd.print(conta - 1);
    lcd.print(" ");
  }
  //Apaga selecao posterior
  if (conta < pos)
  {
    lcd.setCursor(posicao + 2, 0);
    lcd.print(" ");
    lcd.print(conta + 1);
    lcd.print(" ");
  }

  //Imprime blocos cheios
  lcd.setCursor(posicao - 1, 0);
  lcd.write((uint8_t)0);
  lcd.write((uint8_t)0);
  lcd.write((uint8_t)0);

  //imprime valor
  lcd.setCursor(posicao, 0);
  lcd.write((uint8_t)(conta));

  //Imprime Opcao atual
  lcd.setCursor(14, 2);
  lcd.print(conta);
}

Achou a explicação muito complicada ? Dê uma olhada no vídeo abaixo, que mostra esse circuito em funcionamento:


O programa atualiza os valores somente na tela, mas você pode modificar facilmente este programa para que ele acione portas do Arduino ou envie e receba dados de algum sensor.

10 comentários:

  1. I just couldnt leave your website before letting you know that I really enjoyed the useful information you offer to your visitors... Will be back often to check up on new posts.

    electronic display boards india

    ResponderExcluir
    Respostas
    1. Hi !

      I really appreciate your comments. You are always welcome. :)

      Best regards !

      Adilson

      Excluir
  2. gostaria de adquirir alguns contadores de passagem para instalar em minhas lojas aqui em sp, como faço? obrigado

    ResponderExcluir
    Respostas
    1. Boa noite,

      Ok, por favor entre em contato utilizando o formulário de contato no lado direito da página. Conversamos por email.

      Abraço!

      Excluir
  3. Pensei que os encoders eram para controlar o giro de motores?

    ResponderExcluir
    Respostas
    1. Bom dia Eduardo,

      O encoder pode ter várias aplicações, inclusive controlar o giro de motores, o menu que eu criei é só um exemplo. :)

      Abraço!

      Excluir
  4. Qual o raio de rotação do encoder? Tipo, uma rotação (20 pulsos) equivale a quantos mm em linha reta?

    ResponderExcluir
  5. e possível saber posições com o encoder, tipo um leve giro de 10 graus e fazer a leitura, ou só funciona com voltas completas ? se sim, à algum material para ajudar ?

    ResponderExcluir
    Respostas
    1. Bom dia,

      Esse encoder que eu uso no post tem um número fixo de pontos, à medida que vc gira o eixo. Você pode dividir 360 pelo número de pontos (não sei exatamente quantos são), para descobrir quantos graus por ponto ele se desloca.

      Abraço!

      Excluir