Arduino Nano - Encoder Rotativo

Este tutorial ensina você a usar o encoder rotativo com o Arduino Nano. Veja o que vamos abordar:

Hardware Necessário

1×Official Arduino Nano
1×Alternatively, DIYables Nano V3.0 Development Board
1×Cabo USB A para Mini-B
1×Encoder Rotativo
1×Fios Jumper
1×(Recomendado) Placa de Expansão com Bornes de Parafuso para Arduino Nano
1×(Recomendado) Placa de Expansão Breakout para Arduino Nano
1×(Recomendado) Divisor de Alimentação para Arduino Nano

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Divulgação: Alguns dos links desta seção são links de afiliado da Amazon. Podemos receber uma comissão pelas compras feitas por meio desses links, sem custo adicional para você. Agradecemos o seu apoio.

Sobre o Encoder Rotativo

Um botão giratório chamado encoder rotativo pode transformar giros em um sinal. Ele mostra quanto algo girou e em que posição está. Existem dois tipos principais:

  • Encoder incremental: Usa sinais rápidos para ver quanto algo se moveu.
  • Encoder absoluto: Esse tipo fornece um código único para cada posição, o que ajuda a descobrir exatamente onde algo está, mesmo se a energia acabar.

Este guia é todo sobre o encoder incremental.

Pinagem do Módulo Encoder Rotativo

rotary encoder pinout

Um módulo encoder rotativo tem 4 pinos:

  • Pino CLK (Saída A): é o pulso principal que nos diz quanta rotação ocorreu. Sempre que você gira o botão em um clique (detent) em qualquer direção, o pino CLK emite um sinal que completa um ciclo inteiro (LOW → HIGH → LOW).
  • Pino DT (Saída B): age como o pino CLK, mas emite um sinal que fica atrasado em relação ao sinal CLK em 90 graus. Ele nos ajuda a descobrir a direção da rotação (sentido horário ou anti-horário).
  • Pino SW: é a saída do botão de pressão dentro do encoder. Ele é normalmente aberto. Se usarmos um resistor de pull-up nesse pino, o pino SW ficará HIGH quando o botão não estiver pressionado e LOW quando estiver pressionado.
  • Pino VCC (+): precisa ser conectado ao VCC (entre 3,3 e 5 volts)
  • Pino GND: precisa ser conectado ao GND (0V)

Encoder Rotativo vs Potenciômetro

Você pode confundir o encoder rotativo com o potenciômetro, mas essas são peças diferentes. Veja uma comparação entre eles:

  • O encoder rotativo pode ser visto como a versão moderna de um potenciômetro, mas oferece mais recursos.
  • O encoder rotativo pode girar completamente sem parar, enquanto o potenciômetro só consegue girar cerca de três quartos de volta.
  • O encoder rotativo emite pulsos, enquanto o potenciômetro produz tensão analógica.
  • Quando você só precisa saber quanto o botão se moveu, sem identificar sua posição exata, o encoder rotativo é conveniente. Por outro lado, o potenciômetro é valioso quando você precisa saber com precisão a posição de um botão.

Como o Encoder Rotativo Funciona

rotary encoder output

Dentro do encoder, há um disco com ranhuras conectado a um pino chamado C, que funciona como um terra compartilhado. Há mais dois pinos, A e B.

  • Quando você gira o botão, os pinos A e B tocam o pino C do terra compartilhado, mas em uma certa ordem, dependendo do lado para o qual você gira o botão (sentido horário ou anti-horário).
  • Esses toques criam dois sinais. Eles são um pouco diferentes no tempo, porque um pino toca o terra antes do outro. Os dois sinais estão defasados em 90 graus um do outro. Isso é chamado de codificação em quadratura.
  • Quando você gira o botão no sentido horário, o pino A toca o terra antes do pino B. Quando você gira o botão no sentido anti-horário, o pino B toca o terra antes do pino A.
  • Monitorando quando cada pino toca ou sai do terra, podemos descobrir para que lado o botão está girando. Fazemos isso verificando o que acontece com o pino B quando o pino A muda.
How rotary encoder works

Quando A muda de estado de LOW para HIGH:

  • Se B está LOW, o botão foi girado no sentido horário.
  • Se B está HIGH, o botão foi girado no sentido anti-horário.

※ Nota:

Os pinos A e B estão conectados aos pinos CLK e DT. No entanto, dependendo dos fabricantes, a ordem pode ser diferente. Os códigos fornecidos abaixo foram testados com o encoder rotativo da DIYables

Como Programar o Encoder Rotativo

  • Verifique o sinal do pino CLK
  • Se o estado mudar de LOW para HIGH, verifique o estado do pino DT.
    • Se o estado do pino DT for HIGH, o botão foi girado no sentido anti-horário, aumente o contador em 1
    • Se o estado do pino DT for LOW, o botão foi girado no sentido horário, diminua o contador em 1

Diagrama de Ligação

The wiring diagram between Arduino Nano and rotary encoder

This image is created using Fritzing. Click to enlarge image

Veja A melhor forma de alimentar o Arduino Nano e outros componentes.

Código Arduino Nano – Encoder Rotativo

O código Arduino Nano abaixo faz o seguinte:

  • Detecta a direção e a quantidade de rotação do encoder.
    • Se detectar que o botão foi girado em um clique (detent) no sentido horário, aumenta o contador em um.
    • Se detectar que o botão foi girado em um clique (detent) no sentido anti-horário, diminui o contador em um.
  • Detecta se o botão está pressionado.
/* * Este código de Arduino Nano foi desenvolvido por pt.newbiely.com * Este código de Arduino Nano é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-nano/arduino-nano-rotary-encoder */ #include <ezButton.h> // The library to use for SW pin #define CLK_PIN 2 #define DT_PIN 3 #define SW_PIN 4 #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // anticlockwise direction int counter = 0; int direction = DIRECTION_CW; int CLK_state; int prev_CLK_state; ezButton button(SW_PIN); void setup() { Serial.begin(9600); // Configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // read the initial state of the rotary encoder's CLK pin prev_CLK_state = digitalRead(CLK_PIN); } void loop() { button.loop(); // MUST call the loop() function first // read the current state of the rotary encoder's CLK pin CLK_state = digitalRead(CLK_PIN); // If the state of CLK is changed, then pulse occurred // React to only the rising edge (from LOW to HIGH) to avoid double count if (CLK_state != prev_CLK_state && CLK_state == HIGH) { // if the DT state is HIGH // The encoder is rotating in anticlockwise direction => decrease the counter if (digitalRead(DT_PIN) == HIGH) { counter--; direction = DIRECTION_CCW; } else { // The encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } Serial.print("Twisted direction: "); if (direction == DIRECTION_CW) Serial.print("CLOCKWISE"); else Serial.print("ANTICLOCKWISE"); Serial.print(" - counter: "); Serial.println(counter); } // save last CLK state prev_CLK_state = CLK_state; if (button.isPressed()) { Serial.println("The button is pressed"); } }

Para simplificar o código de debounce do botão, a biblioteca ezButton é usada.

Passos Rápidos

  • Instale a biblioteca ezButton na Arduino IDE. Veja Como Fazer
  • Copie o código acima e abra com a Arduino IDE
  • Clique no botão Upload na Arduino IDE para fazer upload do código para o Arduino Nano
  • Gire o botão no sentido horário e depois no sentido anti-horário
  • Pressione o botão
  • Confira o resultado no Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Nano
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano' on 'COM15')
New Line
9600 baud
Twisted direction: CLOCKWISE - counter: 1 Twisted direction: CLOCKWISE - counter: 2 Twisted direction: CLOCKWISE - counter: 3 Twisted direction: CLOCKWISE - counter: 4 Twisted direction: CLOCKWISE - counter: 5 Twisted direction: ANTICLOCKWISE - counter: 4 Twisted direction: ANTICLOCKWISE - counter: 3 Twisted direction: ANTICLOCKWISE - counter: 2 Twisted direction: ANTICLOCKWISE - counter: 1 Twisted direction: ANTICLOCKWISE - counter: 0 The button is pressed
Ln 11, Col 1
Arduino Nano on COM15
2

Explicação do Código

Confira os comentários linha por linha no código

Código Arduino Nano – Encoder Rotativo com Interrupção

No exemplo de código anterior, usamos o método de polling, que verifica continuamente o estado do pino. Isso tem duas desvantagens:

  • Desperdiça recursos do Arduino Nano
  • Alguns contadores podem ser perdidos se outro código demorar para executar.

Uma maneira de lidar com isso é usar interrupções. As interrupções eliminam a necessidade de verificar constantemente um determinado evento. Isso permite que o Arduino Nano execute outras tarefas sem perder um evento.

Aqui está um exemplo de como ler um encoder rotativo com interrupções.

/* * Este código de Arduino Nano foi desenvolvido por pt.newbiely.com * Este código de Arduino Nano é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-nano/arduino-nano-rotary-encoder */ #include <ezButton.h> // The library to use for SW pin #define CLK_PIN 2 // The Arduino Nano pin D2 connect to the pin CLK of the rotary encoder #define DT_PIN 3 // The Arduino Nano pin D3 connect to the pin DT of the rotary encoder #define SW_PIN 4 // The Arduino Nano pin D4 connect to the pin SW of the rotary encoder #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // anticlockwise direction volatile int counter = 0; volatile int direction = DIRECTION_CW; volatile unsigned long last_time; // for debouncing int prev_counter; ezButton button(SW_PIN); void INTERRUPT_handler() { if ((millis() - last_time) < 50) // debounce time is 10ms return; if (digitalRead(DT_PIN) == HIGH) { // The encoder is rotating in anticlockwise direction => decrease the counter counter--; direction = DIRECTION_CCW; } else { // The encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } last_time = millis(); } void setup() { Serial.begin(9600); // Configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // use interrupt for CLK pin is enough // call INTERRUPT_handler() when CLK pin changes from LOW to HIGH attachInterrupt(digitalPinToInterrupt(CLK_PIN), INTERRUPT_handler, RISING); } void loop() { button.loop(); // MUST call the loop() function first if (prev_counter != counter) { Serial.print("Twisted direction: "); if (direction == DIRECTION_CW) Serial.print("CLOCKWISE"); else Serial.print("ANTICLOCKWISE"); Serial.print(" - counter: "); Serial.println(counter); prev_counter = counter; } if (button.isPressed()) { Serial.println("The button is pressed"); } // TO DO: your other work here }

Agora, ao girar o botão, você verá informações aparecendo no Serial Monitor, bem parecidas com as que você viu no código anterior.

※ Nota:

  • Se você usar a interrupção, precisa conectar o pino CLK do encoder a um pino do Arduino Nano que suporte interrupções. Mas lembre-se: nem todos os pinos do Arduino Nano conseguem fazer isso. Por exemplo, no Arduino Nano, somente os pinos 2 e 3 funcionam com interrupções.
  • Você pode encontrar tutoriais em outros sites que usam duas interrupções para um único encoder, mas isso é desnecessário e um desperdício. Apenas uma interrupção é suficiente.
  • É importante usar a palavra-chave volatile nas variáveis globais usadas na interrupção. Ignorar isso pode causar problemas inesperados.
  • Mantenha o código dentro da interrupção o mais simples possível. Evite usar Serial.print() ou Serial.println() dentro da interrupção.

Aplicações do Encoder Rotativo com Arduino Nano

Com o Encoder Rotativo, podemos fazer as seguintes aplicações, mas não só:

  • Arduino Nano - Encoder Rotativo controla a Posição de um Servo Motor
  • Arduino Nano - Encoder Rotativo controla o Brilho de um LED
  • Arduino Nano - Encoder Rotativo controla a Velocidade de um Motor de Passo

Vídeo

Referências de Funções

Tutoriais Relacionados

※ NOSSAS MENSAGENS

  • Fique à vontade para compartilhar o link deste tutorial. Porém, por favor, não use nosso conteúdo em outros sites. Investimos muito esforço e tempo para criar este conteúdo, por favor respeite nosso trabalho!