terça-feira, julho 21, 2020

Usando um Rotary Encoder

Este é mais um daqueles posts sobre algo que eu pensei ser simples, mas deu bastante trabalho na hora de colocar para funcionar.

Minha primeira ideia de interface para o "ATmega Detonator" era bem minimalística: vários LEDs e um botão para ir selecionando sequencialmente as opções. Mais adiante resolvi usar um display I2C e apresentar menus nele. Para selecionar as opções vou um "rotary encoder", inspirado por um vídeo onde ele é usado junto com um display do mesmo modelo que vou usar.

Existe muita informação na internet sobre os "rotary encoders" (listo no final as que usei), portanto vou tentar ser sucinto.



A aparência externa de um "rotary encoder" é parecida com um potenciômetro, mas internamente são totalmente diferentes. O potenciômetro é um resistor cuja resistência varia de 0 a um máximo com o ângulo; normalmente o ângulo é limitado a algo como 270 graus. Ele é apropriado para determinar a posição do eixo.

O "rotary encoder" tem por objetivo indicar a velocidade e a direção da movimentação do eixo, sem se preocupar com a posição. A forma como ele faz isso é bem engenhosa. Mecanicamente temos dois contatos (A e B) que, com o movimento, serão ligados ou desligados a um terminal comum (normalmente ligado a terra):

Fonte: Wikipedia (criado por Matt Hercules)

A ordem com que os contatos são ligados indica a direção do movimento, a velocidade da mudança de cada sinal indica a velocidade da rotação.

Sinais reais. Esquerda rodando no sentido horário e direita rodando no anti-horário
Podemos ter oscilações no momento em que o contato for feito ou desfeito ("bounce"). O modelo que estou usando tem uma chave que é acionada quando o eixo é apertado para baixo e um "clique" a cada par de conexão/desconexão do contato (são 20 cliques por volta). O módulo possui os resistores de pull-up para os três sinais.

As estratégias usuais para ler o "rotary encoder" são:
  • Monitoração contínua: ficar olhando o tempo todo os sinais (via digitalRead) e detectar as transições. É preciso implementar um "debounce" para ignorar as oscilações. O problema desta opção é que dificulta fazer outras coisas ao mesmo tempo.
  • Interrupção:usar o recurso de interrupção para detectar as mudanças em um ou ambos sinais. Isto simplifica fazer outras coisas ao mesmo tempo, mas no Arduino Uno temos somente dois pinos com interrupção e o "debounce" pode ser um pouco mais complicado.
  • Monitorar periodicamente: usar a interrupção de tempo para amostrar os sinais. O próprio tempo entre amostragens pode funcionar como debounce. O problema aqui é que um tempo grande entre amostragens pode resultar na perda de mudanças quando o eixo é girado rapidamente.
Montagem para teste
O programa de teste usa o "rotary encoder" junto com o display para seleção de menus e seleção de um valor numérico (algo que não é necessário no Detonator), usando a amostragem periódica. O debounce consiste em ler o mesmo valor em duas interrupções consecutivas. Foi um pouco crítico determinar o tempo entre as interrupções. Além do problema de conseguir pegar todas as transições quando o eixo é girado rapidamente, as rotinas de I2C (usadas na comunicação com o display) também usam interrupção.

Como o programa ficou longo não vou listar ele aqui mas ele pode ser visto no github.

Para usar no ATmega Detonator vou dar mais uma "polida" nestas rotinas, o objetivo aqui foi só confirmar que funcionava como precisava. Outra mudança, que veremos no próximo post, é usar um tamanho de letra maior para ficar mais fácil de ler.

Links:
https://rudysarduinoprojects.wordpress.com/2019/04/05/fun-with-arduino-25-rotary-encoder-with-switch/
https://lastminuteengineers.com/rotary-encoder-arduino-tutorial/
http://practicalusage.com/arduino-using-a-rotary-encoder/

Nenhum comentário: